• R/O
  • HTTP
  • SSH
  • HTTPS

提交

標籤
無標籤

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

GNU Binutils with patches for OS216


Commit MetaInfo

修訂9c893427353580b909059d1d6655fff139d548e9 (tree)
時間2019-06-05 07:30:03
作者Pedro Alves <palves@redh...>
CommiterPedro Alves

Log Message

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:
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.

Change Summary

差異

--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -42,6 +42,7 @@
4242 #include "tracepoint.h"
4343 #include "hashtab.h"
4444 #include "valprint.h"
45+#include "cli/cli-option.h"
4546
4647 /* The sentinel frame terminates the innermost end of the frame chain.
4748 If unwound, it returns the information needed to construct an
@@ -52,6 +53,9 @@
5253
5354 static struct frame_info *sentinel_frame;
5455
56+/* The values behind the global "set backtrace ..." settings. */
57+set_backtrace_options user_set_backtrace_options;
58+
5559 static struct frame_info *get_prev_frame_raw (struct frame_info *this_frame);
5660 static const char *frame_stop_reason_symbol_string (enum unwind_stop_reason reason);
5761
@@ -295,9 +299,8 @@ show_frame_debug (struct ui_file *file, int from_tty,
295299 fprintf_filtered (file, _("Frame debugging is %s.\n"), value);
296300 }
297301
298-/* Flag to indicate whether backtraces should stop at main et.al. */
302+/* Implementation of "show backtrace past-main". */
299303
300-static int backtrace_past_main;
301304 static void
302305 show_backtrace_past_main (struct ui_file *file, int from_tty,
303306 struct cmd_list_element *c, const char *value)
@@ -308,7 +311,8 @@ show_backtrace_past_main (struct ui_file *file, int from_tty,
308311 value);
309312 }
310313
311-static int backtrace_past_entry;
314+/* Implementation of "show backtrace past-entry". */
315+
312316 static void
313317 show_backtrace_past_entry (struct ui_file *file, int from_tty,
314318 struct cmd_list_element *c, const char *value)
@@ -318,7 +322,8 @@ show_backtrace_past_entry (struct ui_file *file, int from_tty,
318322 value);
319323 }
320324
321-static unsigned int backtrace_limit = UINT_MAX;
325+/* Implementation of "show backtrace limit". */
326+
322327 static void
323328 show_backtrace_limit (struct ui_file *file, int from_tty,
324329 struct cmd_list_element *c, const char *value)
@@ -2276,7 +2281,7 @@ get_prev_frame (struct frame_info *this_frame)
22762281 point inside the main function. */
22772282 if (this_frame->level >= 0
22782283 && get_frame_type (this_frame) == NORMAL_FRAME
2279- && !backtrace_past_main
2284+ && !user_set_backtrace_options.backtrace_past_main
22802285 && frame_pc_p
22812286 && inside_main_func (this_frame))
22822287 /* Don't unwind past main(). Note, this is done _before_ the
@@ -2293,7 +2298,7 @@ get_prev_frame (struct frame_info *this_frame)
22932298 being 1-based and the level being 0-based, and the other accounts for
22942299 the level of the new frame instead of the level of the current
22952300 frame. */
2296- if (this_frame->level + 2 > backtrace_limit)
2301+ if (this_frame->level + 2 > user_set_backtrace_options.backtrace_limit)
22972302 {
22982303 frame_debug_got_null_frame (this_frame, "backtrace limit exceeded");
22992304 return NULL;
@@ -2323,7 +2328,7 @@ get_prev_frame (struct frame_info *this_frame)
23232328 application. */
23242329 if (this_frame->level >= 0
23252330 && get_frame_type (this_frame) == NORMAL_FRAME
2326- && !backtrace_past_entry
2331+ && !user_set_backtrace_options.backtrace_past_entry
23272332 && frame_pc_p
23282333 && inside_entry_func (this_frame))
23292334 {
@@ -2896,6 +2901,39 @@ show_backtrace_cmd (const char *args, int from_tty)
28962901 cmd_show_list (show_backtrace_cmdlist, from_tty, "");
28972902 }
28982903
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+
28992937 void
29002938 _initialize_frame (void)
29012939 {
@@ -2916,34 +2954,8 @@ Show backtrace variables such as the backtrace limit"),
29162954 &show_backtrace_cmdlist, "show backtrace ",
29172955 0/*allow-unknown*/, &showlist);
29182956
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-
29452957 add_setshow_uinteger_cmd ("limit", class_obscure,
2946- &backtrace_limit, _("\
2958+ &user_set_backtrace_options.backtrace_limit, _("\
29472959 Set an upper bound on the number of backtrace levels."), _("\
29482960 Show the upper bound on the number of backtrace levels."), _("\
29492961 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."),
29532965 &set_backtrace_cmdlist,
29542966 &show_backtrace_cmdlist);
29552967
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+
29562972 /* Debug this files internals. */
29572973 add_setshow_zuinteger_cmd ("frame", class_maintenance, &frame_debug, _("\
29582974 Set frame debugging."), _("\
--- a/gdb/frame.h
+++ b/gdb/frame.h
@@ -70,6 +70,7 @@
7070 */
7171
7272 #include "language.h"
73+#include "cli/cli-option.h"
7374
7475 struct symtab_and_line;
7576 struct frame_unwind;
@@ -78,6 +79,7 @@ struct block;
7879 struct gdbarch;
7980 struct ui_file;
8081 struct ui_out;
82+struct frame_print_options;
8183
8284 /* Status of a given frame's stack. */
8385
@@ -753,7 +755,8 @@ extern void print_stack_frame (struct frame_info *, int print_level,
753755 enum print_what print_what,
754756 int set_current_sal);
755757
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,
757760 enum print_what print_what, int args,
758761 int set_current_sal);
759762
@@ -764,6 +767,12 @@ extern int deprecated_frame_register_read (struct frame_info *frame, int regnum,
764767
765768 /* From stack.c. */
766769
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". */
767776 extern const char print_entry_values_no[];
768777 extern const char print_entry_values_only[];
769778 extern const char print_entry_values_preferred[];
@@ -771,7 +780,22 @@ extern const char print_entry_values_if_needed[];
771780 extern const char print_entry_values_both[];
772781 extern const char print_entry_values_compact[];
773782 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;
775799
776800 /* Inferior function parameter value read in from a frame. */
777801
@@ -800,7 +824,8 @@ struct frame_arg
800824 const char *entry_kind;
801825 };
802826
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,
804829 struct frame_arg *argp,
805830 struct frame_arg *entryargp);
806831 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);
881906
882907 extern struct frame_info *skip_unwritable_frames (struct frame_info *frame);
883908
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+
884933 #endif /* !defined (FRAME_H) */
--- a/gdb/mi/mi-cmd-stack.c
+++ b/gdb/mi/mi-cmd-stack.c
@@ -39,7 +39,8 @@
3939
4040 enum what_to_list { locals, arguments, all };
4141
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,
4344 enum print_values values,
4445 struct frame_info *fi,
4546 int skip_unavailable);
@@ -175,7 +176,8 @@ mi_cmd_stack_list_frames (const char *command, char **argv, int argc)
175176 QUIT;
176177 /* Print the location and the address always, even for level 0.
177178 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);
179181 }
180182 }
181183 }
@@ -275,7 +277,8 @@ mi_cmd_stack_list_locals (const char *command, char **argv, int argc)
275277 if "--no-frame-filters" has been specified from the command. */
276278 if (! frame_filters || raw_arg || result == EXT_LANG_BT_NO_FILTERS)
277279 {
278- list_args_or_locals (locals, print_value, frame,
280+ list_args_or_locals (user_frame_print_options,
281+ locals, print_value, frame,
279282 skip_unavailable);
280283 }
281284 }
@@ -389,7 +392,8 @@ mi_cmd_stack_list_args (const char *command, char **argv, int argc)
389392 QUIT;
390393 ui_out_emit_tuple tuple_emitter (uiout, "frame");
391394 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);
393397 }
394398 }
395399 }
@@ -465,7 +469,8 @@ mi_cmd_stack_list_variables (const char *command, char **argv, int argc)
465469 if "--no-frame-filters" has been specified from the command. */
466470 if (! frame_filters || raw_arg || result == EXT_LANG_BT_NO_FILTERS)
467471 {
468- list_args_or_locals (all, print_value, frame,
472+ list_args_or_locals (user_frame_print_options,
473+ all, print_value, frame,
469474 skip_unavailable);
470475 }
471476 }
@@ -557,7 +562,8 @@ list_arg_or_local (const struct frame_arg *arg, enum what_to_list what,
557562 are available. */
558563
559564 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,
561567 struct frame_info *fi, int skip_unavailable)
562568 {
563569 const struct block *block;
@@ -652,7 +658,7 @@ list_args_or_locals (enum what_to_list what, enum print_values values,
652658 {
653659 case PRINT_ALL_VALUES:
654660 if (SYMBOL_IS_ARGUMENT (sym))
655- read_frame_arg (sym2, fi, &arg, &entryarg);
661+ read_frame_arg (fp_opts, sym2, fi, &arg, &entryarg);
656662 else
657663 read_frame_local (sym2, fi, &arg);
658664 }
@@ -764,5 +770,6 @@ mi_cmd_stack_info_frame (const char *command, char **argv, int argc)
764770 if (argc > 0)
765771 error (_("-stack-info-frame: No arguments allowed"));
766772
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);
768775 }
--- a/gdb/python/py-framefilter.c
+++ b/gdb/python/py-framefilter.c
@@ -481,7 +481,8 @@ enumerate_args (PyObject *iter,
481481 return EXT_LANG_BT_ERROR;
482482 }
483483
484- read_frame_arg (sym, frame, &arg, &entryarg);
484+ read_frame_arg (user_frame_print_options,
485+ sym, frame, &arg, &entryarg);
485486
486487 gdb::unique_xmalloc_ptr<char> arg_holder (arg.error);
487488 gdb::unique_xmalloc_ptr<char> entry_holder (entryarg.error);
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -52,16 +52,22 @@
5252 #include "extension.h"
5353 #include "observable.h"
5454 #include "common/def-vector.h"
55+#include "cli/cli-option.h"
5556
5657 /* The possible choices of "set print frame-arguments", and the value
5758 of this setting. */
5859
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";
6263
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+};
6571
6672 /* The possible choices of "set print entry-values", and the value
6773 of this setting. */
@@ -84,7 +90,85 @@ static const char *const print_entry_values_choices[] =
8490 print_entry_values_default,
8591 NULL
8692 };
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+};
88172
89173 /* Prototypes for local functions. */
90174
@@ -93,7 +177,8 @@ static void print_frame_local_vars (struct frame_info *frame,
93177 const char *regexp, const char *t_regexp,
94178 int num_tabs, struct ui_file *stream);
95179
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,
97182 enum print_what print_what, int print_args,
98183 struct symtab_and_line sal);
99184
@@ -177,7 +262,8 @@ print_stack_frame (struct frame_info *frame, int print_level,
177262
178263 try
179264 {
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 */,
181267 set_current_sal);
182268 if (set_current_sal)
183269 set_current_sal_from_frame (frame);
@@ -225,7 +311,8 @@ print_frame_nameless_args (struct frame_info *frame, long start, int num,
225311 iff it should not be printed accoring to user settings. */
226312
227313 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)
229316 {
230317 struct ui_out *uiout = current_uiout;
231318
@@ -269,7 +356,7 @@ print_frame_arg (const struct frame_arg *arg)
269356 try
270357 {
271358 const struct language_defn *language;
272- struct value_print_options opts;
359+ struct value_print_options vp_opts;
273360
274361 /* Avoid value_print because it will deref ref parameters. We
275362 just want to print their addresses. Print ??? for args whose
@@ -286,14 +373,15 @@ print_frame_arg (const struct frame_arg *arg)
286373 else
287374 language = current_language;
288375
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;
292379
293380 /* 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;
295383
296- common_val_print (arg->val, &stb, 2, &opts, language);
384+ common_val_print (arg->val, &stb, 2, &vp_opts, language);
297385 }
298386 catch (const gdb_exception_error &except)
299387 {
@@ -333,15 +421,16 @@ read_frame_local (struct symbol *sym, struct frame_info *frame,
333421 exception. */
334422
335423 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,
337426 struct frame_arg *argp, struct frame_arg *entryargp)
338427 {
339428 struct value *val = NULL, *entryval = NULL;
340429 char *val_error = NULL, *entryval_error = NULL;
341430 int val_equal = 0;
342431
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)
345434 {
346435 try
347436 {
@@ -356,8 +445,8 @@ read_frame_arg (struct symbol *sym, struct frame_info *frame,
356445
357446 if (SYMBOL_COMPUTED_OPS (sym) != NULL
358447 && 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
361450 || !val || value_optimized_out (val)))
362451 {
363452 try
@@ -379,8 +468,8 @@ read_frame_arg (struct symbol *sym, struct frame_info *frame,
379468 if (entryval != NULL && value_optimized_out (entryval))
380469 entryval = NULL;
381470
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)
384473 {
385474 /* For MI do not try to use print_entry_values_compact for ARGP. */
386475
@@ -463,7 +552,7 @@ read_frame_arg (struct symbol *sym, struct frame_info *frame,
463552
464553 if (entryval == NULL)
465554 {
466- if (print_entry_values == print_entry_values_preferred)
555+ if (fp_opts.print_entry_values == print_entry_values_preferred)
467556 {
468557 gdb_assert (val == NULL);
469558
@@ -477,18 +566,18 @@ read_frame_arg (struct symbol *sym, struct frame_info *frame,
477566 strcpy (val_error, except.what ());
478567 }
479568 }
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
483572 && (!val || value_optimized_out (val))))
484573 {
485574 entryval = allocate_optimized_out_value (SYMBOL_TYPE (sym));
486575 entryval_error = NULL;
487576 }
488577 }
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)
492581 && (!val || value_optimized_out (val)) && entryval != NULL)
493582 {
494583 val = NULL;
@@ -500,8 +589,9 @@ read_frame_arg (struct symbol *sym, struct frame_info *frame,
500589 argp->error = val_error ? xstrdup (val_error) : NULL;
501590 if (!val && !val_error)
502591 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)
505595 {
506596 argp->entry_kind = print_entry_values_compact;
507597 gdb_assert (!current_uiout->is_mi_like_p ());
@@ -528,7 +618,8 @@ read_frame_arg (struct symbol *sym, struct frame_info *frame,
528618 ints of arguments according to the stack frame". */
529619
530620 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,
532623 int num, struct ui_file *stream)
533624 {
534625 struct ui_out *uiout = current_uiout;
@@ -540,7 +631,8 @@ print_frame_args (struct symbol *func, struct frame_info *frame,
540631 /* Number of ints of arguments that we have printed so far. */
541632 int args_printed = 0;
542633 /* 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;
544636
545637 if (func)
546638 {
@@ -674,10 +766,10 @@ print_frame_args (struct symbol *func, struct frame_info *frame,
674766 entryarg.entry_kind = print_entry_values_no;
675767 }
676768 else
677- read_frame_arg (sym, frame, &arg, &entryarg);
769+ read_frame_arg (fp_opts, sym, frame, &arg, &entryarg);
678770
679771 if (arg.entry_kind != print_entry_values_only)
680- print_frame_arg (&arg);
772+ print_frame_arg (fp_opts, &arg);
681773
682774 if (entryarg.entry_kind != print_entry_values_no)
683775 {
@@ -687,7 +779,7 @@ print_frame_args (struct symbol *func, struct frame_info *frame,
687779 uiout->wrap_hint (" ");
688780 }
689781
690- print_frame_arg (&entryarg);
782+ print_frame_arg (fp_opts, &entryarg);
691783 }
692784
693785 xfree (arg.error);
@@ -778,7 +870,8 @@ do_gdb_disassembly (struct gdbarch *gdbarch,
778870 messages. */
779871
780872 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,
782875 enum print_what print_what, int print_args,
783876 int set_current_sal)
784877 {
@@ -855,7 +948,7 @@ print_frame_info (struct frame_info *frame, int print_level,
855948 || print_what == SRC_AND_LOC);
856949
857950 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);
859952
860953 source_print = (print_what == SRC_LINE || print_what == SRC_AND_LOC);
861954
@@ -1128,7 +1221,8 @@ find_frame_funname (struct frame_info *frame, enum language *funlang,
11281221 }
11291222
11301223 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,
11321226 enum print_what print_what, int print_args,
11331227 struct symtab_and_line sal)
11341228 {
@@ -1198,7 +1292,7 @@ print_frame (struct frame_info *frame, int print_level,
11981292 ui_out_emit_list list_emitter (uiout, "args");
11991293 try
12001294 {
1201- print_frame_args (func, frame, numargs, gdb_stdout);
1295+ print_frame_args (fp_opts, func, frame, numargs, gdb_stdout);
12021296 }
12031297 catch (const gdb_exception_error &e)
12041298 {
@@ -1477,7 +1571,8 @@ info_frame_command_core (struct frame_info *fi, bool selected_frame_p)
14771571 else
14781572 printf_filtered (" %d args: ", numargs);
14791573 }
1480- print_frame_args (func, fi, numargs, gdb_stdout);
1574+ print_frame_args (user_frame_print_options,
1575+ func, fi, numargs, gdb_stdout);
14811576 puts_filtered ("\n");
14821577 }
14831578 }
@@ -1791,8 +1886,10 @@ static frame_command_helper <select_frame_command_core> select_frame_cmd;
17911886 frames. */
17921887
17931888 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+
17961893 {
17971894 struct frame_info *fi;
17981895 int count;
@@ -1821,7 +1918,14 @@ backtrace_command_1 (const char *count_exp, frame_filter_flags flags,
18211918 count = -1;
18221919 }
18231920
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)
18251929 {
18261930 enum ext_lang_frame_args arg_type;
18271931
@@ -1829,9 +1933,9 @@ backtrace_command_1 (const char *count_exp, frame_filter_flags flags,
18291933 if (from_tty)
18301934 flags |= PRINT_MORE_FRAMES;
18311935
1832- if (!strcmp (print_frame_arguments, "scalars"))
1936+ if (fp_opts.print_frame_arguments == print_frame_arguments_scalars)
18331937 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)
18351939 arg_type = CLI_ALL_VALUES;
18361940 else
18371941 arg_type = NO_VALUES;
@@ -1842,8 +1946,8 @@ backtrace_command_1 (const char *count_exp, frame_filter_flags flags,
18421946 }
18431947
18441948 /* 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)
18471951 {
18481952 struct frame_info *trailing;
18491953
@@ -1869,7 +1973,7 @@ backtrace_command_1 (const char *count_exp, frame_filter_flags flags,
18691973 hand, perhaps the code does or could be fixed to make sure
18701974 the frame->prev field gets set to NULL in that case). */
18711975
1872- print_frame_info (fi, 1, LOCATION, 1, 0);
1976+ print_frame_info (fp_opts, fi, 1, LOCATION, 1, 0);
18731977 if ((flags & PRINT_LOCALS) != 0)
18741978 {
18751979 struct frame_id frame_id = get_frame_id (fi);
@@ -1908,17 +2012,38 @@ backtrace_command_1 (const char *count_exp, frame_filter_flags flags,
19082012 }
19092013 }
19102014
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+
19112030 static void
19122031 backtrace_command (const char *arg, int from_tty)
19132032 {
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;
19162036
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);
19202041
1921- while (!done)
2042+ /* Parse non-'-'-prefixed qualifiers, for backwards
2043+ compatibility. */
2044+ if (arg != NULL)
2045+ {
2046+ while (true)
19222047 {
19232048 const char *save_arg = arg;
19242049 std::string this_arg = extract_arg (&arg);
@@ -1927,16 +2052,16 @@ backtrace_command (const char *arg, int from_tty)
19272052 break;
19282053
19292054 if (subset_compare (this_arg.c_str (), "no-filters"))
1930- filters = false;
2055+ bt_cmd_opts.no_filters = true;
19312056 else if (subset_compare (this_arg.c_str (), "full"))
1932- flags |= PRINT_LOCALS;
2057+ bt_cmd_opts.full = true;
19332058 else if (subset_compare (this_arg.c_str (), "hide"))
1934- flags |= PRINT_HIDE;
2059+ bt_cmd_opts.hide = true;
19352060 else
19362061 {
19372062 /* Not a recognized argument, so stop. */
19382063 arg = save_arg;
1939- done = true;
2064+ break;
19402065 }
19412066 }
19422067
@@ -1944,7 +2069,29 @@ backtrace_command (const char *arg, int from_tty)
19442069 arg = NULL;
19452070 }
19462071
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);
19482095 }
19492096
19502097 /* Iterate over the local variables of a block B, calling CB with
@@ -3030,13 +3177,30 @@ Usage: select-frame level LEVEL"),
30303177 &select_frame_cmd_list,
30313178 &cli_suppress_notification.user_selected_context);
30323179
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_("\
30343185 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+
30403204 add_com_alias ("bt", "backtrace", class_stack, 0);
30413205
30423206 add_com_alias ("where", "backtrace", class_alias, 0);
@@ -3100,33 +3264,20 @@ Prints the argument variables of the current stack frame.\n"),
31003264 Select the stack frame that contains NAME.\n\
31013265 Usage: func NAME"));
31023266
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-
31093267 /* Install "set print raw frame-arguments", a deprecated spelling of
31103268 "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+ _("\
31133273 Set whether to print frame arguments in raw form."), _("\
31143274 Show whether to print frame arguments in raw form."), _("\
31153275 If set, frame arguments are printed in raw form, bypassing any\n\
31163276 pretty-printers for that value."),
3117- NULL, NULL,
3118- &setprintrawlist, &showprintrawlist);
3277+ NULL, NULL,
3278+ &setprintrawlist, &showprintrawlist);
31193279 deprecate_cmd (cmd, "set print raw-frame-arguments");
31203280
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-
31303281 add_setshow_auto_boolean_cmd ("disassemble-next-line", class_stack,
31313282 &disassemble_next_line, _("\
31323283 Set whether to disassemble next source line or insn when execution stops."),
@@ -3147,16 +3298,7 @@ source line."),
31473298 &setlist, &showlist);
31483299 disassemble_next_line = AUTO_BOOLEAN_FALSE;
31493300
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);
31623304 }
--- a/gdb/testsuite/gdb.base/options.exp
+++ b/gdb/testsuite/gdb.base/options.exp
@@ -20,8 +20,11 @@
2020 # The test uses the "maintenance test-options" subcommands to exercise
2121 # TAB-completion and option processing.
2222 #
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+# - print
26+# - compile print
27+# - backtrace
2528
2629 load_lib completion-support.exp
2730
@@ -231,6 +234,56 @@ proc_with_prefix test-print {{prefix ""}} {
231234 "Left operand of assignment is not an lvalue\\."
232235 }
233236
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+
234287 # Miscellaneous tests.
235288 proc_with_prefix test-misc {variant} {
236289 global all_options
@@ -674,3 +727,6 @@ test-print ""
674727 if ![skip_compile_feature_tests] {
675728 test-print "compile "
676729 }
730+
731+# Basic "backtrace" integration tests.
732+test-backtrace