This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[PATCH] -stack-info-depth should always return a count.
- From: Andrew Burgess <aburgess at broadcom dot com>
- To: "gdb-patches at sourceware dot org" <gdb-patches at sourceware dot org>
- Date: Thu, 27 Mar 2014 13:20:25 +0000
- Subject: [PATCH] -stack-info-depth should always return a count.
- Authentication-results: sourceware.org; auth=none
The MI command -stack-info-depth return the "depth" field in most
cases. However, if due to stack corruption, gdb tries to access
some invalid memory then the result is an error and no depth.
I believe that the current behaviour would be better if gdb always
returned a depth number, indicating the number of frames that are
available before the stack corruption, the patch below does this.
I have also added an new "reason" field to the -stack-info-depth
reply, the reason is a string that tries to explain why gdb is
giving this depth as an answer.
For stacks without any corruption the only two possible reason
strings are "All frames" (this is the total stack depth), or
"Reached frame limit" (a LIMIT was passed to -stack-info-depth
and reached). If there is stack corruption then the reason will
be the error string from gdb.
OK to apply?
Thanks,
Andrew
gdb/ChangeLog:
2014-03-27 Andrew Burgess <aburgess@broadcom.com>
* mi/mi-cmd-stack.c (mi_cmd_stack_info_depth): Add TRY_CATCH
around the stack unwind. Add a reason field to explain the given
depth.
* NEWS: Mention changes to -stack-info-depth command.
gdb/testsuite/ChangeLog:
2014-03-27 Andrew Burgess <aburgess@broadcom.com>
* gdb.mi/mi-stack.exp (test_stack_info_depth): Expect new reason
field.
gdb/doc/ChangeLog:
2014-03-27 Andrew Burgess <aburgess@broadcom.com>
* gdb.texinfo (gdb/mi Stack Manipulation): Add information and
examples explaining new reason field for -stack-info-depth
command.
diff --git a/gdb/mi/mi-cmd-stack.c b/gdb/mi/mi-cmd-stack.c
index 7bc8114..9a4eec7 100644
--- a/gdb/mi/mi-cmd-stack.c
+++ b/gdb/mi/mi-cmd-stack.c
@@ -170,8 +170,10 @@ void
mi_cmd_stack_info_depth (char *command, char **argv, int argc)
{
int frame_high;
- int i;
+ int i = 0;
struct frame_info *fi;
+ volatile struct gdb_exception except;
+ const char *reason;
if (argc > 1)
error (_("-stack-info-depth: Usage: [MAX_DEPTH]"));
@@ -183,12 +185,29 @@ mi_cmd_stack_info_depth (char *command, char **argv, int argc)
the stack. */
frame_high = -1;
- for (i = 0, fi = get_current_frame ();
- fi && (i < frame_high || frame_high == -1);
- i++, fi = get_prev_frame (fi))
- QUIT;
+ TRY_CATCH (except, RETURN_MASK_ERROR)
+ {
+ for (i = 0, fi = get_current_frame ();
+ fi && (i < frame_high || frame_high == -1);
+ i++, fi = get_prev_frame (fi))
+ QUIT;
+ }
+
+ if (except.message)
+ {
+ /* Due to the lazy way state is fetched from the target, if we have
+ an exception our depth count will be one greater than it should
+ be. */
+ reason = except.message;
+ --i;
+ }
+ else if (frame_high == -1 || i < frame_high)
+ reason = _("All frames");
+ else
+ reason = _("Reached frame limit");
ui_out_field_int (current_uiout, "depth", i);
+ ui_out_field_string (current_uiout, "reason", reason);
}
/* Print a list of the locals for the current frame. With argument of
2014-03-26 Yao Qi <yao@codesourcery.com>
* lib/gdb.exp (readline_is_used): New proc.
diff --git a/gdb/testsuite/gdb.mi/mi-stack.exp b/gdb/testsuite/gdb.mi/mi-stack.exp
index ac7db7a..4977342 100644
--- a/gdb/testsuite/gdb.mi/mi-stack.exp
+++ b/gdb/testsuite/gdb.mi/mi-stack.exp
@@ -137,15 +137,15 @@ proc test_stack_info_depth {} {
# -stack-info-depth 99
mi_gdb_test "231-stack-info-depth" \
- "231\\^done,depth=\"5\"" \
+ "231\\^done,depth=\"5\",reason=\"\[^\"\]+\"" \
"stack info-depth"
mi_gdb_test "231-stack-info-depth 3" \
- "231\\^done,depth=\"3\"" \
+ "231\\^done,depth=\"3\",reason=\"\[^\"\]+\"" \
"stack info-depth 3"
mi_gdb_test "231-stack-info-depth 99" \
- "231\\^done,depth=\"5\"" \
+ "231\\^done,depth=\"5\",reason=\"\[^\"\]+\"" \
"stack info-depth 99"
mi_gdb_test "231-stack-info-depth 99 99" \
diff --git a/gdb/NEWS b/gdb/NEWS
index 2a384ba..172101e 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -95,6 +95,12 @@ PowerPC64 GNU/Linux little-endian powerpc64le-*-linux*
and "assf"), have been deprecated. Use the "sharedlibrary" command, or
its alias "share", instead.
+* MI changes
+
+ ** The -stack-info-depth command will now always return a depth even if
+ stack corruption is encountered. A new reason string is also returned
+ that explains why gdb is reporting this depth.
+
*** Changes in GDB 7.7
* Improved support for process record-replay and reverse debugging on
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 1df3ca0..4f4ece8 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -27534,8 +27534,11 @@ fullname="/home/foo/bar/devo/gdb/testsuite/gdb.mi/basics.c",line="17"@}
-stack-info-depth [ @var{max-depth} ]
@end smallexample
-Return the depth of the stack. If the integer argument @var{max-depth}
-is specified, do not count beyond @var{max-depth} frames.
+Return the depth of the stack. If the integer argument
+@var{max-depth} is specified, do not count beyond @var{max-depth}
+frames. The reason why gdb returns the answer it does is also given.
+Possible reasons are @var{All frames}, @var{Reached frame limit}, or
+an error message.
@subsubheading @value{GDBN} Command
@@ -27548,19 +27551,35 @@ For a stack with frame levels 0 through 11:
@smallexample
(gdb)
-stack-info-depth
-^done,depth="12"
+^done,depth="12",reason="All frames"
(gdb)
-stack-info-depth 4
-^done,depth="4"
+^done,depth="4",reason="Reached frame limit"
(gdb)
-stack-info-depth 12
-^done,depth="12"
+^done,depth="12",reason="Reached frame limit"
(gdb)
-stack-info-depth 11
-^done,depth="11"
+^done,depth="11",reason="Reached frame limit"
(gdb)
-stack-info-depth 13
-^done,depth="12"
+^done,depth="12",reason="All frames"
+(gdb)
+@end smallexample
+
+An example where there are 3 valid stack frames, after which the stack
+pointer is corrupted and gdb is unable to unwind the stack further:
+
+@smallexample
+(gdb)
+-stack-info-depth
+^done,depth="3",reason="Cannot access memory at address 0xffffffff"
+(gdb)
+-stack-info-depth 4
+^done,depth="3",reason="Cannot access memory at address 0xffffffff"
+(gdb)
+-stack-info-depth 3
+^done,depth="3",reason="Reached frame limit"
(gdb)
@end smallexample