GNU Binutils with patches for OS216
修訂 | 9c893427353580b909059d1d6655fff139d548e9 (tree) |
---|---|
時間 | 2019-06-05 07:30:03 |
作者 | Pedro Alves <palves@redh...> |
Commiter | Pedro Alves |
Make "backtrace" support -OPT options
This adds support for comand options to the "backtrace" command. We'll get:
(gdb) help backtrace
Print backtrace of all stack frames, or innermost COUNT frames.
Usage: backtrace [OPTION]... [QUALIFIER]... [COUNT | -COUNT]
Options:
For backward compatibility, the following qualifiers are supported:
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:
yyyy-mm-dd 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:
yyyy-mm-dd Pedro Alves <palves@redhat.com>
* gdb.base/options.exp (test-backtrace): New.
(top level): Call it.
@@ -42,6 +42,7 @@ | ||
42 | 42 | #include "tracepoint.h" |
43 | 43 | #include "hashtab.h" |
44 | 44 | #include "valprint.h" |
45 | +#include "cli/cli-option.h" | |
45 | 46 | |
46 | 47 | /* The sentinel frame terminates the innermost end of the frame chain. |
47 | 48 | If unwound, it returns the information needed to construct an |
@@ -52,6 +53,9 @@ | ||
52 | 53 | |
53 | 54 | static struct frame_info *sentinel_frame; |
54 | 55 | |
56 | +/* The values behind the global "set backtrace ..." settings. */ | |
57 | +set_backtrace_options user_set_backtrace_options; | |
58 | + | |
55 | 59 | static struct frame_info *get_prev_frame_raw (struct frame_info *this_frame); |
56 | 60 | static const char *frame_stop_reason_symbol_string (enum unwind_stop_reason reason); |
57 | 61 |
@@ -295,9 +299,8 @@ show_frame_debug (struct ui_file *file, int from_tty, | ||
295 | 299 | fprintf_filtered (file, _("Frame debugging is %s.\n"), value); |
296 | 300 | } |
297 | 301 | |
298 | -/* Flag to indicate whether backtraces should stop at main et.al. */ | |
302 | +/* Implementation of "show backtrace past-main". */ | |
299 | 303 | |
300 | -static int backtrace_past_main; | |
301 | 304 | static void |
302 | 305 | show_backtrace_past_main (struct ui_file *file, int from_tty, |
303 | 306 | struct cmd_list_element *c, const char *value) |
@@ -308,7 +311,8 @@ show_backtrace_past_main (struct ui_file *file, int from_tty, | ||
308 | 311 | value); |
309 | 312 | } |
310 | 313 | |
311 | -static int backtrace_past_entry; | |
314 | +/* Implementation of "show backtrace past-entry". */ | |
315 | + | |
312 | 316 | static void |
313 | 317 | show_backtrace_past_entry (struct ui_file *file, int from_tty, |
314 | 318 | struct cmd_list_element *c, const char *value) |
@@ -318,7 +322,8 @@ show_backtrace_past_entry (struct ui_file *file, int from_tty, | ||
318 | 322 | value); |
319 | 323 | } |
320 | 324 | |
321 | -static unsigned int backtrace_limit = UINT_MAX; | |
325 | +/* Implementation of "show backtrace limit". */ | |
326 | + | |
322 | 327 | static void |
323 | 328 | show_backtrace_limit (struct ui_file *file, int from_tty, |
324 | 329 | struct cmd_list_element *c, const char *value) |
@@ -2276,7 +2281,7 @@ get_prev_frame (struct frame_info *this_frame) | ||
2276 | 2281 | point inside the main function. */ |
2277 | 2282 | if (this_frame->level >= 0 |
2278 | 2283 | && get_frame_type (this_frame) == NORMAL_FRAME |
2279 | - && !backtrace_past_main | |
2284 | + && !user_set_backtrace_options.backtrace_past_main | |
2280 | 2285 | && frame_pc_p |
2281 | 2286 | && inside_main_func (this_frame)) |
2282 | 2287 | /* Don't unwind past main(). Note, this is done _before_ the |
@@ -2293,7 +2298,7 @@ get_prev_frame (struct frame_info *this_frame) | ||
2293 | 2298 | being 1-based and the level being 0-based, and the other accounts for |
2294 | 2299 | the level of the new frame instead of the level of the current |
2295 | 2300 | frame. */ |
2296 | - if (this_frame->level + 2 > backtrace_limit) | |
2301 | + if (this_frame->level + 2 > user_set_backtrace_options.backtrace_limit) | |
2297 | 2302 | { |
2298 | 2303 | frame_debug_got_null_frame (this_frame, "backtrace limit exceeded"); |
2299 | 2304 | return NULL; |
@@ -2323,7 +2328,7 @@ get_prev_frame (struct frame_info *this_frame) | ||
2323 | 2328 | application. */ |
2324 | 2329 | if (this_frame->level >= 0 |
2325 | 2330 | && get_frame_type (this_frame) == NORMAL_FRAME |
2326 | - && !backtrace_past_entry | |
2331 | + && !user_set_backtrace_options.backtrace_past_entry | |
2327 | 2332 | && frame_pc_p |
2328 | 2333 | && inside_entry_func (this_frame)) |
2329 | 2334 | { |
@@ -2896,6 +2901,39 @@ show_backtrace_cmd (const char *args, int from_tty) | ||
2896 | 2901 | cmd_show_list (show_backtrace_cmdlist, from_tty, ""); |
2897 | 2902 | } |
2898 | 2903 | |
2904 | +/* Definition of the "set backtrace" settings that are exposed as | |
2905 | + "backtrace" command options. */ | |
2906 | + | |
2907 | +using boolean_option_def | |
2908 | + = gdb::option::boolean_option_def<set_backtrace_options>; | |
2909 | +using uinteger_option_def | |
2910 | + = gdb::option::uinteger_option_def<set_backtrace_options>; | |
2911 | + | |
2912 | +const gdb::option::option_def set_backtrace_option_defs[] = { | |
2913 | + | |
2914 | + boolean_option_def { | |
2915 | + "past-main", | |
2916 | + [] (set_backtrace_options *opt) { return &opt->backtrace_past_main; }, | |
2917 | + show_backtrace_past_main, /* show_cmd_cb */ | |
2918 | + N_("Set whether backtraces should continue past \"main\"."), | |
2919 | + N_("Show whether backtraces should continue past \"main\"."), | |
2920 | + N_("Normally the caller of \"main\" is not of interest, so GDB will terminate\n\ | |
2921 | +the backtrace at \"main\". Set this if you need to see the rest\n\ | |
2922 | +of the stack trace."), | |
2923 | + }, | |
2924 | + | |
2925 | + boolean_option_def { | |
2926 | + "past-entry", | |
2927 | + [] (set_backtrace_options *opt) { return &opt->backtrace_past_entry; }, | |
2928 | + show_backtrace_past_entry, /* show_cmd_cb */ | |
2929 | + N_("Set whether backtraces should continue past the entry point of a program."), | |
2930 | + N_("Show whether backtraces should continue past the entry point of a program."), | |
2931 | + N_("Normally there are no callers beyond the entry point of a program, so GDB\n\ | |
2932 | +will terminate the backtrace there. Set this if you need to see\n\ | |
2933 | +the rest of the stack trace."), | |
2934 | + }, | |
2935 | +}; | |
2936 | + | |
2899 | 2937 | void |
2900 | 2938 | _initialize_frame (void) |
2901 | 2939 | { |
@@ -2916,34 +2954,8 @@ Show backtrace variables such as the backtrace limit"), | ||
2916 | 2954 | &show_backtrace_cmdlist, "show backtrace ", |
2917 | 2955 | 0/*allow-unknown*/, &showlist); |
2918 | 2956 | |
2919 | - add_setshow_boolean_cmd ("past-main", class_obscure, | |
2920 | - &backtrace_past_main, _("\ | |
2921 | -Set whether backtraces should continue past \"main\"."), _("\ | |
2922 | -Show whether backtraces should continue past \"main\"."), _("\ | |
2923 | -Normally the caller of \"main\" is not of interest, so GDB will terminate\n\ | |
2924 | -the backtrace at \"main\". Set this variable if you need to see the rest\n\ | |
2925 | -of the stack trace."), | |
2926 | - NULL, | |
2927 | - show_backtrace_past_main, | |
2928 | - &set_backtrace_cmdlist, | |
2929 | - &show_backtrace_cmdlist); | |
2930 | - | |
2931 | - add_setshow_boolean_cmd ("past-entry", class_obscure, | |
2932 | - &backtrace_past_entry, _("\ | |
2933 | -Set whether backtraces should continue past the entry point of a program."), | |
2934 | - _("\ | |
2935 | -Show whether backtraces should continue past the entry point of a program."), | |
2936 | - _("\ | |
2937 | -Normally there are no callers beyond the entry point of a program, so GDB\n\ | |
2938 | -will terminate the backtrace there. Set this variable if you need to see\n\ | |
2939 | -the rest of the stack trace."), | |
2940 | - NULL, | |
2941 | - show_backtrace_past_entry, | |
2942 | - &set_backtrace_cmdlist, | |
2943 | - &show_backtrace_cmdlist); | |
2944 | - | |
2945 | 2957 | add_setshow_uinteger_cmd ("limit", class_obscure, |
2946 | - &backtrace_limit, _("\ | |
2958 | + &user_set_backtrace_options.backtrace_limit, _("\ | |
2947 | 2959 | Set an upper bound on the number of backtrace levels."), _("\ |
2948 | 2960 | Show the upper bound on the number of backtrace levels."), _("\ |
2949 | 2961 | 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."), | ||
2953 | 2965 | &set_backtrace_cmdlist, |
2954 | 2966 | &show_backtrace_cmdlist); |
2955 | 2967 | |
2968 | + gdb::option::add_setshow_cmds_for_options | |
2969 | + (class_stack, &user_set_backtrace_options, | |
2970 | + set_backtrace_option_defs, &set_backtrace_cmdlist, &show_backtrace_cmdlist); | |
2971 | + | |
2956 | 2972 | /* Debug this files internals. */ |
2957 | 2973 | add_setshow_zuinteger_cmd ("frame", class_maintenance, &frame_debug, _("\ |
2958 | 2974 | Set frame debugging."), _("\ |
@@ -70,6 +70,7 @@ | ||
70 | 70 | */ |
71 | 71 | |
72 | 72 | #include "language.h" |
73 | +#include "cli/cli-option.h" | |
73 | 74 | |
74 | 75 | struct symtab_and_line; |
75 | 76 | struct frame_unwind; |
@@ -78,6 +79,7 @@ struct block; | ||
78 | 79 | struct gdbarch; |
79 | 80 | struct ui_file; |
80 | 81 | struct ui_out; |
82 | +struct frame_print_options; | |
81 | 83 | |
82 | 84 | /* Status of a given frame's stack. */ |
83 | 85 |
@@ -753,7 +755,8 @@ extern void print_stack_frame (struct frame_info *, int print_level, | ||
753 | 755 | enum print_what print_what, |
754 | 756 | int set_current_sal); |
755 | 757 | |
756 | -extern void print_frame_info (struct frame_info *, int print_level, | |
758 | +extern void print_frame_info (const frame_print_options &fp_opts, | |
759 | + struct frame_info *, int print_level, | |
757 | 760 | enum print_what print_what, int args, |
758 | 761 | int set_current_sal); |
759 | 762 |
@@ -764,6 +767,12 @@ extern int deprecated_frame_register_read (struct frame_info *frame, int regnum, | ||
764 | 767 | |
765 | 768 | /* From stack.c. */ |
766 | 769 | |
770 | +/* The possible choices of "set print frame-arguments". */ | |
771 | +extern const char print_frame_arguments_all[]; | |
772 | +extern const char print_frame_arguments_scalars[]; | |
773 | +extern const char print_frame_arguments_none[]; | |
774 | + | |
775 | +/* The possible choices of "set print entry-values". */ | |
767 | 776 | extern const char print_entry_values_no[]; |
768 | 777 | extern const char print_entry_values_only[]; |
769 | 778 | extern const char print_entry_values_preferred[]; |
@@ -771,7 +780,22 @@ extern const char print_entry_values_if_needed[]; | ||
771 | 780 | extern const char print_entry_values_both[]; |
772 | 781 | extern const char print_entry_values_compact[]; |
773 | 782 | extern const char print_entry_values_default[]; |
774 | -extern const char *print_entry_values; | |
783 | + | |
784 | +/* Data for the frame-printing "set print" settings exposed as command | |
785 | + options. */ | |
786 | + | |
787 | +struct frame_print_options | |
788 | +{ | |
789 | + const char *print_frame_arguments = print_frame_arguments_scalars; | |
790 | + const char *print_entry_values = print_entry_values_default; | |
791 | + | |
792 | + /* If non-zero, don't invoke pretty-printers for frame | |
793 | + arguments. */ | |
794 | + int print_raw_frame_arguments; | |
795 | +}; | |
796 | + | |
797 | +/* The values behind the global "set print ..." settings. */ | |
798 | +extern frame_print_options user_frame_print_options; | |
775 | 799 | |
776 | 800 | /* Inferior function parameter value read in from a frame. */ |
777 | 801 |
@@ -800,7 +824,8 @@ struct frame_arg | ||
800 | 824 | const char *entry_kind; |
801 | 825 | }; |
802 | 826 | |
803 | -extern void read_frame_arg (struct symbol *sym, struct frame_info *frame, | |
827 | +extern void read_frame_arg (const frame_print_options &fp_opts, | |
828 | + symbol *sym, frame_info *frame, | |
804 | 829 | struct frame_arg *argp, |
805 | 830 | struct frame_arg *entryargp); |
806 | 831 | extern void read_frame_local (struct symbol *sym, struct frame_info *frame, |
@@ -881,4 +906,28 @@ extern struct frame_info *skip_tailcall_frames (struct frame_info *frame); | ||
881 | 906 | |
882 | 907 | extern struct frame_info *skip_unwritable_frames (struct frame_info *frame); |
883 | 908 | |
909 | +/* Data for the "set backtrace" settings. */ | |
910 | + | |
911 | +struct set_backtrace_options | |
912 | +{ | |
913 | + /* Flag to indicate whether backtraces should continue past | |
914 | + main. */ | |
915 | + int backtrace_past_main = 0; | |
916 | + | |
917 | + /* Flag to indicate whether backtraces should continue past | |
918 | + entry. */ | |
919 | + int backtrace_past_entry = 0; | |
920 | + | |
921 | + /* Upper bound on the number of backtrace levels. Note this is not | |
922 | + exposed as a command option, because "backtrace" and "frame | |
923 | + apply" already have other means to set a frame count limit. */ | |
924 | + unsigned int backtrace_limit = UINT_MAX; | |
925 | +}; | |
926 | + | |
927 | +/* The corresponding option definitions. */ | |
928 | +extern const gdb::option::option_def set_backtrace_option_defs[2]; | |
929 | + | |
930 | +/* The values behind the global "set backtrace ..." settings. */ | |
931 | +extern set_backtrace_options user_set_backtrace_options; | |
932 | + | |
884 | 933 | #endif /* !defined (FRAME_H) */ |
@@ -39,7 +39,8 @@ | ||
39 | 39 | |
40 | 40 | enum what_to_list { locals, arguments, all }; |
41 | 41 | |
42 | -static void list_args_or_locals (enum what_to_list what, | |
42 | +static void list_args_or_locals (const frame_print_options &fp_opts, | |
43 | + enum what_to_list what, | |
43 | 44 | enum print_values values, |
44 | 45 | struct frame_info *fi, |
45 | 46 | int skip_unavailable); |
@@ -175,7 +176,8 @@ mi_cmd_stack_list_frames (const char *command, char **argv, int argc) | ||
175 | 176 | QUIT; |
176 | 177 | /* Print the location and the address always, even for level 0. |
177 | 178 | If args is 0, don't print the arguments. */ |
178 | - print_frame_info (fi, 1, LOC_AND_ADDRESS, 0 /* args */, 0); | |
179 | + print_frame_info (user_frame_print_options, | |
180 | + fi, 1, LOC_AND_ADDRESS, 0 /* args */, 0); | |
179 | 181 | } |
180 | 182 | } |
181 | 183 | } |
@@ -275,7 +277,8 @@ mi_cmd_stack_list_locals (const char *command, char **argv, int argc) | ||
275 | 277 | if "--no-frame-filters" has been specified from the command. */ |
276 | 278 | if (! frame_filters || raw_arg || result == EXT_LANG_BT_NO_FILTERS) |
277 | 279 | { |
278 | - list_args_or_locals (locals, print_value, frame, | |
280 | + list_args_or_locals (user_frame_print_options, | |
281 | + locals, print_value, frame, | |
279 | 282 | skip_unavailable); |
280 | 283 | } |
281 | 284 | } |
@@ -389,7 +392,8 @@ mi_cmd_stack_list_args (const char *command, char **argv, int argc) | ||
389 | 392 | QUIT; |
390 | 393 | ui_out_emit_tuple tuple_emitter (uiout, "frame"); |
391 | 394 | uiout->field_int ("level", i); |
392 | - list_args_or_locals (arguments, print_values, fi, skip_unavailable); | |
395 | + list_args_or_locals (user_frame_print_options, | |
396 | + arguments, print_values, fi, skip_unavailable); | |
393 | 397 | } |
394 | 398 | } |
395 | 399 | } |
@@ -465,7 +469,8 @@ mi_cmd_stack_list_variables (const char *command, char **argv, int argc) | ||
465 | 469 | if "--no-frame-filters" has been specified from the command. */ |
466 | 470 | if (! frame_filters || raw_arg || result == EXT_LANG_BT_NO_FILTERS) |
467 | 471 | { |
468 | - list_args_or_locals (all, print_value, frame, | |
472 | + list_args_or_locals (user_frame_print_options, | |
473 | + all, print_value, frame, | |
469 | 474 | skip_unavailable); |
470 | 475 | } |
471 | 476 | } |
@@ -557,7 +562,8 @@ list_arg_or_local (const struct frame_arg *arg, enum what_to_list what, | ||
557 | 562 | are available. */ |
558 | 563 | |
559 | 564 | static void |
560 | -list_args_or_locals (enum what_to_list what, enum print_values values, | |
565 | +list_args_or_locals (const frame_print_options &fp_opts, | |
566 | + enum what_to_list what, enum print_values values, | |
561 | 567 | struct frame_info *fi, int skip_unavailable) |
562 | 568 | { |
563 | 569 | const struct block *block; |
@@ -652,7 +658,7 @@ list_args_or_locals (enum what_to_list what, enum print_values values, | ||
652 | 658 | { |
653 | 659 | case PRINT_ALL_VALUES: |
654 | 660 | if (SYMBOL_IS_ARGUMENT (sym)) |
655 | - read_frame_arg (sym2, fi, &arg, &entryarg); | |
661 | + read_frame_arg (fp_opts, sym2, fi, &arg, &entryarg); | |
656 | 662 | else |
657 | 663 | read_frame_local (sym2, fi, &arg); |
658 | 664 | } |
@@ -764,5 +770,6 @@ mi_cmd_stack_info_frame (const char *command, char **argv, int argc) | ||
764 | 770 | if (argc > 0) |
765 | 771 | error (_("-stack-info-frame: No arguments allowed")); |
766 | 772 | |
767 | - print_frame_info (get_selected_frame (NULL), 1, LOC_AND_ADDRESS, 0, 1); | |
773 | + print_frame_info (user_frame_print_options, | |
774 | + get_selected_frame (NULL), 1, LOC_AND_ADDRESS, 0, 1); | |
768 | 775 | } |
@@ -481,7 +481,8 @@ enumerate_args (PyObject *iter, | ||
481 | 481 | return EXT_LANG_BT_ERROR; |
482 | 482 | } |
483 | 483 | |
484 | - read_frame_arg (sym, frame, &arg, &entryarg); | |
484 | + read_frame_arg (user_frame_print_options, | |
485 | + sym, frame, &arg, &entryarg); | |
485 | 486 | |
486 | 487 | gdb::unique_xmalloc_ptr<char> arg_holder (arg.error); |
487 | 488 | gdb::unique_xmalloc_ptr<char> entry_holder (entryarg.error); |
@@ -52,16 +52,22 @@ | ||
52 | 52 | #include "extension.h" |
53 | 53 | #include "observable.h" |
54 | 54 | #include "common/def-vector.h" |
55 | +#include "cli/cli-option.h" | |
55 | 56 | |
56 | 57 | /* The possible choices of "set print frame-arguments", and the value |
57 | 58 | of this setting. */ |
58 | 59 | |
59 | -static const char *const print_frame_arguments_choices[] = | |
60 | - {"all", "scalars", "none", NULL}; | |
61 | -static const char *print_frame_arguments = "scalars"; | |
60 | +const char print_frame_arguments_all[] = "all"; | |
61 | +const char print_frame_arguments_scalars[] = "scalars"; | |
62 | +const char print_frame_arguments_none[] = "none"; | |
62 | 63 | |
63 | -/* If non-zero, don't invoke pretty-printers for frame arguments. */ | |
64 | -static int print_raw_frame_arguments; | |
64 | +static const char *const print_frame_arguments_choices[] = | |
65 | +{ | |
66 | + print_frame_arguments_all, | |
67 | + print_frame_arguments_scalars, | |
68 | + print_frame_arguments_none, | |
69 | + NULL | |
70 | +}; | |
65 | 71 | |
66 | 72 | /* The possible choices of "set print entry-values", and the value |
67 | 73 | of this setting. */ |
@@ -84,7 +90,85 @@ static const char *const print_entry_values_choices[] = | ||
84 | 90 | print_entry_values_default, |
85 | 91 | NULL |
86 | 92 | }; |
87 | -const char *print_entry_values = print_entry_values_default; | |
93 | + | |
94 | +/* See frame.h. */ | |
95 | +frame_print_options user_frame_print_options; | |
96 | + | |
97 | +/* Option definitions for some frame-related "set print ..." | |
98 | + settings. */ | |
99 | + | |
100 | +using boolean_option_def | |
101 | + = gdb::option::boolean_option_def<frame_print_options>; | |
102 | +using enum_option_def | |
103 | + = gdb::option::enum_option_def<frame_print_options>; | |
104 | + | |
105 | +static const gdb::option::option_def frame_print_option_defs[] = { | |
106 | + | |
107 | + enum_option_def { | |
108 | + "entry-values", | |
109 | + print_entry_values_choices, | |
110 | + [] (frame_print_options *opt) { return &opt->print_entry_values; }, | |
111 | + NULL, /* show_cmd_cb */ | |
112 | + N_("Set printing of function arguments at function entry"), | |
113 | + N_("Show printing of function arguments at function entry"), | |
114 | + N_("GDB can sometimes determine the values of function arguments at entry,\n\ | |
115 | +in addition to their current values. This option tells GDB whether\n\ | |
116 | +to print the current value, the value at entry (marked as val@entry),\n\ | |
117 | +or both. Note that one or both of these values may be <optimized out>."), | |
118 | + }, | |
119 | + | |
120 | + enum_option_def { | |
121 | + "frame-arguments", | |
122 | + print_frame_arguments_choices, | |
123 | + [] (frame_print_options *opt) { return &opt->print_frame_arguments; }, | |
124 | + NULL, /* show_cmd_cb */ | |
125 | + N_("Set printing of non-scalar frame arguments"), | |
126 | + N_("Show printing of non-scalar frame arguments"), | |
127 | + NULL /* help_doc */ | |
128 | + }, | |
129 | + | |
130 | + boolean_option_def { | |
131 | + "raw-frame-arguments", | |
132 | + [] (frame_print_options *opt) { return &opt->print_raw_frame_arguments; }, | |
133 | + NULL, /* show_cmd_cb */ | |
134 | + N_("Set whether to print frame arguments in raw form."), | |
135 | + N_("Show whether to print frame arguments in raw form."), | |
136 | + N_("If set, frame arguments are printed in raw form, bypassing any\n\ | |
137 | +pretty-printers for that value.") | |
138 | + }, | |
139 | +}; | |
140 | + | |
141 | +/* Options for the "backtrace" command. */ | |
142 | + | |
143 | +struct backtrace_cmd_options | |
144 | +{ | |
145 | + int full = 0; | |
146 | + int no_filters = 0; | |
147 | + int hide = 0; | |
148 | +}; | |
149 | + | |
150 | +using bt_flag_option_def | |
151 | + = gdb::option::flag_option_def<backtrace_cmd_options>; | |
152 | + | |
153 | +static const gdb::option::option_def backtrace_command_option_defs[] = { | |
154 | + bt_flag_option_def { | |
155 | + "full", | |
156 | + [] (backtrace_cmd_options *opt) { return &opt->full; }, | |
157 | + N_("Print values of local variables.") | |
158 | + }, | |
159 | + | |
160 | + bt_flag_option_def { | |
161 | + "no-filters", | |
162 | + [] (backtrace_cmd_options *opt) { return &opt->no_filters; }, | |
163 | + N_("Prohibit frame filters from executing on a backtrace."), | |
164 | + }, | |
165 | + | |
166 | + bt_flag_option_def { | |
167 | + "hide", | |
168 | + [] (backtrace_cmd_options *opt) { return &opt->hide; }, | |
169 | + N_("Causes Python frame filter elided frames to not be printed."), | |
170 | + }, | |
171 | +}; | |
88 | 172 | |
89 | 173 | /* Prototypes for local functions. */ |
90 | 174 |
@@ -93,7 +177,8 @@ static void print_frame_local_vars (struct frame_info *frame, | ||
93 | 177 | const char *regexp, const char *t_regexp, |
94 | 178 | int num_tabs, struct ui_file *stream); |
95 | 179 | |
96 | -static void print_frame (struct frame_info *frame, int print_level, | |
180 | +static void print_frame (const frame_print_options &opts, | |
181 | + frame_info *frame, int print_level, | |
97 | 182 | enum print_what print_what, int print_args, |
98 | 183 | struct symtab_and_line sal); |
99 | 184 |
@@ -177,7 +262,8 @@ print_stack_frame (struct frame_info *frame, int print_level, | ||
177 | 262 | |
178 | 263 | try |
179 | 264 | { |
180 | - print_frame_info (frame, print_level, print_what, 1 /* print_args */, | |
265 | + print_frame_info (user_frame_print_options, | |
266 | + frame, print_level, print_what, 1 /* print_args */, | |
181 | 267 | set_current_sal); |
182 | 268 | if (set_current_sal) |
183 | 269 | set_current_sal_from_frame (frame); |
@@ -225,7 +311,8 @@ print_frame_nameless_args (struct frame_info *frame, long start, int num, | ||
225 | 311 | iff it should not be printed accoring to user settings. */ |
226 | 312 | |
227 | 313 | static void |
228 | -print_frame_arg (const struct frame_arg *arg) | |
314 | +print_frame_arg (const frame_print_options &fp_opts, | |
315 | + const struct frame_arg *arg) | |
229 | 316 | { |
230 | 317 | struct ui_out *uiout = current_uiout; |
231 | 318 |
@@ -269,7 +356,7 @@ print_frame_arg (const struct frame_arg *arg) | ||
269 | 356 | try |
270 | 357 | { |
271 | 358 | const struct language_defn *language; |
272 | - struct value_print_options opts; | |
359 | + struct value_print_options vp_opts; | |
273 | 360 | |
274 | 361 | /* Avoid value_print because it will deref ref parameters. We |
275 | 362 | just want to print their addresses. Print ??? for args whose |
@@ -286,14 +373,15 @@ print_frame_arg (const struct frame_arg *arg) | ||
286 | 373 | else |
287 | 374 | language = current_language; |
288 | 375 | |
289 | - get_no_prettyformat_print_options (&opts); | |
290 | - opts.deref_ref = 1; | |
291 | - opts.raw = print_raw_frame_arguments; | |
376 | + get_no_prettyformat_print_options (&vp_opts); | |
377 | + vp_opts.deref_ref = 1; | |
378 | + vp_opts.raw = fp_opts.print_raw_frame_arguments; | |
292 | 379 | |
293 | 380 | /* True in "summary" mode, false otherwise. */ |
294 | - opts.summary = !strcmp (print_frame_arguments, "scalars"); | |
381 | + vp_opts.summary | |
382 | + = fp_opts.print_frame_arguments == print_frame_arguments_scalars; | |
295 | 383 | |
296 | - common_val_print (arg->val, &stb, 2, &opts, language); | |
384 | + common_val_print (arg->val, &stb, 2, &vp_opts, language); | |
297 | 385 | } |
298 | 386 | catch (const gdb_exception_error &except) |
299 | 387 | { |
@@ -333,15 +421,16 @@ read_frame_local (struct symbol *sym, struct frame_info *frame, | ||
333 | 421 | exception. */ |
334 | 422 | |
335 | 423 | void |
336 | -read_frame_arg (struct symbol *sym, struct frame_info *frame, | |
424 | +read_frame_arg (const frame_print_options &fp_opts, | |
425 | + symbol *sym, frame_info *frame, | |
337 | 426 | struct frame_arg *argp, struct frame_arg *entryargp) |
338 | 427 | { |
339 | 428 | struct value *val = NULL, *entryval = NULL; |
340 | 429 | char *val_error = NULL, *entryval_error = NULL; |
341 | 430 | int val_equal = 0; |
342 | 431 | |
343 | - if (print_entry_values != print_entry_values_only | |
344 | - && print_entry_values != print_entry_values_preferred) | |
432 | + if (fp_opts.print_entry_values != print_entry_values_only | |
433 | + && fp_opts.print_entry_values != print_entry_values_preferred) | |
345 | 434 | { |
346 | 435 | try |
347 | 436 | { |
@@ -356,8 +445,8 @@ read_frame_arg (struct symbol *sym, struct frame_info *frame, | ||
356 | 445 | |
357 | 446 | if (SYMBOL_COMPUTED_OPS (sym) != NULL |
358 | 447 | && SYMBOL_COMPUTED_OPS (sym)->read_variable_at_entry != NULL |
359 | - && print_entry_values != print_entry_values_no | |
360 | - && (print_entry_values != print_entry_values_if_needed | |
448 | + && fp_opts.print_entry_values != print_entry_values_no | |
449 | + && (fp_opts.print_entry_values != print_entry_values_if_needed | |
361 | 450 | || !val || value_optimized_out (val))) |
362 | 451 | { |
363 | 452 | try |
@@ -379,8 +468,8 @@ read_frame_arg (struct symbol *sym, struct frame_info *frame, | ||
379 | 468 | if (entryval != NULL && value_optimized_out (entryval)) |
380 | 469 | entryval = NULL; |
381 | 470 | |
382 | - if (print_entry_values == print_entry_values_compact | |
383 | - || print_entry_values == print_entry_values_default) | |
471 | + if (fp_opts.print_entry_values == print_entry_values_compact | |
472 | + || fp_opts.print_entry_values == print_entry_values_default) | |
384 | 473 | { |
385 | 474 | /* For MI do not try to use print_entry_values_compact for ARGP. */ |
386 | 475 |
@@ -463,7 +552,7 @@ read_frame_arg (struct symbol *sym, struct frame_info *frame, | ||
463 | 552 | |
464 | 553 | if (entryval == NULL) |
465 | 554 | { |
466 | - if (print_entry_values == print_entry_values_preferred) | |
555 | + if (fp_opts.print_entry_values == print_entry_values_preferred) | |
467 | 556 | { |
468 | 557 | gdb_assert (val == NULL); |
469 | 558 |
@@ -477,18 +566,18 @@ read_frame_arg (struct symbol *sym, struct frame_info *frame, | ||
477 | 566 | strcpy (val_error, except.what ()); |
478 | 567 | } |
479 | 568 | } |
480 | - if (print_entry_values == print_entry_values_only | |
481 | - || print_entry_values == print_entry_values_both | |
482 | - || (print_entry_values == print_entry_values_preferred | |
569 | + if (fp_opts.print_entry_values == print_entry_values_only | |
570 | + || fp_opts.print_entry_values == print_entry_values_both | |
571 | + || (fp_opts.print_entry_values == print_entry_values_preferred | |
483 | 572 | && (!val || value_optimized_out (val)))) |
484 | 573 | { |
485 | 574 | entryval = allocate_optimized_out_value (SYMBOL_TYPE (sym)); |
486 | 575 | entryval_error = NULL; |
487 | 576 | } |
488 | 577 | } |
489 | - if ((print_entry_values == print_entry_values_compact | |
490 | - || print_entry_values == print_entry_values_if_needed | |
491 | - || print_entry_values == print_entry_values_preferred) | |
578 | + if ((fp_opts.print_entry_values == print_entry_values_compact | |
579 | + || fp_opts.print_entry_values == print_entry_values_if_needed | |
580 | + || fp_opts.print_entry_values == print_entry_values_preferred) | |
492 | 581 | && (!val || value_optimized_out (val)) && entryval != NULL) |
493 | 582 | { |
494 | 583 | val = NULL; |
@@ -500,8 +589,9 @@ read_frame_arg (struct symbol *sym, struct frame_info *frame, | ||
500 | 589 | argp->error = val_error ? xstrdup (val_error) : NULL; |
501 | 590 | if (!val && !val_error) |
502 | 591 | argp->entry_kind = print_entry_values_only; |
503 | - else if ((print_entry_values == print_entry_values_compact | |
504 | - || print_entry_values == print_entry_values_default) && val_equal) | |
592 | + else if ((fp_opts.print_entry_values == print_entry_values_compact | |
593 | + || fp_opts.print_entry_values == print_entry_values_default) | |
594 | + && val_equal) | |
505 | 595 | { |
506 | 596 | argp->entry_kind = print_entry_values_compact; |
507 | 597 | gdb_assert (!current_uiout->is_mi_like_p ()); |
@@ -528,7 +618,8 @@ read_frame_arg (struct symbol *sym, struct frame_info *frame, | ||
528 | 618 | ints of arguments according to the stack frame". */ |
529 | 619 | |
530 | 620 | static void |
531 | -print_frame_args (struct symbol *func, struct frame_info *frame, | |
621 | +print_frame_args (const frame_print_options &fp_opts, | |
622 | + struct symbol *func, struct frame_info *frame, | |
532 | 623 | int num, struct ui_file *stream) |
533 | 624 | { |
534 | 625 | struct ui_out *uiout = current_uiout; |
@@ -540,7 +631,8 @@ print_frame_args (struct symbol *func, struct frame_info *frame, | ||
540 | 631 | /* Number of ints of arguments that we have printed so far. */ |
541 | 632 | int args_printed = 0; |
542 | 633 | /* True if we should print arguments, false otherwise. */ |
543 | - int print_args = strcmp (print_frame_arguments, "none"); | |
634 | + bool print_args | |
635 | + = fp_opts.print_frame_arguments != print_frame_arguments_none; | |
544 | 636 | |
545 | 637 | if (func) |
546 | 638 | { |
@@ -674,10 +766,10 @@ print_frame_args (struct symbol *func, struct frame_info *frame, | ||
674 | 766 | entryarg.entry_kind = print_entry_values_no; |
675 | 767 | } |
676 | 768 | else |
677 | - read_frame_arg (sym, frame, &arg, &entryarg); | |
769 | + read_frame_arg (fp_opts, sym, frame, &arg, &entryarg); | |
678 | 770 | |
679 | 771 | if (arg.entry_kind != print_entry_values_only) |
680 | - print_frame_arg (&arg); | |
772 | + print_frame_arg (fp_opts, &arg); | |
681 | 773 | |
682 | 774 | if (entryarg.entry_kind != print_entry_values_no) |
683 | 775 | { |
@@ -687,7 +779,7 @@ print_frame_args (struct symbol *func, struct frame_info *frame, | ||
687 | 779 | uiout->wrap_hint (" "); |
688 | 780 | } |
689 | 781 | |
690 | - print_frame_arg (&entryarg); | |
782 | + print_frame_arg (fp_opts, &entryarg); | |
691 | 783 | } |
692 | 784 | |
693 | 785 | xfree (arg.error); |
@@ -778,7 +870,8 @@ do_gdb_disassembly (struct gdbarch *gdbarch, | ||
778 | 870 | messages. */ |
779 | 871 | |
780 | 872 | void |
781 | -print_frame_info (struct frame_info *frame, int print_level, | |
873 | +print_frame_info (const frame_print_options &fp_opts, | |
874 | + frame_info *frame, int print_level, | |
782 | 875 | enum print_what print_what, int print_args, |
783 | 876 | int set_current_sal) |
784 | 877 | { |
@@ -855,7 +948,7 @@ print_frame_info (struct frame_info *frame, int print_level, | ||
855 | 948 | || print_what == SRC_AND_LOC); |
856 | 949 | |
857 | 950 | if (location_print || !sal.symtab) |
858 | - print_frame (frame, print_level, print_what, print_args, sal); | |
951 | + print_frame (fp_opts, frame, print_level, print_what, print_args, sal); | |
859 | 952 | |
860 | 953 | source_print = (print_what == SRC_LINE || print_what == SRC_AND_LOC); |
861 | 954 |
@@ -1128,7 +1221,8 @@ find_frame_funname (struct frame_info *frame, enum language *funlang, | ||
1128 | 1221 | } |
1129 | 1222 | |
1130 | 1223 | static void |
1131 | -print_frame (struct frame_info *frame, int print_level, | |
1224 | +print_frame (const frame_print_options &fp_opts, | |
1225 | + frame_info *frame, int print_level, | |
1132 | 1226 | enum print_what print_what, int print_args, |
1133 | 1227 | struct symtab_and_line sal) |
1134 | 1228 | { |
@@ -1198,7 +1292,7 @@ print_frame (struct frame_info *frame, int print_level, | ||
1198 | 1292 | ui_out_emit_list list_emitter (uiout, "args"); |
1199 | 1293 | try |
1200 | 1294 | { |
1201 | - print_frame_args (func, frame, numargs, gdb_stdout); | |
1295 | + print_frame_args (fp_opts, func, frame, numargs, gdb_stdout); | |
1202 | 1296 | } |
1203 | 1297 | catch (const gdb_exception_error &e) |
1204 | 1298 | { |
@@ -1477,7 +1571,8 @@ info_frame_command_core (struct frame_info *fi, bool selected_frame_p) | ||
1477 | 1571 | else |
1478 | 1572 | printf_filtered (" %d args: ", numargs); |
1479 | 1573 | } |
1480 | - print_frame_args (func, fi, numargs, gdb_stdout); | |
1574 | + print_frame_args (user_frame_print_options, | |
1575 | + func, fi, numargs, gdb_stdout); | |
1481 | 1576 | puts_filtered ("\n"); |
1482 | 1577 | } |
1483 | 1578 | } |
@@ -1791,8 +1886,10 @@ static frame_command_helper <select_frame_command_core> select_frame_cmd; | ||
1791 | 1886 | frames. */ |
1792 | 1887 | |
1793 | 1888 | static void |
1794 | -backtrace_command_1 (const char *count_exp, frame_filter_flags flags, | |
1795 | - int no_filters, int from_tty) | |
1889 | +backtrace_command_1 (const frame_print_options &fp_opts, | |
1890 | + const backtrace_cmd_options &bt_opts, | |
1891 | + const char *count_exp, int from_tty) | |
1892 | + | |
1796 | 1893 | { |
1797 | 1894 | struct frame_info *fi; |
1798 | 1895 | int count; |
@@ -1821,7 +1918,14 @@ backtrace_command_1 (const char *count_exp, frame_filter_flags flags, | ||
1821 | 1918 | count = -1; |
1822 | 1919 | } |
1823 | 1920 | |
1824 | - if (! no_filters) | |
1921 | + frame_filter_flags flags = 0; | |
1922 | + | |
1923 | + if (bt_opts.full) | |
1924 | + flags |= PRINT_LOCALS; | |
1925 | + if (bt_opts.hide) | |
1926 | + flags |= PRINT_HIDE; | |
1927 | + | |
1928 | + if (!bt_opts.no_filters) | |
1825 | 1929 | { |
1826 | 1930 | enum ext_lang_frame_args arg_type; |
1827 | 1931 |
@@ -1829,9 +1933,9 @@ backtrace_command_1 (const char *count_exp, frame_filter_flags flags, | ||
1829 | 1933 | if (from_tty) |
1830 | 1934 | flags |= PRINT_MORE_FRAMES; |
1831 | 1935 | |
1832 | - if (!strcmp (print_frame_arguments, "scalars")) | |
1936 | + if (fp_opts.print_frame_arguments == print_frame_arguments_scalars) | |
1833 | 1937 | arg_type = CLI_SCALAR_VALUES; |
1834 | - else if (!strcmp (print_frame_arguments, "all")) | |
1938 | + else if (fp_opts.print_frame_arguments == print_frame_arguments_all) | |
1835 | 1939 | arg_type = CLI_ALL_VALUES; |
1836 | 1940 | else |
1837 | 1941 | arg_type = NO_VALUES; |
@@ -1842,8 +1946,8 @@ backtrace_command_1 (const char *count_exp, frame_filter_flags flags, | ||
1842 | 1946 | } |
1843 | 1947 | |
1844 | 1948 | /* Run the inbuilt backtrace if there are no filters registered, or |
1845 | - "no-filters" has been specified from the command. */ | |
1846 | - if (no_filters || result == EXT_LANG_BT_NO_FILTERS) | |
1949 | + "-no-filters" has been specified from the command. */ | |
1950 | + if (bt_opts.no_filters || result == EXT_LANG_BT_NO_FILTERS) | |
1847 | 1951 | { |
1848 | 1952 | struct frame_info *trailing; |
1849 | 1953 |
@@ -1869,7 +1973,7 @@ backtrace_command_1 (const char *count_exp, frame_filter_flags flags, | ||
1869 | 1973 | hand, perhaps the code does or could be fixed to make sure |
1870 | 1974 | the frame->prev field gets set to NULL in that case). */ |
1871 | 1975 | |
1872 | - print_frame_info (fi, 1, LOCATION, 1, 0); | |
1976 | + print_frame_info (fp_opts, fi, 1, LOCATION, 1, 0); | |
1873 | 1977 | if ((flags & PRINT_LOCALS) != 0) |
1874 | 1978 | { |
1875 | 1979 | struct frame_id frame_id = get_frame_id (fi); |
@@ -1908,17 +2012,38 @@ backtrace_command_1 (const char *count_exp, frame_filter_flags flags, | ||
1908 | 2012 | } |
1909 | 2013 | } |
1910 | 2014 | |
2015 | +/* Create an option_def_group array grouping all the "backtrace" | |
2016 | + options, with FP_OPTS, BT_CMD_OPT, SET_BT_OPTS as contexts. */ | |
2017 | + | |
2018 | +static inline std::array<gdb::option::option_def_group, 3> | |
2019 | +make_backtrace_options_def_group (frame_print_options *fp_opts, | |
2020 | + backtrace_cmd_options *bt_cmd_opts, | |
2021 | + set_backtrace_options *set_bt_opts) | |
2022 | +{ | |
2023 | + return {{ | |
2024 | + { {frame_print_option_defs}, fp_opts }, | |
2025 | + { {set_backtrace_option_defs}, set_bt_opts }, | |
2026 | + { {backtrace_command_option_defs}, bt_cmd_opts } | |
2027 | + }}; | |
2028 | +} | |
2029 | + | |
1911 | 2030 | static void |
1912 | 2031 | backtrace_command (const char *arg, int from_tty) |
1913 | 2032 | { |
1914 | - bool filters = true; | |
1915 | - frame_filter_flags flags = 0; | |
2033 | + frame_print_options fp_opts = user_frame_print_options; | |
2034 | + backtrace_cmd_options bt_cmd_opts; | |
2035 | + set_backtrace_options set_bt_opts = user_set_backtrace_options; | |
1916 | 2036 | |
1917 | - if (arg) | |
1918 | - { | |
1919 | - bool done = false; | |
2037 | + auto grp | |
2038 | + = make_backtrace_options_def_group (&fp_opts, &bt_cmd_opts, &set_bt_opts); | |
2039 | + gdb::option::process_options | |
2040 | + (&arg, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, grp); | |
1920 | 2041 | |
1921 | - while (!done) | |
2042 | + /* Parse non-'-'-prefixed qualifiers, for backwards | |
2043 | + compatibility. */ | |
2044 | + if (arg != NULL) | |
2045 | + { | |
2046 | + while (true) | |
1922 | 2047 | { |
1923 | 2048 | const char *save_arg = arg; |
1924 | 2049 | std::string this_arg = extract_arg (&arg); |
@@ -1927,16 +2052,16 @@ backtrace_command (const char *arg, int from_tty) | ||
1927 | 2052 | break; |
1928 | 2053 | |
1929 | 2054 | if (subset_compare (this_arg.c_str (), "no-filters")) |
1930 | - filters = false; | |
2055 | + bt_cmd_opts.no_filters = true; | |
1931 | 2056 | else if (subset_compare (this_arg.c_str (), "full")) |
1932 | - flags |= PRINT_LOCALS; | |
2057 | + bt_cmd_opts.full = true; | |
1933 | 2058 | else if (subset_compare (this_arg.c_str (), "hide")) |
1934 | - flags |= PRINT_HIDE; | |
2059 | + bt_cmd_opts.hide = true; | |
1935 | 2060 | else |
1936 | 2061 | { |
1937 | 2062 | /* Not a recognized argument, so stop. */ |
1938 | 2063 | arg = save_arg; |
1939 | - done = true; | |
2064 | + break; | |
1940 | 2065 | } |
1941 | 2066 | } |
1942 | 2067 |
@@ -1944,7 +2069,29 @@ backtrace_command (const char *arg, int from_tty) | ||
1944 | 2069 | arg = NULL; |
1945 | 2070 | } |
1946 | 2071 | |
1947 | - backtrace_command_1 (arg, flags, !filters /* no frame-filters */, from_tty); | |
2072 | + /* These options are handled quite deep in the unwind machinery, so | |
2073 | + we get to pass them down by swapping globals. */ | |
2074 | + scoped_restore restore_set_backtrace_options | |
2075 | + = make_scoped_restore (&user_set_backtrace_options, set_bt_opts); | |
2076 | + | |
2077 | + backtrace_command_1 (fp_opts, bt_cmd_opts, arg, from_tty); | |
2078 | +} | |
2079 | + | |
2080 | +/* Completer for the "backtrace" command. */ | |
2081 | + | |
2082 | +static void | |
2083 | +backtrace_command_completer (struct cmd_list_element *ignore, | |
2084 | + completion_tracker &tracker, | |
2085 | + const char *text, const char */*word*/) | |
2086 | +{ | |
2087 | + const auto group | |
2088 | + = make_backtrace_options_def_group (nullptr, nullptr, nullptr); | |
2089 | + if (gdb::option::complete_options | |
2090 | + (tracker, &text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, group)) | |
2091 | + return; | |
2092 | + | |
2093 | + const char *word = advance_to_expression_complete_word_point (tracker, text); | |
2094 | + expression_completer (ignore, tracker, text, word); | |
1948 | 2095 | } |
1949 | 2096 | |
1950 | 2097 | /* Iterate over the local variables of a block B, calling CB with |
@@ -3030,13 +3177,30 @@ Usage: select-frame level LEVEL"), | ||
3030 | 3177 | &select_frame_cmd_list, |
3031 | 3178 | &cli_suppress_notification.user_selected_context); |
3032 | 3179 | |
3033 | - add_com ("backtrace", class_stack, backtrace_command, _("\ | |
3180 | + const auto backtrace_opts | |
3181 | + = make_backtrace_options_def_group (nullptr, nullptr, nullptr); | |
3182 | + | |
3183 | + static std::string backtrace_help | |
3184 | + = gdb::option::build_help (N_("\ | |
3034 | 3185 | Print backtrace of all stack frames, or innermost COUNT frames.\n\ |
3035 | -Usage: backtrace [QUALIFIERS]... [COUNT]\n\ | |
3036 | -With a negative argument, print outermost -COUNT frames.\n\ | |
3037 | -Use of the 'full' qualifier also prints the values of the local variables.\n\ | |
3038 | -Use of the 'no-filters' qualifier prohibits frame filters from executing\n\ | |
3039 | -on this backtrace.")); | |
3186 | +Usage: backtrace [OPTION]... [QUALIFIER]... [COUNT | -COUNT]\n\ | |
3187 | +\n\ | |
3188 | +Options:\n\ | |
3189 | +%OPTIONS%\ | |
3190 | +For backward compatibility, the following qualifiers are supported:\n\ | |
3191 | +\n\ | |
3192 | + full - same as -full option.\n\ | |
3193 | + no-filters - same as -no-filters option.\n\ | |
3194 | + hide - same as -hide.\n\ | |
3195 | +\n\ | |
3196 | +With a negative COUNT, print outermost -COUNT frames."), | |
3197 | + backtrace_opts); | |
3198 | + | |
3199 | + cmd_list_element *c = add_com ("backtrace", class_stack, | |
3200 | + backtrace_command, | |
3201 | + backtrace_help.c_str ()); | |
3202 | + set_cmd_completer_handle_brkchars (c, backtrace_command_completer); | |
3203 | + | |
3040 | 3204 | add_com_alias ("bt", "backtrace", class_stack, 0); |
3041 | 3205 | |
3042 | 3206 | add_com_alias ("where", "backtrace", class_alias, 0); |
@@ -3100,33 +3264,20 @@ Prints the argument variables of the current stack frame.\n"), | ||
3100 | 3264 | Select the stack frame that contains NAME.\n\ |
3101 | 3265 | Usage: func NAME")); |
3102 | 3266 | |
3103 | - add_setshow_enum_cmd ("frame-arguments", class_stack, | |
3104 | - print_frame_arguments_choices, &print_frame_arguments, | |
3105 | - _("Set printing of non-scalar frame arguments"), | |
3106 | - _("Show printing of non-scalar frame arguments"), | |
3107 | - NULL, NULL, NULL, &setprintlist, &showprintlist); | |
3108 | - | |
3109 | 3267 | /* Install "set print raw frame-arguments", a deprecated spelling of |
3110 | 3268 | "set print raw-frame-arguments". */ |
3111 | - cmd = add_setshow_boolean_cmd ("frame-arguments", no_class, | |
3112 | - &print_raw_frame_arguments, _("\ | |
3269 | + cmd = add_setshow_boolean_cmd | |
3270 | + ("frame-arguments", no_class, | |
3271 | + &user_frame_print_options.print_raw_frame_arguments, | |
3272 | + _("\ | |
3113 | 3273 | Set whether to print frame arguments in raw form."), _("\ |
3114 | 3274 | Show whether to print frame arguments in raw form."), _("\ |
3115 | 3275 | If set, frame arguments are printed in raw form, bypassing any\n\ |
3116 | 3276 | pretty-printers for that value."), |
3117 | - NULL, NULL, | |
3118 | - &setprintrawlist, &showprintrawlist); | |
3277 | + NULL, NULL, | |
3278 | + &setprintrawlist, &showprintrawlist); | |
3119 | 3279 | deprecate_cmd (cmd, "set print raw-frame-arguments"); |
3120 | 3280 | |
3121 | - add_setshow_boolean_cmd ("raw-frame-arguments", no_class, | |
3122 | - &print_raw_frame_arguments, _("\ | |
3123 | -Set whether to print frame arguments in raw form."), _("\ | |
3124 | -Show whether to print frame arguments in raw form."), _("\ | |
3125 | -If set, frame arguments are printed in raw form, bypassing any\n\ | |
3126 | -pretty-printers for that value."), | |
3127 | - NULL, NULL, | |
3128 | - &setprintlist, &showprintlist); | |
3129 | - | |
3130 | 3281 | add_setshow_auto_boolean_cmd ("disassemble-next-line", class_stack, |
3131 | 3282 | &disassemble_next_line, _("\ |
3132 | 3283 | Set whether to disassemble next source line or insn when execution stops."), |
@@ -3147,16 +3298,7 @@ source line."), | ||
3147 | 3298 | &setlist, &showlist); |
3148 | 3299 | disassemble_next_line = AUTO_BOOLEAN_FALSE; |
3149 | 3300 | |
3150 | - add_setshow_enum_cmd ("entry-values", class_stack, | |
3151 | - print_entry_values_choices, &print_entry_values, | |
3152 | - _("Set printing of function arguments at function " | |
3153 | - "entry"), | |
3154 | - _("Show printing of function arguments at function " | |
3155 | - "entry"), | |
3156 | - _("\ | |
3157 | -GDB can sometimes determine the values of function arguments at entry,\n\ | |
3158 | -in addition to their current values. This option tells GDB whether\n\ | |
3159 | -to print the current value, the value at entry (marked as val@entry),\n\ | |
3160 | -or both. Note that one or both of these values may be <optimized out>."), | |
3161 | - NULL, NULL, &setprintlist, &showprintlist); | |
3301 | + gdb::option::add_setshow_cmds_for_options | |
3302 | + (class_stack, &user_frame_print_options, | |
3303 | + frame_print_option_defs, &setprintlist, &showprintlist); | |
3162 | 3304 | } |
@@ -20,8 +20,11 @@ | ||
20 | 20 | # The test uses the "maintenance test-options" subcommands to exercise |
21 | 21 | # TAB-completion and option processing. |
22 | 22 | # |
23 | -# It also tests option integration in various commands, including | |
24 | -# "print" and "compile print". | |
23 | +# It also tests option integration in various commands, including: | |
24 | +# | |
25 | ||
26 | +# - compile print | |
27 | +# - backtrace | |
25 | 28 | |
26 | 29 | load_lib completion-support.exp |
27 | 30 |
@@ -231,6 +234,56 @@ proc_with_prefix test-print {{prefix ""}} { | ||
231 | 234 | "Left operand of assignment is not an lvalue\\." |
232 | 235 | } |
233 | 236 | |
237 | +# Basic option-machinery + "backtrace" command integration tests. | |
238 | +proc_with_prefix test-backtrace {} { | |
239 | + clean_restart | |
240 | + | |
241 | + test_gdb_complete_unique "backtrace" "backtrace" | |
242 | + test_gdb_complete_none "backtrace " | |
243 | + | |
244 | + gdb_test "backtrace -" "Ambiguous option at: -" | |
245 | + gdb_test "backtrace --" "No stack\\." | |
246 | + gdb_test "backtrace -- -" "No stack\\." | |
247 | + | |
248 | + test_gdb_complete_multiple "backtrace " "-" "" { | |
249 | + "-entry-values" | |
250 | + "-frame-arguments" | |
251 | + "-full" | |
252 | + "-hide" | |
253 | + "-no-filters" | |
254 | + "-past-entry" | |
255 | + "-past-main" | |
256 | + "-raw-frame-arguments" | |
257 | + } | |
258 | + | |
259 | + global binfile | |
260 | + clean_restart $binfile | |
261 | + | |
262 | + if ![runto_main] { | |
263 | + fail "cannot run to main" | |
264 | + return | |
265 | + } | |
266 | + | |
267 | + # COUNT in "backtrace COUNT" is parsed as an expression. Check | |
268 | + # that we complete expressions. | |
269 | + | |
270 | + test_gdb_complete_unique \ | |
271 | + "backtrace xxx" \ | |
272 | + "backtrace xxx1" | |
273 | + | |
274 | + test_gdb_complete_unique \ | |
275 | + "backtrace -xxx" \ | |
276 | + "backtrace -xxx1" | |
277 | + | |
278 | + test_gdb_complete_unique \ | |
279 | + "backtrace 1 + xxx" \ | |
280 | + "backtrace 1 + xxx1" | |
281 | + | |
282 | + test_gdb_complete_unique \ | |
283 | + "backtrace (1 + xxx" \ | |
284 | + "backtrace (1 + xxx1" | |
285 | +} | |
286 | + | |
234 | 287 | # Miscellaneous tests. |
235 | 288 | proc_with_prefix test-misc {variant} { |
236 | 289 | global all_options |
@@ -674,3 +727,6 @@ test-print "" | ||
674 | 727 | if ![skip_compile_feature_tests] { |
675 | 728 | test-print "compile " |
676 | 729 | } |
730 | + | |
731 | +# Basic "backtrace" integration tests. | |
732 | +test-backtrace |