Move unwind reasons to an external .def file

gdb/
	* 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.
	* stack.c (backtrace_command_1): Handle UNWIND_FIRST_ERROR as an alias
	instead of a distinct value.

doc/
	* gdb.texinfo ((Frames In Python): Document
	gdb.FRAME_UNWIND_FIRST_ERROR contant.
This commit is contained in:
Kevin Pouget
2011-10-27 11:04:27 +00:00
parent f77b9a5df0
commit 2231f1fb60
8 changed files with 133 additions and 70 deletions

View File

@ -1,3 +1,16 @@
2011-10-27 Kevin Pouget <kevin.pouget@st.com>
Move unwind reasons to an external .def file
* 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.
* stack.c (backtrace_command_1): Handle UNWIND_FIRST_ERROR as an alias
instead of a distinct value.
2011-10-27 Phil Muldoon <pmuldoon@redhat.com> 2011-10-27 Phil Muldoon <pmuldoon@redhat.com>
PR python/13331 PR python/13331

View File

@ -1,3 +1,8 @@
2011-10-27 Kevin Pouget <kevin.pouget@st.com>
* gdb.texinfo ((Frames In Python): Document
gdb.FRAME_UNWIND_FIRST_ERROR contant.
2011-10-26 Paul Koning <paul_koning@dell.com> 2011-10-26 Paul Koning <paul_koning@dell.com>
* gdb.texinfo (gdb.types): Document new deepitems function. * gdb.texinfo (gdb.types): Document new deepitems function.

View File

@ -23473,6 +23473,19 @@ stack corruption.
@item gdb.FRAME_UNWIND_NO_SAVED_PC @item gdb.FRAME_UNWIND_NO_SAVED_PC
The frame unwinder did not find any saved PC, but we needed The frame unwinder did not find any saved PC, but we needed
one to unwind further. 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 table
@end defun @end defun

View File

@ -2351,23 +2351,11 @@ frame_stop_reason_string (enum unwind_stop_reason reason)
{ {
switch (reason) switch (reason)
{ {
case UNWIND_NULL_ID: #define SET(name, description) \
return _("unwinder did not report frame ID"); 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: default:
internal_error (__FILE__, __LINE__, internal_error (__FILE__, __LINE__,
"Invalid frame stop reason"); "Invalid frame stop reason");

View File

@ -446,47 +446,16 @@ extern struct address_space *get_frame_address_space (struct frame_info *);
enum unwind_stop_reason enum unwind_stop_reason
{ {
/* No particular reason; either we haven't tried unwinding yet, #define SET(name, description) name,
or we didn't fail. */ #define FIRST_ENTRY(name) UNWIND_FIRST = name,
UNWIND_NO_REASON, #define LAST_ENTRY(name) UNWIND_LAST = name,
#define FIRST_ERROR(name) UNWIND_FIRST_ERROR = name,
/* The previous frame's analyzer returns an invalid result #include "unwind_stop_reasons.def"
from this_id. #undef SET
#undef FIRST_ENTRY
FIXME drow/2006-08-16: This is how GDB used to indicate end of #undef LAST_ENTRY
stack. We should migrate to a model where frames always have a #undef FIRST_ERROR
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,
}; };
/* Return the reason why we can't unwind past this frame. */ /* Return the reason why we can't unwind past this frame. */

View File

@ -553,7 +553,7 @@ gdbpy_frame_stop_reason_string (PyObject *self, PyObject *args)
if (!PyArg_ParseTuple (args, "i", &reason)) if (!PyArg_ParseTuple (args, "i", &reason))
return NULL; return NULL;
if (reason < 0 || reason > UNWIND_NO_SAVED_PC) if (reason < UNWIND_FIRST || reason > UNWIND_LAST)
{ {
PyErr_SetString (PyExc_ValueError, PyErr_SetString (PyExc_ValueError,
_("Invalid frame stop reason.")); _("Invalid frame stop reason."));
@ -610,18 +610,13 @@ gdbpy_initialize_frames (void)
PyModule_AddIntConstant (gdb_module, "SIGTRAMP_FRAME", SIGTRAMP_FRAME); PyModule_AddIntConstant (gdb_module, "SIGTRAMP_FRAME", SIGTRAMP_FRAME);
PyModule_AddIntConstant (gdb_module, "ARCH_FRAME", ARCH_FRAME); PyModule_AddIntConstant (gdb_module, "ARCH_FRAME", ARCH_FRAME);
PyModule_AddIntConstant (gdb_module, "SENTINEL_FRAME", SENTINEL_FRAME); PyModule_AddIntConstant (gdb_module, "SENTINEL_FRAME", SENTINEL_FRAME);
PyModule_AddIntConstant (gdb_module,
"FRAME_UNWIND_NO_REASON", UNWIND_NO_REASON); #define SET(name, description) \
PyModule_AddIntConstant (gdb_module, PyModule_AddIntConstant (gdb_module, "FRAME_"#name, name);
"FRAME_UNWIND_NULL_ID", UNWIND_NULL_ID); #define FIRST_ERROR(name) \
PyModule_AddIntConstant (gdb_module, PyModule_AddIntConstant (gdb_module, "FRAME_"#name, name);
"FRAME_UNWIND_FIRST_ERROR", UNWIND_FIRST_ERROR); #include "unwind_stop_reasons.def"
PyModule_AddIntConstant (gdb_module, #undef SET
"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);
Py_INCREF (&frame_object_type); Py_INCREF (&frame_object_type);
PyModule_AddObject (gdb_module, "Frame", (PyObject *) &frame_object_type); PyModule_AddObject (gdb_module, "Frame", (PyObject *) &frame_object_type);

View File

@ -1625,7 +1625,7 @@ backtrace_command_1 (char *count_exp, int show_locals, int from_tty)
enum unwind_stop_reason reason; enum unwind_stop_reason reason;
reason = get_frame_unwind_stop_reason (trailing); reason = get_frame_unwind_stop_reason (trailing);
if (reason > UNWIND_FIRST_ERROR) if (reason >= UNWIND_FIRST_ERROR)
printf_filtered (_("Backtrace stopped: %s\n"), printf_filtered (_("Backtrace stopped: %s\n"),
frame_stop_reason_string (reason)); frame_stop_reason_string (reason));
} }

View File

@ -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