* [PATCH 2/9] gdb: Select a frame for frame_info.
2015-09-11 18:49 [PATCH 0/9] Changes to frame selection Andrew Burgess
@ 2015-09-11 18:49 ` Andrew Burgess
2015-09-11 18:50 ` [PATCH 7/9] gdb: Simplify parse_frame_specification Andrew Burgess
` (8 subsequent siblings)
9 siblings, 0 replies; 25+ messages in thread
From: Andrew Burgess @ 2015-09-11 18:49 UTC (permalink / raw)
To: gdb-patches; +Cc: Andrew Burgess
Within the 'info frame' command (implemented in the frame_info function)
gdb will create register values, which are then displayed to the user.
These register values will be created as lazy value. As part of
fetching the value of a lazy register value we must find the frame in
which the value was created based on the frame id, which is stored in
the value, this is done with a call to frame_find_by_id.
In a previous commit I already addressed the problem that
frame_find_by_id did not used to consider the selected frame when trying
to find a frame. This is now fixed.
However, if in frame_info the user passed a frame specification, then it
is possible that a brand new frame will have been created, a frame
outside of the current backtrace, and also not the currently selected
frame. So, usually, something like, 'info frame 4' will cause gdb to
crash with an assertion failure. This can be especially annoying if the
user accidentally types 'info frame 4' intending to ask about the fourth
stack frame, but, there happens to only be 3 stack frames at present.
The solution I propose here is that frame_info should temporarily select
the frame identified by the user. The previously selected frame will be
restored at the end of the function.
gdb/ChangeLog:
* frame.h (make_restore_selected_frame_cleanup): Declare new
function.
* frame.c (do_restore_selected_frame): New function.
(make_restore_selected_frame_cleanup): Define new function.
* stack.c (frame_info): Temporarily select frame for duration of
this function.
gdb/testsuite/ChangeLog:
* gdb.base/create-frame.exp: Add test for 'info frame' with
specific address.
---
gdb/ChangeLog | 9 +++++++++
gdb/frame.c | 21 +++++++++++++++++++++
gdb/frame.h | 4 ++++
gdb/stack.c | 10 ++++++++++
gdb/testsuite/ChangeLog | 5 +++++
gdb/testsuite/gdb.base/frame-cmds.exp | 8 +++++++-
6 files changed, 56 insertions(+), 1 deletion(-)
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index b4fe9cc..79952c7 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,14 @@
2015-09-11 Andrew Burgess <andrew.burgess@embecosm.com>
+ * frame.h (make_restore_selected_frame_cleanup): Declare new
+ function.
+ * frame.c (do_restore_selected_frame): New function.
+ (make_restore_selected_frame_cleanup): Define new function.
+ * stack.c (frame_info): Temporarily select frame for duration of
+ this function.
+
+2015-09-11 Andrew Burgess <andrew.burgess@embecosm.com>
+
* frame.c (frame_find_by_id): Also check the selected frame.
2015-09-11 Pierre Langlois <pierre.langlois@arm.com>
diff --git a/gdb/frame.c b/gdb/frame.c
index 114fa6a..f964fd8 100644
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -2753,6 +2753,27 @@ frame_prepare_for_sniffer (struct frame_info *frame,
return make_cleanup (frame_cleanup_after_sniffer, frame);
}
+/* Used as a clean-up to restore the selected frame. */
+
+static void
+do_restore_selected_frame (void *arg)
+{
+ struct frame_info *fi = (struct frame_info *) arg;
+
+ select_frame (fi);
+}
+
+/* See frame.h. */
+
+struct cleanup *
+make_restore_selected_frame_cleanup (void)
+{
+ struct frame_info *fi;
+
+ fi = get_selected_frame_if_set ();
+ return make_cleanup (do_restore_selected_frame, fi);
+}
+
extern initialize_file_ftype _initialize_frame; /* -Wmissing-prototypes */
static struct cmd_list_element *set_backtrace_cmdlist;
diff --git a/gdb/frame.h b/gdb/frame.h
index 03f3892..c7c90cf 100644
--- a/gdb/frame.h
+++ b/gdb/frame.h
@@ -820,5 +820,9 @@ extern int frame_unwinder_is (struct frame_info *fi,
extern enum language get_frame_language (struct frame_info *frame);
+/* Create a clean-up to restore the selected frame. This includes
+ restoring the selected frame to NULL if that is its current value. */
+
+extern struct cleanup * make_restore_selected_frame_cleanup (void);
#endif /* !defined (FRAME_H) */
diff --git a/gdb/stack.c b/gdb/stack.c
index 7d37dd1..82b366d 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -1434,6 +1434,16 @@ frame_info (char *addr_exp, int from_tty)
fi = parse_frame_specification_1 (addr_exp, "No stack.", &selected_frame_p);
gdbarch = get_frame_arch (fi);
+ /* During the following value will be created and then displayed.
+ Displaying a value can require using frame_find_by_id, so we must make
+ sure that the frame FI is findable using frame_find_by_id. As it is
+ possible that the frame specification caused a new frame to be
+ created, one outside of the current stack trace, and different to the
+ currently selected frame, then the only way to ensure that we can find
+ this frame again later is if we temporarily select this new frame. */
+ make_restore_selected_frame_cleanup ();
+ select_frame (fi);
+
/* Name of the value returned by get_frame_pc(). Per comments, "pc"
is not a good name. */
if (gdbarch_pc_regnum (gdbarch) >= 0)
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index cf83b3a..ee0ad76 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,10 @@
2015-09-11 Andrew Burgess <andrew.burgess@embecosm.com>
+ * gdb.base/create-frame.exp: Add test for 'info frame' with
+ specific address.
+
+2015-09-11 Andrew Burgess <andrew.burgess@embecosm.com>
+
* gdb.mi/mi-var-frame.c: New file.
* gdb.mi/mi-var-frame.exp: New file.
* gdb.base/frame-cmds.c: New file.
diff --git a/gdb/testsuite/gdb.base/frame-cmds.exp b/gdb/testsuite/gdb.base/frame-cmds.exp
index 2518463..e285a4e 100644
--- a/gdb/testsuite/gdb.base/frame-cmds.exp
+++ b/gdb/testsuite/gdb.base/frame-cmds.exp
@@ -27,4 +27,10 @@ gdb_test "bt" "#0.*#1.*#2.*" "backtrace at breakpoint"
gdb_test_no_output "select-frame 3"
gdb_test "info frame" "Stack level 0, frame at 0x3:.*" \
- "info frame for created frame"
+ "info frame for currently selected frame, at 0x3"
+
+gdb_test "info frame 4" "Stack frame at 0x4:.*" \
+ "info frame for specific frame, created at 0x4"
+
+gdb_test "info frame" "Stack level 0, frame at 0x3:.*" \
+ "info frame for currently selected frame (again), at 0x3"
--
2.5.1
^ permalink raw reply [flat|nested] 25+ messages in thread* [PATCH 7/9] gdb: Simplify parse_frame_specification.
2015-09-11 18:49 [PATCH 0/9] Changes to frame selection Andrew Burgess
2015-09-11 18:49 ` [PATCH 2/9] gdb: Select a frame for frame_info Andrew Burgess
@ 2015-09-11 18:50 ` Andrew Burgess
2015-09-30 13:50 ` Pedro Alves
2015-09-11 18:50 ` [PATCH 6/9] gdb: Avoid unneeded calls to parse_frame_specification Andrew Burgess
` (7 subsequent siblings)
9 siblings, 1 reply; 25+ messages in thread
From: Andrew Burgess @ 2015-09-11 18:50 UTC (permalink / raw)
To: gdb-patches; +Cc: Andrew Burgess
Remove an unneeded parameter from parse_frame_specification, replace
with a fixed string within parse_frame_specification. The message was
the same in every place that parse_frame_specification was used anyway.
gdb/ChangeLog:
* stack.c (parse_frame_specification): Remove message parameter,
replace with fixed string in function body, update function
comment.
(frame_info): Remove message to parse_frame_specification.
(select_frame_command): Likewise.
---
gdb/ChangeLog | 8 ++++++++
gdb/stack.c | 18 ++++++++----------
2 files changed, 16 insertions(+), 10 deletions(-)
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index dccac52..d530d06 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,13 @@
2015-09-11 Andrew Burgess <andrew.burgess@embecosm.com>
+ * stack.c (parse_frame_specification): Remove message parameter,
+ replace with fixed string in function body, update function
+ comment.
+ (frame_info): Remove message to parse_frame_specification.
+ (select_frame_command): Likewise.
+
+2015-09-11 Andrew Burgess <andrew.burgess@embecosm.com>
+
* stack.c (parse_frame_specification): Delete.
(parse_frame_specification_1): Rename to
parse_frame_specification.
diff --git a/gdb/stack.c b/gdb/stack.c
index 1bc1fe6..9cde1e5 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -1273,15 +1273,13 @@ print_frame (struct frame_info *frame, int print_level,
}
\f
-/* Read a frame specification in whatever the appropriate format is
- from FRAME_EXP. Call error(), printing MESSAGE, 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. */
+/* 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. */
static struct frame_info *
-parse_frame_specification (const char *frame_exp, const char *message,
- int *selected_frame_p)
+parse_frame_specification (const char *frame_exp, int *selected_frame_p)
{
int numargs;
struct value *args[4];
@@ -1330,7 +1328,7 @@ parse_frame_specification (const char *frame_exp, const char *message,
{
if (selected_frame_p != NULL)
(*selected_frame_p) = 1;
- return get_selected_frame (message);
+ return get_selected_frame (_("No stack."));
}
/* None of the remaining use the selected frame. */
@@ -1425,7 +1423,7 @@ frame_info (char *addr_exp, int from_tty)
CORE_ADDR caller_pc = 0;
int caller_pc_p = 0;
- fi = parse_frame_specification (addr_exp, "No stack.", &selected_frame_p);
+ fi = parse_frame_specification (addr_exp, &selected_frame_p);
gdbarch = get_frame_arch (fi);
/* During the following value will be created and then displayed.
@@ -2287,7 +2285,7 @@ find_relative_frame (struct frame_info *frame, int *level_offset_ptr)
void
select_frame_command (char *level_exp, int from_tty)
{
- select_frame (parse_frame_specification (level_exp, "No stack.", NULL));
+ select_frame (parse_frame_specification (level_exp, NULL));
}
/* The "frame" command. With no argument, print the selected frame
--
2.5.1
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [PATCH 7/9] gdb: Simplify parse_frame_specification.
2015-09-11 18:50 ` [PATCH 7/9] gdb: Simplify parse_frame_specification Andrew Burgess
@ 2015-09-30 13:50 ` Pedro Alves
0 siblings, 0 replies; 25+ messages in thread
From: Pedro Alves @ 2015-09-30 13:50 UTC (permalink / raw)
To: Andrew Burgess, gdb-patches
On 09/11/2015 07:49 PM, Andrew Burgess wrote:
> Remove an unneeded parameter from parse_frame_specification, replace
> with a fixed string within parse_frame_specification. The message was
> the same in every place that parse_frame_specification was used anyway.
>
> gdb/ChangeLog:
>
> * stack.c (parse_frame_specification): Remove message parameter,
> replace with fixed string in function body, update function
> comment.
> (frame_info): Remove message to parse_frame_specification.
> (select_frame_command): Likewise.
OK.
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 6/9] gdb: Avoid unneeded calls to parse_frame_specification.
2015-09-11 18:49 [PATCH 0/9] Changes to frame selection Andrew Burgess
2015-09-11 18:49 ` [PATCH 2/9] gdb: Select a frame for frame_info Andrew Burgess
2015-09-11 18:50 ` [PATCH 7/9] gdb: Simplify parse_frame_specification Andrew Burgess
@ 2015-09-11 18:50 ` Andrew Burgess
2015-09-30 13:48 ` Pedro Alves
2015-09-11 18:50 ` [PATCH 9/9] gdb: Change how frames are selected for 'frame' and 'info frame' Andrew Burgess
` (6 subsequent siblings)
9 siblings, 1 reply; 25+ messages in thread
From: Andrew Burgess @ 2015-09-11 18:50 UTC (permalink / raw)
To: gdb-patches; +Cc: Andrew Burgess
Within the stack command there are a couple of places where fixed
strings are passed into functions that are really intended for
processing user input. These fixed strings are then processed and the
result returned.
Given that the input strings in these cases are fixed, and are always
"0", then the result will always be the same, the current frame. By
switching to using get_current_frame instead the code can be simplified,
and the intention of the code is clearer.
gdb/ChangeLog:
* stack.c (parse_frame_specification): Delete.
(parse_frame_specification_1): Rename to
parse_frame_specification.
(frame_info): Use parse_frame_specification.
(select_frame_command): Likewise.
(return_command): Use select_frame and print_stack_frame rather
than frame_command and select_frame_command.
(func_command): Use get_current_frame rather than
parse_frame_specification.
---
gdb/ChangeLog | 12 ++++++++++++
gdb/stack.c | 21 +++++++--------------
2 files changed, 19 insertions(+), 14 deletions(-)
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 7c4b567..dccac52 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,17 @@
2015-09-11 Andrew Burgess <andrew.burgess@embecosm.com>
+ * stack.c (parse_frame_specification): Delete.
+ (parse_frame_specification_1): Rename to
+ parse_frame_specification.
+ (frame_info): Use parse_frame_specification.
+ (select_frame_command): Likewise.
+ (return_command): Use select_frame and print_stack_frame rather
+ than frame_command and select_frame_command.
+ (func_command): Use get_current_frame rather than
+ parse_frame_specification.
+
+2015-09-11 Andrew Burgess <andrew.burgess@embecosm.com>
+
* stack.c (func_command): Return early when there is no ARG
string.
diff --git a/gdb/stack.c b/gdb/stack.c
index 1049995..1bc1fe6 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -1280,8 +1280,8 @@ print_frame (struct frame_info *frame, int print_level,
the default selected frame was used. */
static struct frame_info *
-parse_frame_specification_1 (const char *frame_exp, const char *message,
- int *selected_frame_p)
+parse_frame_specification (const char *frame_exp, const char *message,
+ int *selected_frame_p)
{
int numargs;
struct value *args[4];
@@ -1401,12 +1401,6 @@ parse_frame_specification_1 (const char *frame_exp, const char *message,
error (_("Too many args in frame specification"));
}
-static struct frame_info *
-parse_frame_specification (char *frame_exp)
-{
- return parse_frame_specification_1 (frame_exp, NULL, NULL);
-}
-
/* Print verbosely the selected frame or the frame at address
ADDR_EXP. Absolutely all information in the frame is printed. */
@@ -1431,7 +1425,7 @@ frame_info (char *addr_exp, int from_tty)
CORE_ADDR caller_pc = 0;
int caller_pc_p = 0;
- fi = parse_frame_specification_1 (addr_exp, "No stack.", &selected_frame_p);
+ fi = parse_frame_specification (addr_exp, "No stack.", &selected_frame_p);
gdbarch = get_frame_arch (fi);
/* During the following value will be created and then displayed.
@@ -2293,7 +2287,7 @@ find_relative_frame (struct frame_info *frame, int *level_offset_ptr)
void
select_frame_command (char *level_exp, int from_tty)
{
- select_frame (parse_frame_specification_1 (level_exp, "No stack.", NULL));
+ select_frame (parse_frame_specification (level_exp, "No stack.", NULL));
}
/* The "frame" command. With no argument, print the selected frame
@@ -2501,11 +2495,10 @@ return_command (char *retval_exp, int from_tty)
if (get_frame_type (get_current_frame ()) == DUMMY_FRAME)
frame_pop (get_current_frame ());
+ select_frame (get_current_frame ());
/* If interactive, print the frame that is now current. */
if (from_tty)
- frame_command ("0", 1);
- else
- select_frame_command ("0", 0);
+ print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC, 1);
}
/* Sets the scope to input function name, provided that the function
@@ -2530,7 +2523,7 @@ func_command (char *arg, int from_tty)
if (arg == NULL)
return;
- frame = parse_frame_specification ("0");
+ frame = get_current_frame ();
sals = decode_line_with_current_source (arg, DECODE_LINE_FUNFIRSTLINE);
cleanups = make_cleanup (xfree, sals.sals);
func_bounds = XNEWVEC (struct function_bounds, sals.nelts);
--
2.5.1
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [PATCH 6/9] gdb: Avoid unneeded calls to parse_frame_specification.
2015-09-11 18:50 ` [PATCH 6/9] gdb: Avoid unneeded calls to parse_frame_specification Andrew Burgess
@ 2015-09-30 13:48 ` Pedro Alves
0 siblings, 0 replies; 25+ messages in thread
From: Pedro Alves @ 2015-09-30 13:48 UTC (permalink / raw)
To: Andrew Burgess, gdb-patches
On 09/11/2015 07:49 PM, Andrew Burgess wrote:
> Within the stack command there are a couple of places where fixed
> strings are passed into functions that are really intended for
> processing user input. These fixed strings are then processed and the
> result returned.
>
> Given that the input strings in these cases are fixed, and are always
> "0", then the result will always be the same, the current frame. By
> switching to using get_current_frame instead the code can be simplified,
> and the intention of the code is clearer.
>
> gdb/ChangeLog:
>
> * stack.c (parse_frame_specification): Delete.
> (parse_frame_specification_1): Rename to
> parse_frame_specification.
> (frame_info): Use parse_frame_specification.
> (select_frame_command): Likewise.
> (return_command): Use select_frame and print_stack_frame rather
> than frame_command and select_frame_command.
> (func_command): Use get_current_frame rather than
> parse_frame_specification.
OK. Nice clean up.
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 9/9] gdb: Change how frames are selected for 'frame' and 'info frame'.
2015-09-11 18:49 [PATCH 0/9] Changes to frame selection Andrew Burgess
` (2 preceding siblings ...)
2015-09-11 18:50 ` [PATCH 6/9] gdb: Avoid unneeded calls to parse_frame_specification Andrew Burgess
@ 2015-09-11 18:50 ` Andrew Burgess
2015-09-11 20:21 ` Eli Zaretskii
2015-09-30 14:00 ` Pedro Alves
2015-09-11 18:50 ` [PATCH 4/9] gdb/doc: Restructure frame command documentation Andrew Burgess
` (5 subsequent siblings)
9 siblings, 2 replies; 25+ messages in thread
From: Andrew Burgess @ 2015-09-11 18:50 UTC (permalink / raw)
To: gdb-patches; +Cc: Andrew Burgess
The 'frame' command, and thanks to code reuse the 'frame info' and
'select-frame' commands, currently have an overloaded mechanism for
selecting a frame.
These commands take one or two parameters, if it's one parameter then we
first try to use the parameter as an integer to select a frame by
index. If that fails then we treat the parameter as an address and try
to select a stack frame by stack-address. If we still have not selected
a stack frame, or we had two parameters initially, then we create a new
stack frame and select that.
The result of this is that a typo by the user, entering the wrong stack
frame index for example, can result in a brand new frame being created
rather than an error.
The purpose of this commit is to remove this overloading, while
hopefully offering some level of backward compatibility.
The 'frame', 'select-frame', and 'info frame' commands now all take a
frame specification string as an argument, this string can be any of the
following:
(1) An integer. This is treated as a frame number. If a frame for
that number does not exist then the user gets an error.
(2) A string like 'level <NUMBER>', where <NUMBER> is a frame number
as in option (1) above.
(3) A string like 'address <ADDRESS>', where <ADDRESS> is a
stack-frame address. If there is no frame for this address then the
user gets an error.
(4) A string like 'function <NAME>', where <NAME> is a function name,
the inner most frame for function <NAME> is selected. If there is no
frame for function <NAME> then the user gets an error.
(5) A string like 'create <STACK-ADDRESS>', this creates a new frame
with stack address <STACK-ADDRESS>.
(6) A string like 'create <STACK-ADDRESS> <PC-ADDRESS>', this creates
a new frame with stack address <STACK-ADDRESS> an the pc <PC-ADDRESS>.
This change assumes that the most common use of the commands like
'frame' is to select a frame by frame level number, it is for this
reason that this is the behaviour that is kept for backwards
compatibility. Any of the alternative behaviours, which are assumed to
be less used, now require a change in user behaviour.
gdb/ChangeLog:
* 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.
(parse_frame_selection_spec): New function.
(free_frame_selection_spec): New function.
(parse_frame_specification): Rewrite.
(frame_selection_completer): New function.
(_initialize_stack): Add completion function for 'frame',
'select-frame', and 'info frame' commands.
(NEWS): Mention changes to frame related commands.
gdb/doc/ChangeLog:
* gdb.texinfo (Selection): Rewrite documentation for 'frame' and
'select-frame' commands.
(Frame Info): Rewrite documentation for 'info frame' command.
gdb/testsuite/ChangeLog:
* 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.
---
gdb/ChangeLog | 24 ++
gdb/NEWS | 6 +
gdb/doc/ChangeLog | 6 +
gdb/doc/gdb.texinfo | 84 +++++--
gdb/mi/mi-cmd-stack.c | 16 +-
gdb/stack.c | 404 +++++++++++++++++++++++++---------
gdb/stack.h | 2 +-
gdb/testsuite/ChangeLog | 6 +
gdb/testsuite/gdb.base/frame-cmds.c | 20 +-
gdb/testsuite/gdb.mi/mi-var-frame.exp | 17 +-
10 files changed, 443 insertions(+), 142 deletions(-)
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 9da954d..6af7d45 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -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 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
diff --git a/gdb/NEWS b/gdb/NEWS
index 0cf51e1..bf5f455 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -3,6 +3,12 @@
*** 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.
+
* Support for tracepoints on aarch64-linux was added in GDBserver.
* The 'record instruction-history' command now indicates speculative execution
diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index f7d7a94..bb82cf9 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -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
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 225e57d..b27aaf8 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -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
diff --git a/gdb/mi/mi-cmd-stack.c b/gdb/mi/mi-cmd-stack.c
index 520db2b..ede23a1 100644
--- a/gdb/mi/mi-cmd-stack.c
+++ b/gdb/mi/mi-cmd-stack.c
@@ -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
diff --git a/gdb/stack.c b/gdb/stack.c
index 71e171a..2f15b6c 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -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,
}
\f
-/* 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;
+}
+
\f
/* 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,22 @@ 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, _("\
+ cmd = 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."));
+ 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"));
+ 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 +2813,10 @@ 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 selected stack frame, or frame at ADDR."));
+ set_cmd_completer (cmd, frame_selection_completer);
+
add_info_alias ("f", "frame", 1);
add_info ("locals", locals_info,
_("Local variables of current stack frame."));
diff --git a/gdb/stack.h b/gdb/stack.h
index 21ddac5..26566a2 100644
--- a/gdb/stack.h
+++ b/gdb/stack.h
@@ -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);
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 272d3fc..bdd8be4 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -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.
diff --git a/gdb/testsuite/gdb.base/frame-cmds.c b/gdb/testsuite/gdb.base/frame-cmds.c
index 53b222d..24a46f3 100644
--- a/gdb/testsuite/gdb.base/frame-cmds.c
+++ b/gdb/testsuite/gdb.base/frame-cmds.c
@@ -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;
}
diff --git a/gdb/testsuite/gdb.mi/mi-var-frame.exp b/gdb/testsuite/gdb.mi/mi-var-frame.exp
index 5c3f196..247675a 100644
--- a/gdb/testsuite/gdb.mi/mi-var-frame.exp
+++ b/gdb/testsuite/gdb.mi/mi-var-frame.exp
@@ -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"
--
2.5.1
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [PATCH 9/9] gdb: Change how frames are selected for 'frame' and 'info frame'.
2015-09-11 18:50 ` [PATCH 9/9] gdb: Change how frames are selected for 'frame' and 'info frame' Andrew Burgess
@ 2015-09-11 20:21 ` Eli Zaretskii
2015-09-15 10:41 ` Andrew Burgess
2015-09-30 14:00 ` Pedro Alves
1 sibling, 1 reply; 25+ messages in thread
From: Eli Zaretskii @ 2015-09-11 20:21 UTC (permalink / raw)
To: Andrew Burgess; +Cc: gdb-patches, andrew.burgess
> From: Andrew Burgess <andrew.burgess@embecosm.com>
> Cc: Andrew Burgess <andrew.burgess@embecosm.com>
> Date: Fri, 11 Sep 2015 19:49:43 +0100
>
> *** 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.
Please show an example of a changed command. NEWS entries are
supposed to be self-contained, and this one isn't.
> 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.
This part is OK.
Thanks.
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 9/9] gdb: Change how frames are selected for 'frame' and 'info frame'.
2015-09-11 20:21 ` Eli Zaretskii
@ 2015-09-15 10:41 ` Andrew Burgess
2015-09-15 10:50 ` Eli Zaretskii
0 siblings, 1 reply; 25+ messages in thread
From: Andrew Burgess @ 2015-09-15 10:41 UTC (permalink / raw)
To: gdb-patches; +Cc: Eli Zaretskii
Revised version of this patch. Changes are:
- Longer entry in NEWS file to address Eli's feedback.
- Updated doc string for "frame", "select-frame", and "info frame"
commands within gdb. I forgot to do this in the first version of
the patch.
Thanks,
Andrew
---
The 'frame' command, and thanks to code reuse the 'frame info' and
'select-frame' commands, currently have an overloaded mechanism for
selecting a frame.
These commands take one or two parameters, if it's one parameter then we
first try to use the parameter as an integer to select a frame by
index. If that fails then we treat the parameter as an address and try
to select a stack frame by stack-address. If we still have not selected
a stack frame, or we had two parameters initially, then we create a new
stack frame and select that.
The result of this is that a typo by the user, entering the wrong stack
frame index for example, can result in a brand new frame being created
rather than an error.
The purpose of this commit is to remove this overloading, while
hopefully offering some level of backward compatibility.
The 'frame', 'select-frame', and 'info frame' commands now all take a
frame specification string as an argument, this string can be any of the
following:
(1) An integer. This is treated as a frame number. If a frame for
that number does not exist then the user gets an error.
(2) A string like 'level <NUMBER>', where <NUMBER> is a frame number
as in option (1) above.
(3) A string like 'address <ADDRESS>', where <ADDRESS> is a
stack-frame address. If there is no frame for this address then the
user gets an error.
(4) A string like 'function <NAME>', where <NAME> is a function name,
the inner most frame for function <NAME> is selected. If there is no
frame for function <NAME> then the user gets an error.
(5) A string like 'create <STACK-ADDRESS>', this creates a new frame
with stack address <STACK-ADDRESS>.
(6) A string like 'create <STACK-ADDRESS> <PC-ADDRESS>', this creates
a new frame with stack address <STACK-ADDRESS> an the pc <PC-ADDRESS>.
This change assumes that the most common use of the commands like
'frame' is to select a frame by frame level number, it is for this
reason that this is the behaviour that is kept for backwards
compatibility. Any of the alternative behaviours, which are assumed to
be less used, now require a change in user behaviour.
gdb/ChangeLog:
* 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.
gdb/doc/ChangeLog:
* gdb.texinfo (Selection): Rewrite documentation for 'frame' and
'select-frame' commands.
(Frame Info): Rewrite documentation for 'info frame' command.
gdb/testsuite/ChangeLog:
* 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.
---
gdb/ChangeLog | 24 ++
gdb/NEWS | 20 ++
gdb/doc/ChangeLog | 6 +
gdb/doc/gdb.texinfo | 84 +++++--
gdb/mi/mi-cmd-stack.c | 16 +-
gdb/stack.c | 436 +++++++++++++++++++++++++---------
gdb/stack.h | 2 +-
gdb/testsuite/ChangeLog | 6 +
gdb/testsuite/gdb.base/frame-cmds.c | 20 +-
gdb/testsuite/gdb.mi/mi-var-frame.exp | 17 +-
10 files changed, 481 insertions(+), 150 deletions(-)
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 9da954d..c72ea81 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -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
diff --git a/gdb/NEWS b/gdb/NEWS
index 0cf51e1..3d15d46 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -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
diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index f7d7a94..bb82cf9 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -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
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 225e57d..b27aaf8 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -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
diff --git a/gdb/mi/mi-cmd-stack.c b/gdb/mi/mi-cmd-stack.c
index 520db2b..ede23a1 100644
--- a/gdb/mi/mi-cmd-stack.c
+++ b/gdb/mi/mi-cmd-stack.c
@@ -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
diff --git a/gdb/stack.c b/gdb/stack.c
index 71e171a..9db63ae 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -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,
}
\f
-/* 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;
+}
+
\f
/* 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."));
diff --git a/gdb/stack.h b/gdb/stack.h
index 21ddac5..26566a2 100644
--- a/gdb/stack.h
+++ b/gdb/stack.h
@@ -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);
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 272d3fc..bdd8be4 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -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.
diff --git a/gdb/testsuite/gdb.base/frame-cmds.c b/gdb/testsuite/gdb.base/frame-cmds.c
index 53b222d..24a46f3 100644
--- a/gdb/testsuite/gdb.base/frame-cmds.c
+++ b/gdb/testsuite/gdb.base/frame-cmds.c
@@ -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;
}
diff --git a/gdb/testsuite/gdb.mi/mi-var-frame.exp b/gdb/testsuite/gdb.mi/mi-var-frame.exp
index 5c3f196..247675a 100644
--- a/gdb/testsuite/gdb.mi/mi-var-frame.exp
+++ b/gdb/testsuite/gdb.mi/mi-var-frame.exp
@@ -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"
--
2.5.1
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [PATCH 9/9] gdb: Change how frames are selected for 'frame' and 'info frame'.
2015-09-15 10:41 ` Andrew Burgess
@ 2015-09-15 10:50 ` Eli Zaretskii
2015-09-17 11:36 ` Andrew Burgess
0 siblings, 1 reply; 25+ messages in thread
From: Eli Zaretskii @ 2015-09-15 10:50 UTC (permalink / raw)
To: Andrew Burgess; +Cc: gdb-patches
> Date: Tue, 15 Sep 2015 11:40:51 +0100
> From: Andrew Burgess <andrew.burgess@embecosm.com>
> Cc: Eli Zaretskii <eliz@gnu.org>
>
> Revised version of this patch. Changes are:
>
> - Longer entry in NEWS file to address Eli's feedback.
> - Updated doc string for "frame", "select-frame", and "info frame"
> commands within gdb. I forgot to do this in the first version of
> the patch.
Thanks. The documentation parts are OK. The doc strings look good
to me, with one minor gotcha:
> +Select a stack frame by the frames stack frame address:\n\
^^^^^^
This "frames" should be deleted, I think.
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [PATCH 9/9] gdb: Change how frames are selected for 'frame' and 'info frame'.
2015-09-15 10:50 ` Eli Zaretskii
@ 2015-09-17 11:36 ` Andrew Burgess
0 siblings, 0 replies; 25+ messages in thread
From: Andrew Burgess @ 2015-09-17 11:36 UTC (permalink / raw)
To: gdb-patches; +Cc: Eli Zaretskii
* Eli Zaretskii <eliz@gnu.org> [2015-09-15 13:50:17 +0300]:
> > Date: Tue, 15 Sep 2015 11:40:51 +0100
> > From: Andrew Burgess <andrew.burgess@embecosm.com>
> > Cc: Eli Zaretskii <eliz@gnu.org>
>
> > +Select a stack frame by the frames stack frame address:\n\
> ^^^^^^
> This "frames" should be deleted, I think.
Thanks I've fixed this.
Andrew
---
gdb: Change how frames are selected for 'frame' and 'info frame'.
The 'frame' command, and thanks to code reuse the 'frame info' and
'select-frame' commands, currently have an overloaded mechanism for
selecting a frame.
These commands take one or two parameters, if it's one parameter then we
first try to use the parameter as an integer to select a frame by
index. If that fails then we treat the parameter as an address and try
to select a stack frame by stack-address. If we still have not selected
a stack frame, or we had two parameters initially, then we create a new
stack frame and select that.
The result of this is that a typo by the user, entering the wrong stack
frame index for example, can result in a brand new frame being created
rather than an error.
The purpose of this commit is to remove this overloading, while
hopefully offering some level of backward compatibility.
The 'frame', 'select-frame', and 'info frame' commands now all take a
frame specification string as an argument, this string can be any of the
following:
(1) An integer. This is treated as a frame number. If a frame for
that number does not exist then the user gets an error.
(2) A string like 'level <NUMBER>', where <NUMBER> is a frame number
as in option (1) above.
(3) A string like 'address <ADDRESS>', where <ADDRESS> is a
stack-frame address. If there is no frame for this address then the
user gets an error.
(4) A string like 'function <NAME>', where <NAME> is a function name,
the inner most frame for function <NAME> is selected. If there is no
frame for function <NAME> then the user gets an error.
(5) A string like 'create <STACK-ADDRESS>', this creates a new frame
with stack address <STACK-ADDRESS>.
(6) A string like 'create <STACK-ADDRESS> <PC-ADDRESS>', this creates
a new frame with stack address <STACK-ADDRESS> an the pc <PC-ADDRESS>.
This change assumes that the most common use of the commands like
'frame' is to select a frame by frame level number, it is for this
reason that this is the behaviour that is kept for backwards
compatibility. Any of the alternative behaviours, which are assumed to
be less used, now require a change in user behaviour.
gdb/ChangeLog:
* 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.
gdb/doc/ChangeLog:
* gdb.texinfo (Selection): Rewrite documentation for 'frame' and
'select-frame' commands.
(Frame Info): Rewrite documentation for 'info frame' command.
gdb/testsuite/ChangeLog:
* 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.
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 9da954d..c72ea81 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -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
diff --git a/gdb/NEWS b/gdb/NEWS
index 0cf51e1..3d15d46 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -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
diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index f7d7a94..bb82cf9 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -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
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 225e57d..b27aaf8 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -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
diff --git a/gdb/mi/mi-cmd-stack.c b/gdb/mi/mi-cmd-stack.c
index 520db2b..ede23a1 100644
--- a/gdb/mi/mi-cmd-stack.c
+++ b/gdb/mi/mi-cmd-stack.c
@@ -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
diff --git a/gdb/stack.c b/gdb/stack.c
index 71e171a..9063e4f 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -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,
}
\f
-/* 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;
+}
+
\f
/* 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 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."));
diff --git a/gdb/stack.h b/gdb/stack.h
index 21ddac5..26566a2 100644
--- a/gdb/stack.h
+++ b/gdb/stack.h
@@ -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);
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 272d3fc..bdd8be4 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -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.
diff --git a/gdb/testsuite/gdb.base/frame-cmds.c b/gdb/testsuite/gdb.base/frame-cmds.c
index 53b222d..24a46f3 100644
--- a/gdb/testsuite/gdb.base/frame-cmds.c
+++ b/gdb/testsuite/gdb.base/frame-cmds.c
@@ -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;
}
diff --git a/gdb/testsuite/gdb.mi/mi-var-frame.exp b/gdb/testsuite/gdb.mi/mi-var-frame.exp
index 5c3f196..247675a 100644
--- a/gdb/testsuite/gdb.mi/mi-var-frame.exp
+++ b/gdb/testsuite/gdb.mi/mi-var-frame.exp
@@ -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"
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 9/9] gdb: Change how frames are selected for 'frame' and 'info frame'.
2015-09-11 18:50 ` [PATCH 9/9] gdb: Change how frames are selected for 'frame' and 'info frame' Andrew Burgess
2015-09-11 20:21 ` Eli Zaretskii
@ 2015-09-30 14:00 ` Pedro Alves
1 sibling, 0 replies; 25+ messages in thread
From: Pedro Alves @ 2015-09-30 14:00 UTC (permalink / raw)
To: Andrew Burgess, gdb-patches
On 09/11/2015 07:49 PM, Andrew Burgess wrote:
> --- a/gdb/stack.c
> +++ b/gdb/stack.c
> @@ -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);
No space after first *. Also, can that be "const char *" ?
But most importantly - is there a reason this is implemented
the way it is (manually handling completion, parsing, etc.) instead of
creating sub-commands for "frame", etc., like done e.g., for "thread",
thread apply", "thread apply all", etc. ?
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 4/9] gdb/doc: Restructure frame command documentation.
2015-09-11 18:49 [PATCH 0/9] Changes to frame selection Andrew Burgess
` (3 preceding siblings ...)
2015-09-11 18:50 ` [PATCH 9/9] gdb: Change how frames are selected for 'frame' and 'info frame' Andrew Burgess
@ 2015-09-11 18:50 ` Andrew Burgess
2015-09-11 20:17 ` Eli Zaretskii
2015-09-11 18:50 ` [PATCH 3/9] gdb: Make use of safe-ctype.h header Andrew Burgess
` (4 subsequent siblings)
9 siblings, 1 reply; 25+ messages in thread
From: Andrew Burgess @ 2015-09-11 18:50 UTC (permalink / raw)
To: gdb-patches; +Cc: Andrew Burgess
The 'frame' command is documented in two places. The 'select-frame'
command is only mentioned in one of these places.
Of the two places, having the description of 'frame' and 'select-frame'
in the section 'Selecting a Frame' seems like the most obvious choice,
which is where things like 'up' and 'down' are also documented.
This commit moves the documentation of 'frame' and 'select-frame' into
the 'Selecting a Frame' section, and removes the duplicate documentation
of the 'frame' command.
At the same time I have reordered the sections in the 'Examining the
Stack' chapter, moving the discussion of frame filters to the end of the
chapter; it feels odd that we talk about frame filters before such basic
things like navigating the stack, or examining stack frames in general.
gdb/doc/ChangeLog:
* gdb.texinfo (Frames): Remove 'frame' and 'select-frame'
description.
(Frame Filter Management): Move to later in the 'Examining the
Stack' chapter.
(Selection): Add entry for 'select-frame'.
---
gdb/doc/ChangeLog | 8 ++
gdb/doc/gdb.texinfo | 309 +++++++++++++++++++++++++---------------------------
2 files changed, 157 insertions(+), 160 deletions(-)
diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index 29c66b8..f7d7a94 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -1,3 +1,11 @@
+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
+ Stack' chapter.
+ (Selection): Add entry for 'select-frame'.
+
2015-08-24 Pedro Alves <palves@redhat.com>
* gdb.texinfo (Remote Configuration): Document the "set/show
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index cd0abad..225e57d 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -6948,23 +6948,6 @@ it had a separate frame, which is numbered zero as usual, allowing
correct tracing of the function call chain. However, @value{GDBN} has
no provision for frameless functions elsewhere in the stack.
-@table @code
-@kindex frame@r{, command}
-@cindex current stack frame
-@item frame @r{[}@var{framespec}@r{]}
-The @code{frame} command allows you to move from one stack frame to another,
-and to print the stack frame you select. The @var{framespec} may be either the
-address of the frame or the stack frame number. Without an argument,
-@code{frame} prints the current stack frame.
-
-@kindex select-frame
-@cindex selecting frame silently
-@item select-frame
-The @code{select-frame} command allows you to move from one stack frame
-to another without printing the frame. This is the silent version of
-@code{frame}.
-@end table
-
@node Backtrace
@section Backtraces
@@ -7164,149 +7147,6 @@ Display an absolute filename.
Show the current way to display filenames.
@end table
-@node Frame Filter Management
-@section Management of Frame Filters.
-@cindex managing frame filters
-
-Frame filters are Python based utilities to manage and decorate the
-output of frames. @xref{Frame Filter API}, for further information.
-
-Managing frame filters is performed by several commands available
-within @value{GDBN}, detailed here.
-
-@table @code
-@kindex info frame-filter
-@item info frame-filter
-Print a list of installed frame filters from all dictionaries, showing
-their name, priority and enabled status.
-
-@kindex disable frame-filter
-@anchor{disable frame-filter all}
-@item disable frame-filter @var{filter-dictionary} @var{filter-name}
-Disable a frame filter in the dictionary matching
-@var{filter-dictionary} and @var{filter-name}. The
-@var{filter-dictionary} may be @code{all}, @code{global},
-@code{progspace}, or the name of the object file where the frame filter
-dictionary resides. When @code{all} is specified, all frame filters
-across all dictionaries are disabled. The @var{filter-name} is the name
-of the frame filter and is used when @code{all} is not the option for
-@var{filter-dictionary}. A disabled frame-filter is not deleted, it
-may be enabled again later.
-
-@kindex enable frame-filter
-@item enable frame-filter @var{filter-dictionary} @var{filter-name}
-Enable a frame filter in the dictionary matching
-@var{filter-dictionary} and @var{filter-name}. The
-@var{filter-dictionary} may be @code{all}, @code{global},
-@code{progspace} or the name of the object file where the frame filter
-dictionary resides. When @code{all} is specified, all frame filters across
-all dictionaries are enabled. The @var{filter-name} is the name of the frame
-filter and is used when @code{all} is not the option for
-@var{filter-dictionary}.
-
-Example:
-
-@smallexample
-(gdb) info frame-filter
-
-global frame-filters:
- Priority Enabled Name
- 1000 No PrimaryFunctionFilter
- 100 Yes Reverse
-
-progspace /build/test frame-filters:
- Priority Enabled Name
- 100 Yes ProgspaceFilter
-
-objfile /build/test frame-filters:
- Priority Enabled Name
- 999 Yes BuildProgra Filter
-
-(gdb) disable frame-filter /build/test BuildProgramFilter
-(gdb) info frame-filter
-
-global frame-filters:
- Priority Enabled Name
- 1000 No PrimaryFunctionFilter
- 100 Yes Reverse
-
-progspace /build/test frame-filters:
- Priority Enabled Name
- 100 Yes ProgspaceFilter
-
-objfile /build/test frame-filters:
- Priority Enabled Name
- 999 No BuildProgramFilter
-
-(gdb) enable frame-filter global PrimaryFunctionFilter
-(gdb) info frame-filter
-
-global frame-filters:
- Priority Enabled Name
- 1000 Yes PrimaryFunctionFilter
- 100 Yes Reverse
-
-progspace /build/test frame-filters:
- Priority Enabled Name
- 100 Yes ProgspaceFilter
-
-objfile /build/test frame-filters:
- Priority Enabled Name
- 999 No BuildProgramFilter
-@end smallexample
-
-@kindex set frame-filter priority
-@item set frame-filter priority @var{filter-dictionary} @var{filter-name} @var{priority}
-Set the @var{priority} of a frame filter in the dictionary matching
-@var{filter-dictionary}, and the frame filter name matching
-@var{filter-name}. The @var{filter-dictionary} may be @code{global},
-@code{progspace} or the name of the object file where the frame filter
-dictionary resides. The @var{priority} is an integer.
-
-@kindex show frame-filter priority
-@item show frame-filter priority @var{filter-dictionary} @var{filter-name}
-Show the @var{priority} of a frame filter in the dictionary matching
-@var{filter-dictionary}, and the frame filter name matching
-@var{filter-name}. The @var{filter-dictionary} may be @code{global},
-@code{progspace} or the name of the object file where the frame filter
-dictionary resides.
-
-Example:
-
-@smallexample
-(gdb) info frame-filter
-
-global frame-filters:
- Priority Enabled Name
- 1000 Yes PrimaryFunctionFilter
- 100 Yes Reverse
-
-progspace /build/test frame-filters:
- Priority Enabled Name
- 100 Yes ProgspaceFilter
-
-objfile /build/test frame-filters:
- Priority Enabled Name
- 999 No BuildProgramFilter
-
-(gdb) set frame-filter priority global Reverse 50
-(gdb) info frame-filter
-
-global frame-filters:
- Priority Enabled Name
- 1000 Yes PrimaryFunctionFilter
- 50 Yes Reverse
-
-progspace /build/test frame-filters:
- Priority Enabled Name
- 100 Yes ProgspaceFilter
-
-objfile /build/test frame-filters:
- Priority Enabled Name
- 999 No BuildProgramFilter
-@end smallexample
-@end table
-
@node Selection
@section Selecting a Frame
@@ -7374,6 +7214,13 @@ editing program by typing @code{edit}.
for details.
@table @code
+@kindex select-frame
+@item select-frame
+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.
+
@kindex down-silently
@kindex up-silently
@item up-silently @var{n}
@@ -7450,6 +7297,148 @@ accessible at the point of execution of the selected frame.
@end table
+@node Frame Filter Management
+@section Management of Frame Filters.
+@cindex managing frame filters
+
+Frame filters are Python based utilities to manage and decorate the
+output of frames. @xref{Frame Filter API}, for further information.
+
+Managing frame filters is performed by several commands available
+within @value{GDBN}, detailed here.
+
+@table @code
+@kindex info frame-filter
+@item info frame-filter
+Print a list of installed frame filters from all dictionaries, showing
+their name, priority and enabled status.
+
+@kindex disable frame-filter
+@anchor{disable frame-filter all}
+@item disable frame-filter @var{filter-dictionary} @var{filter-name}
+Disable a frame filter in the dictionary matching
+@var{filter-dictionary} and @var{filter-name}. The
+@var{filter-dictionary} may be @code{all}, @code{global},
+@code{progspace}, or the name of the object file where the frame filter
+dictionary resides. When @code{all} is specified, all frame filters
+across all dictionaries are disabled. The @var{filter-name} is the name
+of the frame filter and is used when @code{all} is not the option for
+@var{filter-dictionary}. A disabled frame-filter is not deleted, it
+may be enabled again later.
+
+@kindex enable frame-filter
+@item enable frame-filter @var{filter-dictionary} @var{filter-name}
+Enable a frame filter in the dictionary matching
+@var{filter-dictionary} and @var{filter-name}. The
+@var{filter-dictionary} may be @code{all}, @code{global},
+@code{progspace} or the name of the object file where the frame filter
+dictionary resides. When @code{all} is specified, all frame filters across
+all dictionaries are enabled. The @var{filter-name} is the name of the frame
+filter and is used when @code{all} is not the option for
+@var{filter-dictionary}.
+
+Example:
+
+@smallexample
+(gdb) info frame-filter
+
+global frame-filters:
+ Priority Enabled Name
+ 1000 No PrimaryFunctionFilter
+ 100 Yes Reverse
+
+progspace /build/test frame-filters:
+ Priority Enabled Name
+ 100 Yes ProgspaceFilter
+
+objfile /build/test frame-filters:
+ Priority Enabled Name
+ 999 Yes BuildProgra Filter
+
+(gdb) disable frame-filter /build/test BuildProgramFilter
+(gdb) info frame-filter
+
+global frame-filters:
+ Priority Enabled Name
+ 1000 No PrimaryFunctionFilter
+ 100 Yes Reverse
+
+progspace /build/test frame-filters:
+ Priority Enabled Name
+ 100 Yes ProgspaceFilter
+
+objfile /build/test frame-filters:
+ Priority Enabled Name
+ 999 No BuildProgramFilter
+
+(gdb) enable frame-filter global PrimaryFunctionFilter
+(gdb) info frame-filter
+
+global frame-filters:
+ Priority Enabled Name
+ 1000 Yes PrimaryFunctionFilter
+ 100 Yes Reverse
+
+progspace /build/test frame-filters:
+ Priority Enabled Name
+ 100 Yes ProgspaceFilter
+
+objfile /build/test frame-filters:
+ Priority Enabled Name
+ 999 No BuildProgramFilter
+@end smallexample
+
+@kindex set frame-filter priority
+@item set frame-filter priority @var{filter-dictionary} @var{filter-name} @var{priority}
+Set the @var{priority} of a frame filter in the dictionary matching
+@var{filter-dictionary}, and the frame filter name matching
+@var{filter-name}. The @var{filter-dictionary} may be @code{global},
+@code{progspace} or the name of the object file where the frame filter
+dictionary resides. The @var{priority} is an integer.
+
+@kindex show frame-filter priority
+@item show frame-filter priority @var{filter-dictionary} @var{filter-name}
+Show the @var{priority} of a frame filter in the dictionary matching
+@var{filter-dictionary}, and the frame filter name matching
+@var{filter-name}. The @var{filter-dictionary} may be @code{global},
+@code{progspace} or the name of the object file where the frame filter
+dictionary resides.
+
+Example:
+
+@smallexample
+(gdb) info frame-filter
+
+global frame-filters:
+ Priority Enabled Name
+ 1000 Yes PrimaryFunctionFilter
+ 100 Yes Reverse
+
+progspace /build/test frame-filters:
+ Priority Enabled Name
+ 100 Yes ProgspaceFilter
+
+objfile /build/test frame-filters:
+ Priority Enabled Name
+ 999 No BuildProgramFilter
+
+(gdb) set frame-filter priority global Reverse 50
+(gdb) info frame-filter
+
+global frame-filters:
+ Priority Enabled Name
+ 1000 Yes PrimaryFunctionFilter
+ 50 Yes Reverse
+
+progspace /build/test frame-filters:
+ Priority Enabled Name
+ 100 Yes ProgspaceFilter
+
+objfile /build/test frame-filters:
+ Priority Enabled Name
+ 999 No BuildProgramFilter
+@end smallexample
+@end table
@node Source
@chapter Examining Source Files
--
2.5.1
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [PATCH 4/9] gdb/doc: Restructure frame command documentation.
2015-09-11 18:50 ` [PATCH 4/9] gdb/doc: Restructure frame command documentation Andrew Burgess
@ 2015-09-11 20:17 ` Eli Zaretskii
0 siblings, 0 replies; 25+ messages in thread
From: Eli Zaretskii @ 2015-09-11 20:17 UTC (permalink / raw)
To: Andrew Burgess; +Cc: gdb-patches, andrew.burgess
> From: Andrew Burgess <andrew.burgess@embecosm.com>
> Cc: Andrew Burgess <andrew.burgess@embecosm.com>
> Date: Fri, 11 Sep 2015 19:49:38 +0100
>
> The 'frame' command is documented in two places. The 'select-frame'
> command is only mentioned in one of these places.
>
> Of the two places, having the description of 'frame' and 'select-frame'
> in the section 'Selecting a Frame' seems like the most obvious choice,
> which is where things like 'up' and 'down' are also documented.
>
> This commit moves the documentation of 'frame' and 'select-frame' into
> the 'Selecting a Frame' section, and removes the duplicate documentation
> of the 'frame' command.
>
> At the same time I have reordered the sections in the 'Examining the
> Stack' chapter, moving the discussion of frame filters to the end of the
> chapter; it feels odd that we talk about frame filters before such basic
> things like navigating the stack, or examining stack frames in general.
OK, thanks.
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 3/9] gdb: Make use of safe-ctype.h header.
2015-09-11 18:49 [PATCH 0/9] Changes to frame selection Andrew Burgess
` (4 preceding siblings ...)
2015-09-11 18:50 ` [PATCH 4/9] gdb/doc: Restructure frame command documentation Andrew Burgess
@ 2015-09-11 18:50 ` Andrew Burgess
2015-09-30 13:43 ` Pedro Alves
2015-09-11 18:50 ` [PATCH 8/9] gdb: Split func_command into two parts Andrew Burgess
` (3 subsequent siblings)
9 siblings, 1 reply; 25+ messages in thread
From: Andrew Burgess @ 2015-09-11 18:50 UTC (permalink / raw)
To: gdb-patches; +Cc: Andrew Burgess
In stack.c switch to using safe-ctype.h instead of ctype.h, update code
as required.
gdb/ChangeLog:
* stack.c: Include safe-ctype.h not ctype.h.
(parse_frame_specification): Use ISSPACE not isspace.
(backtrace_command): Use TOLOWER not tolower.
---
gdb/ChangeLog | 6 ++++++
gdb/stack.c | 6 +++---
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 79952c7..50aa7f0 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,11 @@
2015-09-11 Andrew Burgess <andrew.burgess@embecosm.com>
+ * stack.c: Include safe-ctype.h not ctype.h.
+ (parse_frame_specification): Use ISSPACE not isspace.
+ (backtrace_command): Use TOLOWER not tolower.
+
+2015-09-11 Andrew Burgess <andrew.burgess@embecosm.com>
+
* frame.h (make_restore_selected_frame_cleanup): Declare new
function.
* frame.c (do_restore_selected_frame): New function.
diff --git a/gdb/stack.c b/gdb/stack.c
index 82b366d..2fe176f 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -48,7 +48,7 @@
#include "cli/cli-utils.h"
#include "objfiles.h"
-#include <ctype.h>
+#include "safe-ctype.h"
#include "symfile.h"
#include "extension.h"
@@ -1305,7 +1305,7 @@ parse_frame_specification_1 (const char *frame_exp, const char *message,
/* Parse the argument, extract it, save it. */
for (p = frame_exp;
- *p && !isspace (*p);
+ *p && !ISSPACE (*p);
p++);
addr_string = savestring (frame_exp, p - frame_exp);
frame_exp = p;
@@ -1904,7 +1904,7 @@ backtrace_command (char *arg, int from_tty)
unsigned int j;
for (j = 0; j < strlen (argv[i]); j++)
- argv[i][j] = tolower (argv[i][j]);
+ argv[i][j] = TOLOWER (argv[i][j]);
if (no_filters < 0 && subset_compare (argv[i], "no-filters"))
no_filters = argc;
--
2.5.1
^ permalink raw reply [flat|nested] 25+ messages in thread* [PATCH 8/9] gdb: Split func_command into two parts.
2015-09-11 18:49 [PATCH 0/9] Changes to frame selection Andrew Burgess
` (5 preceding siblings ...)
2015-09-11 18:50 ` [PATCH 3/9] gdb: Make use of safe-ctype.h header Andrew Burgess
@ 2015-09-11 18:50 ` Andrew Burgess
2015-09-30 13:52 ` Pedro Alves
2015-09-11 18:50 ` [PATCH 1/9] gdb: Check the selected-frame in frame_find_by_id Andrew Burgess
` (2 subsequent siblings)
9 siblings, 1 reply; 25+ messages in thread
From: Andrew Burgess @ 2015-09-11 18:50 UTC (permalink / raw)
To: gdb-patches; +Cc: Andrew Burgess
The func_command function is used to emulate the dbx 'func' command.
However, finding a stack frame based on function name might be a useful
feature, and so the core of func_command is now split out into a
separate function.
gdb/ChangeLog:
* 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
function comment.
(find_frame_for_function): New function, now returns a result.
---
gdb/ChangeLog | 8 ++++++++
gdb/stack.c | 49 ++++++++++++++++++++++++++++++++-----------------
2 files changed, 40 insertions(+), 17 deletions(-)
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index d530d06..9da954d 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,13 @@
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
+ function comment.
+ (find_frame_for_function): New function, now returns a result.
+
+2015-09-11 Andrew Burgess <andrew.burgess@embecosm.com>
+
* stack.c (parse_frame_specification): Remove message parameter,
replace with fixed string in function body, update function
comment.
diff --git a/gdb/stack.c b/gdb/stack.c
index 9cde1e5..71e171a 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -2211,15 +2211,6 @@ args_info (char *ignore, int from_tty)
gdb_stdout);
}
-/* Select frame FRAME. Also print the stack frame and show the source
- if this is the tui version. */
-static void
-select_and_print_frame (struct frame_info *frame)
-{
- select_frame (frame);
- if (frame)
- print_stack_frame (frame, 1, SRC_AND_LOC, 1);
-}
\f
/* Return the symbol-block in which the selected frame is executing.
Can return zero under various legitimate circumstances.
@@ -2507,8 +2498,11 @@ struct function_bounds
CORE_ADDR low, high;
};
-static void
-func_command (char *arg, int from_tty)
+/* Find stack frame for a function matching FUNCTION_NAME. If there is no
+ matching stack frame then return NULL. */
+
+static struct frame_info *
+find_frame_for_function (char *function_name)
{
struct frame_info *frame;
int found = 0;
@@ -2518,11 +2512,11 @@ func_command (char *arg, int from_tty)
struct function_bounds *func_bounds = NULL;
struct cleanup *cleanups;
- if (arg == NULL)
- return;
+ gdb_assert (function_name != NULL);
frame = get_current_frame ();
- sals = decode_line_with_current_source (arg, DECODE_LINE_FUNFIRSTLINE);
+ sals = decode_line_with_current_source (function_name,
+ DECODE_LINE_FUNFIRSTLINE);
cleanups = make_cleanup (xfree, sals.sals);
func_bounds = XNEWVEC (struct function_bounds, sals.nelts);
make_cleanup (xfree, func_bounds);
@@ -2555,10 +2549,31 @@ func_command (char *arg, int from_tty)
do_cleanups (cleanups);
if (!found)
- printf_filtered (_("'%s' not within current stack frame.\n"), arg);
- else if (frame != get_selected_frame (NULL))
- select_and_print_frame (frame);
+ frame = NULL;
+
+ return frame;
}
+
+/* Implements the dbx 'func' command. */
+
+static void
+func_command (char *arg, int from_tty)
+{
+ struct frame_info *frame;
+
+ if (arg == NULL)
+ return;
+
+ frame = find_frame_for_function (arg);
+ if (frame == NULL)
+ error (_("'%s' not within current stack frame.\n"), arg);
+ if (frame != get_selected_frame (NULL))
+ {
+ select_frame (frame);
+ print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC, 1);
+ }
+}
+
\f
/* Provide a prototype to silence -Wmissing-prototypes. */
--
2.5.1
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [PATCH 8/9] gdb: Split func_command into two parts.
2015-09-11 18:50 ` [PATCH 8/9] gdb: Split func_command into two parts Andrew Burgess
@ 2015-09-30 13:52 ` Pedro Alves
0 siblings, 0 replies; 25+ messages in thread
From: Pedro Alves @ 2015-09-30 13:52 UTC (permalink / raw)
To: Andrew Burgess, gdb-patches
On 09/11/2015 07:49 PM, Andrew Burgess wrote:
> The func_command function is used to emulate the dbx 'func' command.
> However, finding a stack frame based on function name might be a useful
> feature,
Indeed.
> and so the core of func_command is now split out into a
> separate function.
>
> gdb/ChangeLog:
>
> * 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
> function comment.
> (find_frame_for_function): New function, now returns a result.
OK.
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 1/9] gdb: Check the selected-frame in frame_find_by_id.
2015-09-11 18:49 [PATCH 0/9] Changes to frame selection Andrew Burgess
` (6 preceding siblings ...)
2015-09-11 18:50 ` [PATCH 8/9] gdb: Split func_command into two parts Andrew Burgess
@ 2015-09-11 18:50 ` Andrew Burgess
2015-09-30 13:40 ` Pedro Alves
2015-09-11 18:50 ` [PATCH 5/9] gdb: Fix bug with dbx style func command Andrew Burgess
2015-10-12 21:43 ` [PATCH 0/9] Changes to frame selection Andrew Burgess
9 siblings, 1 reply; 25+ messages in thread
From: Andrew Burgess @ 2015-09-11 18:50 UTC (permalink / raw)
To: gdb-patches; +Cc: Andrew Burgess
In gdb we track two different things, the current-frame, and the
selected-frame. The current-frame represents the frame in which we are
currently stopped. If gdb stops at a breakpoint and the user asks for a
backtrace then all the frames in the backtrace will be the ancestors of
the the current-frame.
Also the current-frame does not change until the inferior is set running
again (though it is possible for the user to alter the contents of the
current-frame this is not the same as changing the current-frame).
There is also the selected-frame. This is the frame that the user has
"selected" using the frame selection commands 'frame', 'up', or 'down'
being the most common.
Usually the selected-frame is always an ancestor of the current-frame,
however, there is a feature of the 'frame' command that allows arbitrary
frames to be created, in this case the selected-frame might not be an
ancestor of the current-frame.
The problem this causes is that lazy register values hold the frame-id
for the frame in which the real register value can be obtained. When
gdb needs to fetch the actual register value we try to find the frame
using frame_find_by_id, which currently looks at the current-frame, and
all the ancestors of the current-frame.
When the selected-frame is not an ancestor of the current-frame then
frame_find_by_id will fail to find the required frame, and gdb will fail
with an assertion while trying to fetch the lazy value (the assertion is
that the frame will always be found).
This patch extends frame_find_by_id to also check the selected-frame as
a separate comparison as well as the current-frame and its ancestors.
This resolves the issue.
There are also two new tests added that show this issue. The first is
an mi test using var objects, which is where I first saw this issue.
The second is a slightly simpler test, just creating a new frame then
calling 'info frame' is enough to trigger the assertion.
gdb/ChangeLog:
* frame.c (frame_find_by_id): Also check the selected frame.
gdb/testsuite/ChangeLog:
* gdb.mi/mi-var-frame.c: New file.
* gdb.mi/mi-var-frame.exp: New file.
* gdb.base/frame-cmds.c: New file.
* gdb.base/frame-cmds.exp: New file.
---
gdb/ChangeLog | 4 ++
gdb/frame.c | 18 +++++++--
gdb/testsuite/ChangeLog | 7 ++++
gdb/testsuite/gdb.base/frame-cmds.c | 34 +++++++++++++++++
gdb/testsuite/gdb.base/frame-cmds.exp | 30 +++++++++++++++
gdb/testsuite/gdb.mi/mi-var-frame.c | 34 +++++++++++++++++
gdb/testsuite/gdb.mi/mi-var-frame.exp | 70 +++++++++++++++++++++++++++++++++++
7 files changed, 194 insertions(+), 3 deletions(-)
create mode 100644 gdb/testsuite/gdb.base/frame-cmds.c
create mode 100644 gdb/testsuite/gdb.base/frame-cmds.exp
create mode 100644 gdb/testsuite/gdb.mi/mi-var-frame.c
create mode 100644 gdb/testsuite/gdb.mi/mi-var-frame.exp
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index d7a8d31..b4fe9cc 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,7 @@
+2015-09-11 Andrew Burgess <andrew.burgess@embecosm.com>
+
+ * frame.c (frame_find_by_id): Also check the selected frame.
+
2015-09-11 Pierre Langlois <pierre.langlois@arm.com>
* aarch64-tdep.c (decode_cb): Move up comment describing the
diff --git a/gdb/frame.c b/gdb/frame.c
index 745e007..114fa6a 100644
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -732,7 +732,7 @@ frame_id_inner (struct gdbarch *gdbarch, struct frame_id l, struct frame_id r)
struct frame_info *
frame_find_by_id (struct frame_id id)
{
- struct frame_info *frame, *prev_frame;
+ struct frame_info *frame, *prev_frame, *selected_frame;
/* ZERO denotes the null frame, let the caller decide what to do
about it. Should it instead return get_current_frame()? */
@@ -761,7 +761,7 @@ frame_find_by_id (struct frame_id id)
prev_frame = get_prev_frame (frame);
if (!prev_frame)
- return NULL;
+ break;
/* As a safety net to avoid unnecessary backtracing while trying
to find an invalid ID, we check for a common situation where
@@ -772,8 +772,20 @@ frame_find_by_id (struct frame_id id)
&& !frame_id_inner (get_frame_arch (frame), id, self)
&& frame_id_inner (get_frame_arch (prev_frame), id,
get_frame_id (prev_frame)))
- return NULL;
+ break;
+ }
+
+ /* We check the selected frame specifically here to handle the case where
+ the selected frame is not an ancestor of the current frame. */
+ selected_frame = get_selected_frame_if_set ();
+ if (selected_frame)
+ {
+ struct frame_id selected_frame_id = get_frame_id (selected_frame);
+
+ if (frame_id_eq (id, selected_frame_id))
+ return frame;
}
+
return NULL;
}
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 1538d15..cf83b3a 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2015-09-11 Andrew Burgess <andrew.burgess@embecosm.com>
+
+ * gdb.mi/mi-var-frame.c: New file.
+ * gdb.mi/mi-var-frame.exp: New file.
+ * gdb.base/frame-cmds.c: New file.
+ * gdb.base/frame-cmds.exp: New file.
+
2015-09-09 Doug Evans <dje@google.com>
* gdb.python/py-prettyprint.exp: Check result of run_lang_tests.
diff --git a/gdb/testsuite/gdb.base/frame-cmds.c b/gdb/testsuite/gdb.base/frame-cmds.c
new file mode 100644
index 0000000..53b222d
--- /dev/null
+++ b/gdb/testsuite/gdb.base/frame-cmds.c
@@ -0,0 +1,34 @@
+/* Copyright 2015 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+int
+frame_2 (void)
+{
+ return 0;
+}
+
+int
+frame_1 (void)
+{
+ return frame_2 ();
+}
+
+int
+main (void)
+{
+ return frame_1 ();
+}
diff --git a/gdb/testsuite/gdb.base/frame-cmds.exp b/gdb/testsuite/gdb.base/frame-cmds.exp
new file mode 100644
index 0000000..2518463
--- /dev/null
+++ b/gdb/testsuite/gdb.base/frame-cmds.exp
@@ -0,0 +1,30 @@
+# Copyright 2015 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+if { [prepare_for_testing create-frame.exp "create-frame" {create-frame.c} {debug nowarnings}] } {
+ return -1
+}
+set srcfile create-frame.c
+
+runto_main
+gdb_breakpoint frame_2
+gdb_continue_to_breakpoint frame_2
+
+gdb_test "bt" "#0.*#1.*#2.*" "backtrace at breakpoint"
+
+gdb_test_no_output "select-frame 3"
+
+gdb_test "info frame" "Stack level 0, frame at 0x3:.*" \
+ "info frame for created frame"
diff --git a/gdb/testsuite/gdb.mi/mi-var-frame.c b/gdb/testsuite/gdb.mi/mi-var-frame.c
new file mode 100644
index 0000000..53b222d
--- /dev/null
+++ b/gdb/testsuite/gdb.mi/mi-var-frame.c
@@ -0,0 +1,34 @@
+/* Copyright 2015 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+int
+frame_2 (void)
+{
+ return 0;
+}
+
+int
+frame_1 (void)
+{
+ return frame_2 ();
+}
+
+int
+main (void)
+{
+ return frame_1 ();
+}
diff --git a/gdb/testsuite/gdb.mi/mi-var-frame.exp b/gdb/testsuite/gdb.mi/mi-var-frame.exp
new file mode 100644
index 0000000..5c3f196
--- /dev/null
+++ b/gdb/testsuite/gdb.mi/mi-var-frame.exp
@@ -0,0 +1,70 @@
+# Copyright 2015 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# This tests an issue relating to updating var objects in user created
+# frames.
+
+# This test requires a register name for creating a var object.
+# Currently only x86/x86_64 like targets are supported.
+if {![istarget "x86_64-*-*"] && ![istarget "i?86-*-*"]} {
+ return 0
+}
+
+load_lib mi-support.exp
+set MIFLAGS "-i=mi"
+
+gdb_exit
+if [mi_gdb_start] {
+ continue
+}
+
+standard_testfile mi-var-frame.c
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ untested mi-var-frame.exp
+ return -1
+}
+
+mi_delete_breakpoints
+mi_gdb_reinitialize_dir $srcdir/$subdir
+mi_gdb_load ${binfile}
+
+mi_create_breakpoint "frame_2" \
+ "break-insert into frame_2" \
+ -number 1 -func frame_2 -file ".*${srcfile}"
+
+mi_run_cmd
+mi_expect_stop "breakpoint-hit" "frame_2" "" ".*${srcfile}" \
+ ".*" { "" "disp=\"keep\"" } "run to breakpoint"
+
+mi_gdb_test "-stack-info-depth" \
+ "\\^done,depth=\"3\"" \
+ "stack info-depth"
+
+set register "\$eax"
+
+mi_gdb_test "-var-create R * $register" \
+ "\\^done,name=\"R\",numchild=\"0\",value=\".*\",type=\".*\",has_more=\"0\"" \
+ "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"
+
+ mi_gdb_test "-var-update R" \
+ "\\^done,changelist=\\\[\\\]" \
+ "update 'R' in frame $i: no change"
+}
--
2.5.1
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [PATCH 1/9] gdb: Check the selected-frame in frame_find_by_id.
2015-09-11 18:50 ` [PATCH 1/9] gdb: Check the selected-frame in frame_find_by_id Andrew Burgess
@ 2015-09-30 13:40 ` Pedro Alves
0 siblings, 0 replies; 25+ messages in thread
From: Pedro Alves @ 2015-09-30 13:40 UTC (permalink / raw)
To: Andrew Burgess, gdb-patches
Hi Andrew,
On 09/11/2015 07:49 PM, Andrew Burgess wrote:
> In gdb we track two different things, the current-frame, and the
> selected-frame. The current-frame represents the frame in which we are
> currently stopped. If gdb stops at a breakpoint and the user asks for a
> backtrace then all the frames in the backtrace will be the ancestors of
> the the current-frame.
>
> Also the current-frame does not change until the inferior is set running
> again (though it is possible for the user to alter the contents of the
> current-frame this is not the same as changing the current-frame).
>
> There is also the selected-frame. This is the frame that the user has
> "selected" using the frame selection commands 'frame', 'up', or 'down'
> being the most common.
>
> Usually the selected-frame is always an ancestor of the current-frame,
> however, there is a feature of the 'frame' command that allows arbitrary
> frames to be created, in this case the selected-frame might not be an
> ancestor of the current-frame.
>
> The problem this causes is that lazy register values hold the frame-id
> for the frame in which the real register value can be obtained. When
> gdb needs to fetch the actual register value we try to find the frame
> using frame_find_by_id, which currently looks at the current-frame, and
> all the ancestors of the current-frame.
>
> When the selected-frame is not an ancestor of the current-frame then
> frame_find_by_id will fail to find the required frame, and gdb will fail
> with an assertion while trying to fetch the lazy value (the assertion is
> that the frame will always be found).
>
> This patch extends frame_find_by_id to also check the selected-frame as
> a separate comparison as well as the current-frame and its ancestors.
> This resolves the issue.
>
> There are also two new tests added that show this issue. The first is
> an mi test using var objects, which is where I first saw this issue.
> The second is a slightly simpler test, just creating a new frame then
> calling 'info frame' is enough to trigger the assertion.
Seems to me that this issue runs deeper.
Two points:
#1 - Consider what happens if something flushes the frame cache while
the user is looking at a manually-created frame. Anything that
calls registers_changed() and relies on the old selected frame _id_
to re-unwind, re-populate the frame cache, and re-find the old selected
frame object (e.g., see make_cleanup_restore_current_thread).
As is, the selected frame's frame_info object is gone along with the frame cache
flush, so gdb will just unexpectedly lose the selected frame when it tries
to re-find it. E.g., something around:
thread2 ()
{
while (1)
sleep (1);
}
main ()
{
create thread (thread2);
join thread2;
}
(gdb) set non-stop on
(gdb) break sleep if 0
(gdb) c -a&
(gdb) thread 1
(gdb) interrupt
(gdb) frame create 0xaddr
// now the breakpoint at sleep triggers
// while we're looking at the created frame.
// gdb switches to thread 2 internally to handle
// the event, re-resumes the thread (bp condition evals false),
// and then tries to restore the previously selected frame, which
// is gone. so gdb falls back to re-selecting the current frame...
Or simpler, from reading the code, it seems like just "info threads"
should trigger that too.
#2 - As mentioned in my comment here:
https://sourceware.org/bugzilla/show_bug.cgi?id=18074#c1
I think the fix should consider what should happen to
"backtrace" after "frame create". Currently, we always start
the backtrace at the current frame, so the created frame does
not appear in the backtrace. But if the user does "frame create",
and can follow that with "up", shouldn't "bt" after "frame ADDR" to
attempt to backtrace starting at the created frame too?
That would suggest that the fix for this instead would be for
"frame create" to override the source of the current frame.
That then raises the question of how to get out of that
frame.
I'm not saying that that's the best model, but I do think this
should be considered, and the way forward depends on
how frame-related / backtrace commands _should_ work around
"frame create".
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH 5/9] gdb: Fix bug with dbx style func command.
2015-09-11 18:49 [PATCH 0/9] Changes to frame selection Andrew Burgess
` (7 preceding siblings ...)
2015-09-11 18:50 ` [PATCH 1/9] gdb: Check the selected-frame in frame_find_by_id Andrew Burgess
@ 2015-09-11 18:50 ` Andrew Burgess
2015-09-30 13:47 ` Pedro Alves
2015-10-12 21:43 ` [PATCH 0/9] Changes to frame selection Andrew Burgess
9 siblings, 1 reply; 25+ messages in thread
From: Andrew Burgess @ 2015-09-11 18:50 UTC (permalink / raw)
To: gdb-patches; +Cc: Andrew Burgess
The func command, available when starting gdb in dbx mode, is supposed
to take a function name and locate the frame for that function in the
stack. This has been broken for a while due to an invalid check of the
arguments within the worker function. Fixed in this commit.
gdb/ChangeLog:
* stack.c (func_command): Return early when there is no ARG
string.
gdb/testsuite/ChangeLog:
* gdb.base/dbx.exp (test_func): Remove xfails, update expected
results.
---
gdb/ChangeLog | 5 +++++
gdb/stack.c | 2 +-
gdb/testsuite/ChangeLog | 5 +++++
gdb/testsuite/gdb.base/dbx.exp | 6 +-----
4 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 50aa7f0..7c4b567 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,10 @@
2015-09-11 Andrew Burgess <andrew.burgess@embecosm.com>
+ * stack.c (func_command): Return early when there is no ARG
+ string.
+
+2015-09-11 Andrew Burgess <andrew.burgess@embecosm.com>
+
* stack.c: Include safe-ctype.h not ctype.h.
(parse_frame_specification): Use ISSPACE not isspace.
(backtrace_command): Use TOLOWER not tolower.
diff --git a/gdb/stack.c b/gdb/stack.c
index 2fe176f..1049995 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -2527,7 +2527,7 @@ func_command (char *arg, int from_tty)
struct function_bounds *func_bounds = NULL;
struct cleanup *cleanups;
- if (arg != NULL)
+ if (arg == NULL)
return;
frame = parse_frame_specification ("0");
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index ee0ad76..272d3fc 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,10 @@
2015-09-11 Andrew Burgess <andrew.burgess@embecosm.com>
+ * gdb.base/dbx.exp (test_func): Remove xfails, update expected
+ results.
+
+2015-09-11 Andrew Burgess <andrew.burgess@embecosm.com>
+
* gdb.base/create-frame.exp: Add test for 'info frame' with
specific address.
diff --git a/gdb/testsuite/gdb.base/dbx.exp b/gdb/testsuite/gdb.base/dbx.exp
index 19dba62..75cb0fd 100644
--- a/gdb/testsuite/gdb.base/dbx.exp
+++ b/gdb/testsuite/gdb.base/dbx.exp
@@ -293,15 +293,11 @@ proc test_func { } {
global srcfile2
gdb_test "cont" ".*" "cont 1"
gdb_test "step" ".*"
- # This always fails, but it's not clear why. -sts 1999-08-17
- setup_xfail "*-*-*"
gdb_test "func sum" "'sum' not within current stack frame\."
set stop_line [gdb_get_line_number "stop-in-sum" $srcfile2]
gdb_test "stop in sum" "Breakpoint.*at.*: file.*sum\.c, line $stop_line\."
gdb_test "cont" ".*" "cont 2"
- # This always fails, but it's not clear why. -sts 1999-08-17
- setup_xfail "*-*-*"
- gdb_test "func print_average" ".*in print_average.*\\(list=.*, low=0, high=6\\).*at.*average\.c:${decimal}\r\n\${decimal}\[ \t\]+total = sum\\(list, low, high\\);"
+ gdb_test "func print_average" ".*in print_average.*\\(list=.*, low=0, high=6\\).*at.*average\.c:${decimal}\r\n${decimal}\[ \t\]+total = sum\\(list, low, high\\);"
}
# Start with a fresh gdb.
--
2.5.1
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [PATCH 5/9] gdb: Fix bug with dbx style func command.
2015-09-11 18:50 ` [PATCH 5/9] gdb: Fix bug with dbx style func command Andrew Burgess
@ 2015-09-30 13:47 ` Pedro Alves
2015-10-26 13:40 ` Thomas Preud'homme
0 siblings, 1 reply; 25+ messages in thread
From: Pedro Alves @ 2015-09-30 13:47 UTC (permalink / raw)
To: Andrew Burgess, gdb-patches
On 09/11/2015 07:49 PM, Andrew Burgess wrote:
> The func command, available when starting gdb in dbx mode, is supposed
> to take a function name and locate the frame for that function in the
> stack. This has been broken for a while due to an invalid check of the
> arguments within the worker function. Fixed in this commit.
I wonder whether anyone uses / cares about the dbx mode...
>
> gdb/ChangeLog:
>
> * stack.c (func_command): Return early when there is no ARG
> string.
>
> gdb/testsuite/ChangeLog:
>
> * gdb.base/dbx.exp (test_func): Remove xfails, update expected
> results.
OK.
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 25+ messages in thread
* RE: [PATCH 5/9] gdb: Fix bug with dbx style func command.
2015-09-30 13:47 ` Pedro Alves
@ 2015-10-26 13:40 ` Thomas Preud'homme
2015-10-26 16:33 ` Andrew Burgess
0 siblings, 1 reply; 25+ messages in thread
From: Thomas Preud'homme @ 2015-10-26 13:40 UTC (permalink / raw)
To: 'Pedro Alves', Andrew Burgess, gdb-patches
> From: gdb-patches-owner@sourceware.org [mailto:gdb-patches-
> owner@sourceware.org] On Behalf Of Pedro Alves
> Sent: Wednesday, September 30, 2015 9:47 PM
>
> On 09/11/2015 07:49 PM, Andrew Burgess wrote:
> > The func command, available when starting gdb in dbx mode, is
> supposed
> > to take a function name and locate the frame for that function in the
> > stack. This has been broken for a while due to an invalid check of the
> > arguments within the worker function. Fixed in this commit.
>
> I wonder whether anyone uses / cares about the dbx mode...
>
> >
> > gdb/ChangeLog:
> >
> > * stack.c (func_command): Return early when there is no ARG
> > string.
> >
> > gdb/testsuite/ChangeLog:
> >
> > * gdb.base/dbx.exp (test_func): Remove xfails, update
> expected
> > results.
>
> OK.
Actually dbx style func still fails on ARM so this changes shows up as a regression (XFAIL- > FAIL). See [1] for a bit more details.
[1] https://sourceware.org/bugzilla/show_bug.cgi?id=19127
Best regards,
Thomas
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 5/9] gdb: Fix bug with dbx style func command.
2015-10-26 13:40 ` Thomas Preud'homme
@ 2015-10-26 16:33 ` Andrew Burgess
0 siblings, 0 replies; 25+ messages in thread
From: Andrew Burgess @ 2015-10-26 16:33 UTC (permalink / raw)
To: Thomas Preud'homme; +Cc: 'Pedro Alves', gdb-patches
* Thomas Preud'homme <thomas.preudhomme@arm.com> [2015-10-26 18:38:17 +0800]:
> > From: gdb-patches-owner@sourceware.org [mailto:gdb-patches-
> > owner@sourceware.org] On Behalf Of Pedro Alves
> > Sent: Wednesday, September 30, 2015 9:47 PM
> >
> > On 09/11/2015 07:49 PM, Andrew Burgess wrote:
> > > The func command, available when starting gdb in dbx mode, is
> > supposed
> > > to take a function name and locate the frame for that function in the
> > > stack. This has been broken for a while due to an invalid check of the
> > > arguments within the worker function. Fixed in this commit.
> >
> > I wonder whether anyone uses / cares about the dbx mode...
> >
> > >
> > > gdb/ChangeLog:
> > >
> > > * stack.c (func_command): Return early when there is no ARG
> > > string.
> > >
> > > gdb/testsuite/ChangeLog:
> > >
> > > * gdb.base/dbx.exp (test_func): Remove xfails, update
> > expected
> > > results.
> >
> > OK.
>
> Actually dbx style func still fails on ARM so this changes shows up
> as a regression (XFAIL- > FAIL). See [1] for a bit more details.
The failure you're seeing on ARM, where gdb says "Target is
executing." seems pretty strange, and certainly isn't the failure that
I would have expected before, this looks like a different issue, which
is probably worth some investigation. I'm guessing here, but I doubt
that the original XFAIL I removed was intended to mask this specific
failure.
It would probably help to diagnose this issue if you could attach a
gdb.log for a test run of dbx.exp.
Thanks,
Andrew
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH 0/9] Changes to frame selection.
2015-09-11 18:49 [PATCH 0/9] Changes to frame selection Andrew Burgess
` (8 preceding siblings ...)
2015-09-11 18:50 ` [PATCH 5/9] gdb: Fix bug with dbx style func command Andrew Burgess
@ 2015-10-12 21:43 ` Andrew Burgess
9 siblings, 0 replies; 25+ messages in thread
From: Andrew Burgess @ 2015-10-12 21:43 UTC (permalink / raw)
To: gdb-patches
I have pushed patches #3, #4, #5, #6, and #7 from this series. These
were all clean up patches that can live on their own, and were
approved by Pedro / Eli.
I am updating the rest of the patches based on the feedback and will
post a revised series soon.
Thanks,
Andrew
^ permalink raw reply [flat|nested] 25+ messages in thread