This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] -stack-info-depth should always return a count.


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
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]