@@ -1,5 +1,29 @@
2015-09-11 Andrew Burgess <andrew.burgess@embecosm.com>
+ * stack.c (find_frame_for_function): Add declaration.
+ (find_frame_for_address): New function.
+ (enum frame_select_mode): New enum.
+ (FRAME_SELECTION_MAX_ARGS): New define.
+ (struct frame_selection_spec): New structure.
+ (is_frame_mode_string): New function.
+ (parse_frame_selection_spec): New function.
+ (free_frame_selection_spec): New function.
+ (parse_frame_specification): Rewrite.
+ (frame_info): Build argv for frame selection spec.
+ (select_frame_from_spec): New function.
+ (select_frame_command): Make static, build argv for frame
+ selection spec.
+ (frame_selection_completer): New function.
+ (_initialize_stack): Add completion function, and update the help
+ text for 'frame', 'select-frame', and 'info frame' commands.
+ * stack.h (select_frame_command): Delete declaration.
+ (select_frame_from_spec): New declaration.
+ * mi/mi-cmd-stack.c (mi_cmd_stack_select_frame): Use
+ select_frame_from_spec. Catch errors.
+ (NEWS): Mention changes to frame related commands.
+
+2015-09-11 Andrew Burgess <andrew.burgess@embecosm.com>
+
* stack.c (select_and_print_frame): Delete.
(func_command): Most content moved into new function
find_frame_for_function, use new function, print result, add
@@ -3,6 +3,26 @@
*** Changes since GDB 7.10
+* Changes to the "frame", "select-frame", and "info frame" commands.
+ Selecting frames by number remains unchanged, however, selecting
+ frames by stack-address, or creating new frames now requires the use
+ of a sub-command. Various sub-commands now exist for the various
+ methods of selecting a frame; level, address, function, and create.
+ As an example, here are the variants of "frame" that are now available:
+ - frame <number>
+ - frame level <number>
+ Both of these select frame at level <number>.
+ - frame address <address>
+ Select frame for <address>.
+ - frame function <name>
+ Select inner most frame for function <name>.
+ - frame create <stack-address>
+ Create a frame for <stack-address>.
+ - frame create <stack-address> <pc-address>
+ Create a frame for <stack-address> <pc-address>.
+ There are similar variants for the "select-frame" and "info frame"
+ commands.
+
* Support for tracepoints on aarch64-linux was added in GDBserver.
* The 'record instruction-history' command now indicates speculative execution
@@ -1,5 +1,11 @@
2015-09-11 Andrew Burgess <andrew.burgess@embecosm.com>
+ * gdb.texinfo (Selection): Rewrite documentation for 'frame' and
+ 'select-frame' commands.
+ (Frame Info): Rewrite documentation for 'info frame' command.
+
+2015-09-11 Andrew Burgess <andrew.burgess@embecosm.com>
+
* gdb.texinfo (Frames): Remove 'frame' and 'select-frame'
description.
(Frame Filter Management): Move to later in the 'Examining the
@@ -7158,21 +7158,58 @@ of the stack frame just selected.
@table @code
@kindex frame@r{, selecting}
@kindex f @r{(@code{frame})}
-@item frame @var{n}
-@itemx f @var{n}
-Select frame number @var{n}. Recall that frame zero is the innermost
-(currently executing) frame, frame one is the frame that called the
-innermost one, and so on. The highest-numbered frame is the one for
-@code{main}.
+@item frame @r{[} @var{frame-selection-spec} @r{]}
+@item f @r{[} @var{frame-selection-spec} @r{]}
+The @command{frame} command allows different stack frames to be
+selected. The @var{frame-selection-spec} can be any of the following:
+
+@table @code
+@kindex frame level
+@item @var{num}
+@item level @var{num}
+Select frame number @var{num}. Recall that frame zero is the
+innermost (currently executing) frame, frame one is the frame that
+called the innermost one, and so on. The highest-numbered frame is
+the one for @code{main}.
+
+As this is the most common method of navigating the frame stack then
+the string @command{level} can be dropped, the following two commands
+are equivalent:
+
+@smallexample
+(@value{GDBP}) frame 3
+(@value{GDBP}) frame level 3
+@end smallexample
-@item frame @var{stack-addr} [ @var{pc-addr} ]
-@itemx f @var{stack-addr} [ @var{pc-addr} ]
-Select the frame at address @var{stack-addr}. This is useful mainly if the
-chaining of stack frames has been damaged by a bug, making it
-impossible for @value{GDBN} to assign numbers properly to all frames. In
-addition, this can be useful when your program has multiple stacks and
-switches between them. The optional @var{pc-addr} can also be given to
-specify the value of PC for the stack frame.
+@kindex frame address
+@item address @var{stack-address}
+Select the frame with stack address @var{stack-address}. Recall that
+each stack frame has a stack frame address, which roughly corresponds
+to the location on the stack where the stack frame local variables are
+stored.
+
+@kindex frame function
+@item function @var{function-name}
+Select the stack frame for function @var{function-name}. If there are
+multiple stack frames for function @var{function-name} then the inner
+most stack frame is selected.
+
+@kindex frame create
+@item create @var{stack-address} @r{[} @var{pc-addr} @r{]}
+Create and then select a new frame at stack address @var{stack-addr}.
+This is useful mainly if the chaining of stack frames has been damaged
+by a bug, making it impossible for @value{GDBN} to assign numbers
+properly to all frames. In addition, this can be useful when your
+program has multiple stacks and switches between them. The optional
+@var{pc-addr} can also be given to specify the value of PC for the
+stack frame.
+
+When a frame has been created and selected uing @command{frame create}
+then you can always return to the original stack using one of the
+previous stack frame selection instructions, for example
+@command{frame level 0}.
+
+@end table
@kindex up
@item up @var{n}
@@ -7215,11 +7252,13 @@ for details.
@table @code
@kindex select-frame
-@item select-frame
+@item select-frame @r{[} @var{frame-selection-spec} @r{]}
The @code{select-frame} command is a variant of @code{frame} that does
not display the new frame after selecting it. This command is
intended primarily for use in @value{GDBN} command scripts, where the
-output might be unnecessary and distracting.
+output might be unnecessary and distracting. The
+@var{frame-selection-spec} is as for the @command{frame} command
+described in @ref{Selection, ,Selecting a Frame}.
@kindex down-silently
@kindex up-silently
@@ -7277,13 +7316,12 @@ which registers were saved in the frame
something has gone wrong that has made the stack format fail to fit
the usual conventions.
-@item info frame @var{addr}
-@itemx info f @var{addr}
-Print a verbose description of the frame at address @var{addr}, without
-selecting that frame. The selected frame remains unchanged by this
-command. This requires the same kind of address (more than one for some
-architectures) that you specify in the @code{frame} command.
-@xref{Selection, ,Selecting a Frame}.
+@item info frame @r{[} @var{frame-selection-spec} @r{]}
+@itemx info f @r{[} @var{frame-selection-spec} @r{]}
+Print a verbose description of the frame selected by
+@var{frame-selection-spec}. The @var{frame-selection-spec} is the
+same as for the @command{frame} command (@pxref{Selection, ,Selecting
+a Frame}). The selected frame remains unchanged by this command.
@kindex info args
@item info args
@@ -697,10 +697,18 @@ list_args_or_locals (enum what_to_list what, enum print_values values,
void
mi_cmd_stack_select_frame (char *command, char **argv, int argc)
{
- if (argc == 0 || argc > 1)
- error (_("-stack-select-frame: Usage: FRAME_SPEC"));
-
- select_frame_command (argv[0], 1 /* not used */ );
+ TRY
+ {
+ select_frame_from_spec (argv);
+ }
+ CATCH (except, RETURN_MASK_ERROR)
+ {
+ const char *msg = except.message;
+ if (msg == NULL)
+ msg = _("Unknown error");
+ error (_("-stack-select-frame: %s"), msg);
+ }
+ END_CATCH
}
void
@@ -100,6 +100,9 @@ static void set_last_displayed_sal (int valid,
struct symtab *symtab,
int line);
+static struct frame_info * find_frame_for_function (char *);
+static struct frame_info * find_frame_for_address (CORE_ADDR);
+
/* Zero means do things normally; we are interacting directly with the
user. One means print the full filename and linenumber when a
frame is printed, and do so in a format emacs18/emacs19.22 can
@@ -1273,130 +1276,254 @@ print_frame (struct frame_info *frame, int print_level,
}
-/* Read a frame specification in whatever the appropriate format is from
- FRAME_EXP. Call error() if the specification is in any way invalid (so
- this function never returns NULL). When SEPECTED_P is non-NULL set its
- target to indicate that the default selected frame was used. */
+/* The stack frame selection mode as specified by the user in commands such
+ as "info frame <SPEC>" and "frame <SPEC>". */
+enum frame_selection_mode
+ {
+ /* Default is what you get when the user does not specify a specific
+ mode. */
+ frame_mode_default,
+
+ /* Select a frame by level in the stack. Takes a single integer
+ parameter. */
+ frame_mode_level,
-static struct frame_info *
-parse_frame_specification (const char *frame_exp, int *selected_frame_p)
+ /* Select a frame by stack frame address. Takes a single address
+ parameter. */
+ frame_mode_address,
+
+ /* Select a frame by function name. Takes the name of a function as a
+ parameter, selects the inner-most frame matching that function. */
+ frame_mode_function,
+
+ /* Create a new frame. Takes either one or two address parameters and
+ constructs a new frame. */
+ frame_mode_create,
+ };
+
+/* Maximum number of args for frame selection specification. */
+
+#define FRAME_SELECTION_MAX_ARGS 2
+
+/* Structure to hold a parsed frame selection specification. */
+
+struct frame_selection_spec
{
+ /* The mode of the frame selection. */
+ enum frame_selection_mode mode;
+
+ /* The number of arguments in the ARGS array. */
int numargs;
- struct value *args[4];
- CORE_ADDR addrs[ARRAY_SIZE (args)];
- if (frame_exp == NULL)
- numargs = 0;
- else
- {
- numargs = 0;
- while (1)
- {
- char *addr_string;
- struct cleanup *cleanup;
- const char *p;
+ /* Array of strings, copied, and from the frame selection specification
+ string. Each is either NULL or allocated with malloc. */
+ char *args [FRAME_SELECTION_MAX_ARGS];
+};
- /* Skip leading white space, bail of EOL. */
- frame_exp = skip_spaces_const (frame_exp);
- if (!*frame_exp)
- break;
+/* Compare ARG to all the possible frame selection mode strings. If ARG
+ matches then the selected frame mode is placed into MODE and true is
+ returned. If ARG does not match any of the frame selection modes then
+ the contents of MODE are unchanged, and false is returned.
+
+ The matching of ARG against the mode selection strings is case
+ insensitive, and ARG can be any sub-string of a mode string, starting
+ from the first character to count as a match. So, "LE" matches
+ "level", and "a" matches "address". */
+
+static int
+is_frame_mode_string (const char *arg, enum frame_selection_mode *mode)
+{
+ int i;
+ static const struct
+ {
+ const char *mode_str;
+ enum frame_selection_mode mode_val;
+ } mode_list [] =
+ {
+ { "level", frame_mode_level },
+ { "address", frame_mode_address },
+ { "function", frame_mode_function },
+ { "create", frame_mode_create }
+ };
- /* Parse the argument, extract it, save it. */
- for (p = frame_exp;
- *p && !ISSPACE (*p);
- p++);
- addr_string = savestring (frame_exp, p - frame_exp);
- frame_exp = p;
- cleanup = make_cleanup (xfree, addr_string);
-
- /* NOTE: Parse and evaluate expression, but do not use
- functions such as parse_and_eval_long or
- parse_and_eval_address to also extract the value.
- Instead value_as_long and value_as_address are used.
- This avoids problems with expressions that contain
- side-effects. */
- if (numargs >= ARRAY_SIZE (args))
- error (_("Too many args in frame specification"));
- args[numargs++] = parse_and_eval (addr_string);
-
- do_cleanups (cleanup);
+ for (i = 0; i < ARRAY_SIZE (mode_list); ++i)
+ {
+ if ((strlen (arg) <= strlen (mode_list [i].mode_str))
+ && (strncasecmp (arg, mode_list [i].mode_str, strlen (arg)) == 0))
+ {
+ *mode = mode_list [i].mode_val;
+ return 1;
}
}
+ return 0;
+}
- /* If no args, default to the selected frame. */
- if (numargs == 0)
+/* Parse a frame selection specification in ARGV and place the result into
+ SPEC. If the specification in ARGV is invalid then an error is thrown,
+ in which case the contents of SPEC are undefined, but no memory will
+ have been allocated for the args in SPEC. If this function returns then
+ SPEC is valid. */
+
+static void
+parse_frame_selection_spec (char **argv,
+ struct frame_selection_spec *spec)
+{
+ int i;
+
+ spec->mode = frame_mode_default;
+ spec->numargs = 0;
+ for (i = 0; i < FRAME_SELECTION_MAX_ARGS; ++i)
+ spec->args [i] = NULL;
+
+ /* Check for no args case. */
+ if (argv == NULL || *argv == NULL)
+ return;
+
+ /* Is the first arg a frame mode string? */
+ if (is_frame_mode_string (*argv, &spec->mode))
+ argv++;
+
+ /* Now process (copy) the remaining args. */
+ for (/* */ ;*argv != NULL; ++argv)
{
- if (selected_frame_p != NULL)
- (*selected_frame_p) = 1;
- return get_selected_frame (_("No stack."));
+ if (spec->numargs >= FRAME_SELECTION_MAX_ARGS)
+ {
+ for (i = 0; i < spec->numargs; ++i)
+ xfree (spec->args [i]);
+ error (_("Too many args in frame specification."));
+ }
+
+ spec->args [spec->numargs++] = xstrdup (*argv);
}
+}
+
+/* Free resource associated with a struct frame_selection_spec passed in
+ ARG. */
- /* None of the remaining use the selected frame. */
- if (selected_frame_p != NULL)
- (*selected_frame_p) = 0;
+static void
+free_frame_selection_spec (void *arg)
+{
+ int i;
+ struct frame_selection_spec *spec = (struct frame_selection_spec *) arg;
- /* Assume the single arg[0] is an integer, and try using that to
- select a frame relative to current. */
- if (numargs == 1)
+ for (i = 0; i < spec->numargs; ++i)
+ xfree (spec->args [i]);
+}
+
+/* Read a frame specification that has been split into ARGV, and return the
+ specified frame. Call error() if the specification is in any way
+ invalid (so this function never returns NULL). When SEPECTED_P is
+ non-NULL set its target to indicate that the default selected frame was
+ used. */
+
+static struct frame_info *
+parse_frame_specification (char **argv, int *selected_frame_p)
+{
+ struct frame_selection_spec spec;
+ struct cleanup *old_chain;
+ struct frame_info *fid = NULL;
+
+ parse_frame_selection_spec (argv, &spec);
+ old_chain = make_cleanup (free_frame_selection_spec, &spec);
+
+ do
{
- struct frame_info *fid;
- int level = value_as_long (args[0]);
+ if (spec.mode == frame_mode_default && spec.numargs == 0)
+ {
+ if (selected_frame_p != NULL)
+ (*selected_frame_p) = 1;
+ fid = get_selected_frame (_("No stack."));
+ break;
+ }
- fid = find_relative_frame (get_current_frame (), &level);
- if (level == 0)
- /* find_relative_frame was successful. */
- return fid;
- }
+ /* None of the remaining use the selected frame. */
+ if (selected_frame_p != NULL)
+ (*selected_frame_p) = 0;
- /* Convert each value into a corresponding address. */
- {
- int i;
+ if ((spec.mode == frame_mode_create && spec.numargs > 2)
+ || (spec.mode != frame_mode_create && spec.numargs > 1))
+ error (_("Too many args in frame specification."));
- for (i = 0; i < numargs; i++)
- addrs[i] = value_as_address (args[i]);
- }
+ if (spec.mode == frame_mode_level || spec.mode == frame_mode_default)
+ {
+ int level;
- /* Assume that the single arg[0] is an address, use that to identify
- a frame with a matching ID. Should this also accept stack/pc or
- stack/pc/special. */
- if (numargs == 1)
- {
- struct frame_id id = frame_id_build_wild (addrs[0]);
- struct frame_info *fid;
-
- /* If (s)he specifies the frame with an address, he deserves
- what (s)he gets. Still, give the highest one that matches.
- (NOTE: cagney/2004-10-29: Why highest, or outer-most, I don't
- know). */
- for (fid = get_current_frame ();
- fid != NULL;
- fid = get_prev_frame (fid))
+ level = value_as_long (parse_and_eval (spec.args [0]));
+ fid = find_relative_frame (get_current_frame (), &level);
+ if (level == 0)
+ /* find_relative_frame was successful. */
+ break;
+ error (_("No frame at level %s."), spec.args [0]);
+ }
+ else if (spec.mode == frame_mode_function)
{
- if (frame_id_eq (id, get_frame_id (fid)))
- {
- struct frame_info *prev_frame;
+ fid = find_frame_for_function (spec.args [0]);
+ if (fid != NULL)
+ break;
+ error (_("No frame for function \"%s\"."), spec.args [0]);
+ }
+ else
+ {
+ CORE_ADDR addr [FRAME_SELECTION_MAX_ARGS] = { 0 };
+ int i;
- while (1)
- {
- prev_frame = get_prev_frame (fid);
- if (!prev_frame
- || !frame_id_eq (id, get_frame_id (prev_frame)))
- break;
- fid = prev_frame;
- }
- return fid;
+ for (i = 0; i < spec.numargs; ++i)
+ addr [i] = value_as_address (parse_and_eval (spec.args [i]));
+
+ if (spec.mode == frame_mode_address)
+ {
+ fid = find_frame_for_address (addr [0]);
+ if (fid != NULL)
+ break;
+ error (_("No frame at address %s."), spec.args [0]);
+ }
+ else if (spec.mode == frame_mode_create)
+ {
+ if (spec.numargs == 1)
+ fid = create_new_frame (addr [0], 0);
+ else if (spec.numargs == 2)
+ fid = create_new_frame (addr [0], addr [1]);
+ break;
}
}
- }
- /* We couldn't identify the frame as an existing frame, but
- perhaps we can create one with a single argument. */
- if (numargs == 1)
- return create_new_frame (addrs[0], 0);
- else if (numargs == 2)
- return create_new_frame (addrs[0], addrs[1]);
- else
- error (_("Too many args in frame specification"));
+ internal_error (__FILE__, __LINE__,
+ "unhandled case during frame selection");
+ }
+ while (0);
+
+ /* All error cases should be picked up in the above code. If we get here
+ then we should have found a valid frame. */
+ gdb_assert (fid != NULL);
+ do_cleanups (old_chain);
+ return fid;
+}
+
+/* Completion function for "frame" and "info frame" commands. */
+
+static VEC (char_ptr) *
+frame_selection_completer (struct cmd_list_element *ignore,
+ const char *text, const char *word)
+{
+ if (text == word)
+ {
+ VEC (const_char_ptr) *completion_name_vec = NULL;
+ VEC (char_ptr) *matches_vec;
+
+ VEC_safe_push (const_char_ptr, completion_name_vec, "level");
+ VEC_safe_push (const_char_ptr, completion_name_vec, "function");
+ VEC_safe_push (const_char_ptr, completion_name_vec, "address");
+ VEC_safe_push (const_char_ptr, completion_name_vec, "create");
+ VEC_safe_push (const_char_ptr, completion_name_vec, NULL);
+
+ matches_vec
+ = complete_on_enum (VEC_address (const_char_ptr, completion_name_vec),
+ text, word);
+ VEC_free (const_char_ptr, completion_name_vec);
+ return matches_vec;
+ }
+
+ return make_symbol_completion_list (text, word);
}
/* Print verbosely the selected frame or the frame at address
@@ -1422,8 +1549,11 @@ frame_info (char *addr_exp, int from_tty)
/* Initialize it to avoid "may be used uninitialized" warning. */
CORE_ADDR caller_pc = 0;
int caller_pc_p = 0;
+ char **argv;
- fi = parse_frame_specification (addr_exp, &selected_frame_p);
+ argv = gdb_buildargv (addr_exp);
+ make_cleanup_freeargv (argv);
+ fi = parse_frame_specification (argv, &selected_frame_p);
gdbarch = get_frame_arch (fi);
/* During the following value will be created and then displayed.
@@ -2266,17 +2396,28 @@ find_relative_frame (struct frame_info *frame, int *level_offset_ptr)
return frame;
}
+void
+select_frame_from_spec (char **argv)
+{
+ select_frame (parse_frame_specification (argv, NULL));
+}
+
/* The "select_frame" command. With no argument this is a NOP.
- Select the frame at level LEVEL_EXP if it is a valid level.
- Otherwise, treat LEVEL_EXP as an address expression and select it.
+ Select the frame according to LEVEL_EXP.
See parse_frame_specification for more info on proper frame
expressions. */
-void
+static void
select_frame_command (char *level_exp, int from_tty)
{
- select_frame (parse_frame_specification (level_exp, NULL));
+ char **argv;
+ struct cleanup *old_chain;
+
+ argv = gdb_buildargv (level_exp);
+ old_chain = make_cleanup_freeargv (argv);
+ select_frame_from_spec (argv);
+ do_cleanups (old_chain);
}
/* The "frame" command. With no argument, print the selected frame
@@ -2574,6 +2715,43 @@ func_command (char *arg, int from_tty)
}
}
+/* Find inner-mode frame with frame address ADDRESS. Return NULL if no
+ matching frame can be found. */
+
+static struct frame_info *
+find_frame_for_address (CORE_ADDR address)
+{
+ struct frame_id id;
+ struct frame_info *fid;
+
+ id = frame_id_build_wild (address);
+
+ /* If (s)he specifies the frame with an address, he deserves
+ what (s)he gets. Still, give the highest one that matches.
+ (NOTE: cagney/2004-10-29: Why highest, or outer-most, I don't
+ know). */
+ for (fid = get_current_frame ();
+ fid != NULL;
+ fid = get_prev_frame (fid))
+ {
+ if (frame_id_eq (id, get_frame_id (fid)))
+ {
+ struct frame_info *prev_frame;
+
+ while (1)
+ {
+ prev_frame = get_prev_frame (fid);
+ if (!prev_frame
+ || !frame_id_eq (id, get_frame_id (prev_frame)))
+ break;
+ fid = prev_frame;
+ }
+ return fid;
+ }
+ }
+ return NULL;
+}
+
/* Provide a prototype to silence -Wmissing-prototypes. */
@@ -2582,6 +2760,8 @@ void _initialize_stack (void);
void
_initialize_stack (void)
{
+ struct cmd_list_element *cmd;
+
add_com ("return", class_stack, return_command, _("\
Make selected stack frame return to its caller.\n\
Control remains in the debugger, but when you continue\n\
@@ -2604,20 +2784,35 @@ An argument says how many frames down to go."));
Same as the `down' command, but does not print anything.\n\
This is useful in command scripts."));
- add_com ("frame", class_stack, frame_command, _("\
-Select and print a stack frame.\nWith no argument, \
-print the selected stack frame. (See also \"info frame\").\n\
-An argument specifies the frame to select.\n\
-It can be a stack frame number or the address of the frame.\n\
-With argument, nothing is printed if input is coming from\n\
-a command file or a user-defined command."));
+ cmd = add_com ("frame", class_stack, frame_command, _("\
+Select and print a stack frame.\n\
+With no arguments, print the selected stack frame. \
+(See also \"info frame\").\n\
+Alternatively a frame specification may be given to select a specific\n\
+stack frame. The available frame specifications are:\n\
+\n\
+Select a stack frame by number:\n\
+ frame <number>\n\
+ frame level <number>\n\
+\n\
+Select a stack frame by the frames stack frame address:\n\
+ frame address <stack-address>\n\
+\n\
+Select the inner most frame for a function of a given name:\n\
+ frame function <name>\n\
+\n\
+Create a new temporary frame for a given stack frame address and PC:\n\
+ frame create <stack-address>\n\
+ frame create <stack-address> <pc-address>"));
+ set_cmd_completer (cmd, frame_selection_completer);
add_com_alias ("f", "frame", class_stack, 1);
- add_com ("select-frame", class_stack, select_frame_command, _("\
+ cmd = add_com ("select-frame", class_stack, select_frame_command, _("\
Select a stack frame without printing anything.\n\
-An argument specifies the frame to select.\n\
-It can be a stack frame number or the address of the frame.\n"));
+An argument specifies the frame to select, and is the same frame\n\
+specification as for the \"frame\" command."));
+ set_cmd_completer (cmd, frame_selection_completer);
add_com ("backtrace", class_stack, backtrace_command, _("\
Print backtrace of all stack frames, or innermost COUNT frames.\n\
@@ -2631,8 +2826,13 @@ on this backtrace.\n"));
add_info ("stack", backtrace_command,
_("Backtrace of the stack, or innermost COUNT frames."));
add_info_alias ("s", "stack", 1);
- add_info ("frame", frame_info,
- _("All about selected stack frame, or frame at ADDR."));
+ cmd = add_info ("frame", frame_info,
+ _("All about the selected stack frame.\n\
+With no arguments, displays information about the currently selected stack\n\
+frame. Alternatively a frame specification may be provided (See \"frame\")\n\
+the information is then printed about the specified frame."));
+ set_cmd_completer (cmd, frame_selection_completer);
+
add_info_alias ("f", "frame", 1);
add_info ("locals", locals_info,
_("Local variables of current stack frame."));
@@ -20,7 +20,7 @@
#ifndef STACK_H
#define STACK_H
-void select_frame_command (char *level_exp, int from_tty);
+void select_frame_from_spec (char **argv);
void find_frame_funname (struct frame_info *frame, char **funname,
enum language *funlang, struct symbol **funcp);
@@ -1,5 +1,11 @@
2015-09-11 Andrew Burgess <andrew.burgess@embecosm.com>
+ * gdb.base/frame-cmds.exp: Almost complete rewrite.
+ * gdb.base/frame-cmds.c: Extend.
+ * gdb.mi/mi-var-frame.exp: Update a few tests. Add one new test.
+
+2015-09-11 Andrew Burgess <andrew.burgess@embecosm.com>
+
* gdb.base/dbx.exp (test_func): Remove xfails, update expected
results.
@@ -28,7 +28,25 @@ frame_1 (void)
}
int
+recursive (int arg)
+{
+ int v;
+
+ if (arg < 2)
+ v = recursive (arg + 1);
+ else
+ v = frame_2 ();
+
+ return v;
+}
+
+int
main (void)
{
- return frame_1 ();
+ int i, j;
+
+ i = frame_1 ();
+ j = recursive (0);
+
+ return i + j;
}
@@ -60,11 +60,22 @@ mi_gdb_test "-var-create R * $register" \
"create varobj 'R' for register '$register'"
for {set i 0} {$i < 5} {incr i} {
- mi_gdb_test "-stack-select-frame $i" \
- {\^done} \
- "-stack-select-frame $i"
+
+ if { $i < 3 } then {
+ mi_gdb_test "-stack-select-frame $i" \
+ {\^done} \
+ "-stack-select-frame $i"
+ } else {
+ mi_gdb_test "-stack-select-frame create $i" \
+ {\^done} \
+ "-stack-select-frame create frame at $i"
+ }
mi_gdb_test "-var-update R" \
"\\^done,changelist=\\\[\\\]" \
"update 'R' in frame $i: no change"
}
+
+mi_gdb_test "-stack-select-frame 5" \
+ {\^error,msg="-stack-select-frame: No frame at level 5."} \
+ "-stack-select-frame 5"