Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Kevin Pouget <kevin.pouget@gmail.com>
To: Eli Zaretskii <eliz@gnu.org>
Cc: pedro@codesourcery.com, pmuldoon@redhat.com,
	gdb-patches@sourceware.org, 	tromey@redhat.com
Subject: Re: [RFC][Python] gdbpy_frame_stop_reason_string bug
Date: Thu, 27 Oct 2011 10:02:00 -0000	[thread overview]
Message-ID: <CAPftXU+z_bra3oZN7skA-hb7C_xJydNyrT7qrL8jHBetkt=Few@mail.gmail.com> (raw)
In-Reply-To: <CAPftXUJ0xABKVu=NaLEffLe0a_jVfkyCh6yx_UfBrxLVyBXt0w@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 4490 bytes --]

On Tue, Oct 25, 2011 at 2:48 PM, Kevin Pouget <kevin.pouget@gmail.com> wrote:
> On Tue, Oct 25, 2011 at 2:22 PM, Eli Zaretskii <eliz@gnu.org> wrote:
>>> From: Kevin Pouget <kevin.pouget@gmail.com>
>>> Date: Tue, 25 Oct 2011 09:20:19 +0200
>>> Cc: pedro@codesourcery.com, pmuldoon@redhat.com, gdb-patches@sourceware.org,
>>>       tromey@redhat.com
>>>
>>> >> +@item gdb.FRAME_UNWIND_FIRST_ERROR
>>> >> +All the conditions after this alias are considered errors;
>>> >
>>> > Hmm...  This table is preceded by this text:
>>> >
>>> >  @defun Frame.unwind_stop_reason ()
>>> >  Return an integer representing the reason why it's not possible to find
>>> >  more frames toward the outermost frame.  Use
>>> >  @code{gdb.frame_stop_reason_string} to convert the value returned by this
>>> >  function to a string. The value can be one of:
>>> >
>>> > So "conditions after this alias" seems inappropriate in the list that
>>> > follows, because we are not describing conditions or aliases.  Can you
>>> > rephrase this to be consistent with the rest of the list.
>>>
>>> I'm not sure about you see wrong with "alias". We could replace it
>>> with "reference" (like the & operator in C++, but also used in Python
>>> and Java), but it sounds more or less the same to me.
>>>
>>> What do you think about:
>>> "Stop reasons greater or equal to this value/alias/reference"
>>
>> Now that I understand the intent, I would suggest
>>
>>  Any stop reason greater or equal to this value indicates some kind
>>  of error.  This special value facilitates writing code that tests
>>  for errors in unwinding in a way that will work correctly even if
>>  the list of the other values is modified in future @value{GDBN}
>>  versions.  Using it, you could write:
>
> yes, if you feel like it has to be explicited, it's better this way
>
> @smallexample
> reason = gdb.selected_frame().unwind_stop_reason ()
> reason_str =  gdb.frame_stop_reason_string (reason)
> if reason >=  gdb.FRAME_UNWIND_FIRST_ERROR:
>    print "An error occured during the unwinding process: %s" % reason_str
>
> @end smallexample
>>
>>> > And why is it important that the value is an alias for another?
>>>
>>> it's important because it's not a distinct value as the other ones, so
>>> > frame_stop_reason_string(UNWIND_FIRST_ERROR) == frame_stop_reason_string(UNWIND_UNAVAILABLE)
>>> is True, which might be counter-intuitive if you don't know that
>>> UNWIND_FIRST_ERROR is an alias/reference
>>
>> I still don't see the importance, sorry.  Moreover, having this text
>> means that we will need to update the manual each time the list of
>> unwind reasons is modified, **which in a way works against this very
>> feature.**
>
> You're half right with this last sentence, but this Python value is
> not here to ease *our* (GDB developers) lives, but rather for Python
> developers.
> this value is not meant to change very often (not to say almost
> never), so I think it's not a big burden to change the documentation
> as well when it happens.
> The very reason why I wrote it is that I think it's useful for the
> reader: when you look over this list, you can easily see what is a
> normal reason for unwinders to stop, and what isn't (I think that not
> so many people will actually have the chance to use it, but out of
> curiosity, some people will want to read and understand it).
>
>
> But that put aside, you're not convinced yet and I'm running short of
> arguments ... Pedro, Tom, Phil, how do you see that ?

Hello,

there was a line longer than 80char in unwind_reason.def, I've split it

I've also added the definition for FRAME_UNWIND_FIRST_ERROR that you
suggested Eli
(I've truncated the example to

> reason = gdb.selected_frame().unwind_stop_reason ()
> reason_str =  gdb.frame_stop_reason_string (reason)
> if reason >=  gdb.FRAME_UNWIND_FIRST_ERROR:
>     print "An error occured: %s" % reason_str

because the full line was too long for the PDF.

is it your last word for not mentioning the current value of the alias?


Thanks,

Kevin

2011-10-14  Kevin Pouget  <kevin.pouget@st.com>

	* frame.c (frame_stop_reason_string): Rewrite using
	unwind_stop_reasons.def.
	* frame.h (enum unwind_stop_reason): Likewise.
	* python/py-frame.c (gdbpy_initialize_frames): Likewise.
	(gdbpy_frame_stop_reason_string): Use new enum unwind_stop_reason
	constants for bound-checking.
	* unwind_stop_reasons.def: New file.

[-- Attachment #2: 0001-Move-unwind-reasons-to-an-external-.def-file.patch --]
[-- Type: text/x-patch, Size: 10038 bytes --]

From d310b0e18b3b6aaf029b16bfcfa9ba9e056e4348 Mon Sep 17 00:00:00 2001
From: Kevin Pouget <kevin.pouget@st.com>
Date: Mon, 17 Oct 2011 09:42:44 +0200
Subject: [PATCH] Move unwind reasons to an external .def file

---
 gdb/doc/gdb.texinfo         |   13 +++++++
 gdb/frame.c                 |   20 ++--------
 gdb/frame.h                 |   51 +++++----------------------
 gdb/python/py-frame.c       |   21 ++++-------
 gdb/stack.c                 |    2 +-
 gdb/unwind_stop_reasons.def |   80 +++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 116 insertions(+), 71 deletions(-)
 create mode 100644 gdb/unwind_stop_reasons.def

diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 69e2bda..f99fd4a4 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -23445,6 +23445,19 @@ stack corruption.
 @item gdb.FRAME_UNWIND_NO_SAVED_PC
 The frame unwinder did not find any saved PC, but we needed
 one to unwind further.
+
+@item gdb.FRAME_UNWIND_FIRST_ERROR
+Any stop reason greater or equal to this value indicates some kind
+of error.  This special value facilitates writing code that tests
+for errors in unwinding in a way that will work correctly even if
+the list of the other values is modified in future @value{GDBN}
+versions.  Using it, you could write:
+@smallexample
+reason = gdb.selected_frame().unwind_stop_reason ()
+reason_str =  gdb.frame_stop_reason_string (reason)
+if reason >=  gdb.FRAME_UNWIND_FIRST_ERROR:
+    print "An error occured: %s" % reason_str
+@end smallexample
 @end table
 
 @end defun
diff --git a/gdb/frame.c b/gdb/frame.c
index 5824020..e5e442a 100644
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -2351,23 +2351,11 @@ frame_stop_reason_string (enum unwind_stop_reason reason)
 {
   switch (reason)
     {
-    case UNWIND_NULL_ID:
-      return _("unwinder did not report frame ID");
+#define SET(name, description) \
+    case name: return _(description);
+#include "unwind_stop_reasons.def"
+#undef SET
 
-    case UNWIND_UNAVAILABLE:
-      return _("Not enough registers or memory available to unwind further");
-
-    case UNWIND_INNER_ID:
-      return _("previous frame inner to this frame (corrupt stack?)");
-
-    case UNWIND_SAME_ID:
-      return _("previous frame identical to this frame (corrupt stack?)");
-
-    case UNWIND_NO_SAVED_PC:
-      return _("frame did not save the PC");
-
-    case UNWIND_NO_REASON:
-    case UNWIND_FIRST_ERROR:
     default:
       internal_error (__FILE__, __LINE__,
 		      "Invalid frame stop reason");
diff --git a/gdb/frame.h b/gdb/frame.h
index a261a91..55972de 100644
--- a/gdb/frame.h
+++ b/gdb/frame.h
@@ -446,47 +446,16 @@ extern struct address_space *get_frame_address_space (struct frame_info *);
 
 enum unwind_stop_reason
   {
-    /* No particular reason; either we haven't tried unwinding yet,
-       or we didn't fail.  */
-    UNWIND_NO_REASON,
-
-    /* The previous frame's analyzer returns an invalid result
-       from this_id.
-
-       FIXME drow/2006-08-16: This is how GDB used to indicate end of
-       stack.  We should migrate to a model where frames always have a
-       valid ID, and this becomes not just an error but an internal
-       error.  But that's a project for another day.  */
-    UNWIND_NULL_ID,
-
-    /* This frame is the outermost.  */
-    UNWIND_OUTERMOST,
-
-    /* All the conditions after this point are considered errors;
-       abnormal stack termination.  If a backtrace stops for one
-       of these reasons, we'll let the user know.  This marker
-       is not a valid stop reason.  */
-    UNWIND_FIRST_ERROR,
-
-    /* Can't unwind further, because that would require knowing the
-       values of registers or memory that haven't been collected.  */
-    UNWIND_UNAVAILABLE,
-
-    /* This frame ID looks like it ought to belong to a NEXT frame,
-       but we got it for a PREV frame.  Normally, this is a sign of
-       unwinder failure.  It could also indicate stack corruption.  */
-    UNWIND_INNER_ID,
-
-    /* This frame has the same ID as the previous one.  That means
-       that unwinding further would almost certainly give us another
-       frame with exactly the same ID, so break the chain.  Normally,
-       this is a sign of unwinder failure.  It could also indicate
-       stack corruption.  */
-    UNWIND_SAME_ID,
-
-    /* The frame unwinder didn't find any saved PC, but we needed
-       one to unwind further.  */
-    UNWIND_NO_SAVED_PC,
+#define SET(name, description) name,
+#define FIRST_ENTRY(name) UNWIND_FIRST = name,
+#define LAST_ENTRY(name) UNWIND_LAST = name,
+#define FIRST_ERROR(name) UNWIND_FIRST_ERROR = name,
+
+#include "unwind_stop_reasons.def"
+#undef SET
+#undef FIRST_ENTRY
+#undef LAST_ENTRY
+#undef FIRST_ERROR
   };
 
 /* Return the reason why we can't unwind past this frame.  */
diff --git a/gdb/python/py-frame.c b/gdb/python/py-frame.c
index 398ce84..5ed4347 100644
--- a/gdb/python/py-frame.c
+++ b/gdb/python/py-frame.c
@@ -542,7 +542,7 @@ gdbpy_frame_stop_reason_string (PyObject *self, PyObject *args)
   if (!PyArg_ParseTuple (args, "i", &reason))
     return NULL;
 
-  if (reason < 0 || reason > UNWIND_NO_SAVED_PC)
+  if (reason < UNWIND_FIRST || reason > UNWIND_LAST)
     {
       PyErr_SetString (PyExc_ValueError, 
 		       _("Invalid frame stop reason."));
@@ -599,18 +599,13 @@ gdbpy_initialize_frames (void)
   PyModule_AddIntConstant (gdb_module, "SIGTRAMP_FRAME", SIGTRAMP_FRAME);
   PyModule_AddIntConstant (gdb_module, "ARCH_FRAME", ARCH_FRAME);
   PyModule_AddIntConstant (gdb_module, "SENTINEL_FRAME", SENTINEL_FRAME);
-  PyModule_AddIntConstant (gdb_module,
-			   "FRAME_UNWIND_NO_REASON", UNWIND_NO_REASON);
-  PyModule_AddIntConstant (gdb_module,
-			   "FRAME_UNWIND_NULL_ID", UNWIND_NULL_ID);
-  PyModule_AddIntConstant (gdb_module,
-			   "FRAME_UNWIND_FIRST_ERROR", UNWIND_FIRST_ERROR);
-  PyModule_AddIntConstant (gdb_module,
-			   "FRAME_UNWIND_INNER_ID", UNWIND_INNER_ID);
-  PyModule_AddIntConstant (gdb_module,
-			   "FRAME_UNWIND_SAME_ID", UNWIND_SAME_ID);
-  PyModule_AddIntConstant (gdb_module,
-			   "FRAME_UNWIND_NO_SAVED_PC", UNWIND_NO_SAVED_PC);
+
+#define SET(name, description) \
+  PyModule_AddIntConstant (gdb_module, "FRAME_"#name, name);
+#define FIRST_ERROR(name) \
+  PyModule_AddIntConstant (gdb_module, "FRAME_"#name, name);
+#include "unwind_stop_reasons.def"
+#undef SET
 
   Py_INCREF (&frame_object_type);
   PyModule_AddObject (gdb_module, "Frame", (PyObject *) &frame_object_type);
diff --git a/gdb/stack.c b/gdb/stack.c
index 953d3bd..003725a 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -1625,7 +1625,7 @@ backtrace_command_1 (char *count_exp, int show_locals, int from_tty)
       enum unwind_stop_reason reason;
 
       reason = get_frame_unwind_stop_reason (trailing);
-      if (reason > UNWIND_FIRST_ERROR)
+      if (reason >= UNWIND_FIRST_ERROR)
 	printf_filtered (_("Backtrace stopped: %s\n"),
 			 frame_stop_reason_string (reason));
     }
diff --git a/gdb/unwind_stop_reasons.def b/gdb/unwind_stop_reasons.def
new file mode 100644
index 0000000..9a34feb
--- /dev/null
+++ b/gdb/unwind_stop_reasons.def
@@ -0,0 +1,80 @@
+/* Copyright 2011 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/>.  */
+
+/* Reasons why frames could not be further unwound
+   SET (name, description)
+  
+   After this reason name, all reasons should be considered errors;
+   i.e.: abnormal stack termination.
+   FIRST_ERROR (name)  
+   
+   First and Last reason defined
+   FIRST_ENTRY (name)
+   LAST_ENTRY (name)  */
+
+#ifdef SET
+/* No particular reason; either we haven't tried unwinding yet, 
+   or we didn't fail.  */
+SET (UNWIND_NO_REASON, "no reason")
+
+/* The previous frame's analyzer returns an invalid result
+   from this_id.
+
+   FIXME drow/2006-08-16: This is how GDB used to indicate end of
+   stack.  We should migrate to a model where frames always have a
+   valid ID, and this becomes not just an error but an internal
+   error.  But that's a project for another day.  */
+SET (UNWIND_NULL_ID, "unwinder did not report frame ID")
+
+/* This frame is the outermost.  */
+SET (UNWIND_OUTERMOST, "outermost")
+
+/* Can't unwind further, because that would require knowing the
+   values of registers or memory that haven't been collected.  */
+SET (UNWIND_UNAVAILABLE, \
+     "not enough registers or memory available to unwind further")
+
+/* This frame ID looks like it ought to belong to a NEXT frame,
+   but we got it for a PREV frame.  Normally, this is a sign of
+   unwinder failure.  It could also indicate stack corruption.  */
+SET (UNWIND_INNER_ID, "previous frame inner to this frame (corrupt stack?)")
+
+/* This frame has the same ID as the previous one.  That means
+   that unwinding further would almost certainly give us another
+   frame with exactly the same ID, so break the chain.  Normally,
+   this is a sign of unwinder failure.  It could also indicate
+   stack corruption.  */
+SET (UNWIND_SAME_ID, "previous frame identical to this frame (corrupt stack?)")
+
+/* The frame unwinder didn't find any saved PC, but we needed
+   one to unwind further.  */
+SET (UNWIND_NO_SAVED_PC, "frame did not save the PC")
+
+#endif /* SET */
+
+
+#ifdef FIRST_ERROR
+FIRST_ERROR (UNWIND_UNAVAILABLE)
+#endif
+
+#ifdef FIRST_ENTRY
+FIRST_ENTRY (UNWIND_NO_REASON)
+#endif
+
+#ifdef LAST_ENTRY
+LAST_ENTRY (UNWIND_NO_SAVED_PC)
+#endif
-- 
1.7.6.4


  reply	other threads:[~2011-10-27  9:41 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-10-12 14:02 Kevin Pouget
2011-10-12 14:33 ` Phil Muldoon
2011-10-12 14:52 ` Pedro Alves
2011-10-12 15:18   ` Kevin Pouget
2011-10-12 15:28     ` Phil Muldoon
2011-10-12 15:59       ` Pedro Alves
2011-10-12 17:07         ` Tom Tromey
2011-10-13 11:25           ` Kevin Pouget
2011-10-13 11:27             ` Kevin Pouget
2011-10-13 15:19               ` Pedro Alves
2011-10-14  8:18                 ` Kevin Pouget
2011-10-14 14:22                   ` Tom Tromey
2011-10-14 14:41                     ` Kevin Pouget
2011-10-14 15:00                       ` Pedro Alves
2011-10-17 10:31                         ` Kevin Pouget
2011-10-19 21:22                           ` Tom Tromey
2011-10-24 16:53                             ` Kevin Pouget
2011-10-25  0:59                               ` Eli Zaretskii
2011-10-25  8:31                                 ` Kevin Pouget
2011-10-25 12:49                                   ` Eli Zaretskii
2011-10-25 14:27                                     ` Kevin Pouget
2011-10-27 10:02                                       ` Kevin Pouget [this message]
2011-10-27 10:16                                         ` Eli Zaretskii
2011-10-27 12:11                                           ` Kevin Pouget
2011-10-12 15:31     ` Pedro Alves
2011-10-12 17:06     ` Tom Tromey
2011-10-12 17:00   ` Tom Tromey

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAPftXU+z_bra3oZN7skA-hb7C_xJydNyrT7qrL8jHBetkt=Few@mail.gmail.com' \
    --to=kevin.pouget@gmail.com \
    --cc=eliz@gnu.org \
    --cc=gdb-patches@sourceware.org \
    --cc=pedro@codesourcery.com \
    --cc=pmuldoon@redhat.com \
    --cc=tromey@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox