From 2231f1fb609de30056ec5d3f526b39ee146efcab Mon Sep 17 00:00:00 2001 From: Kevin Pouget Date: Thu, 27 Oct 2011 11:04:27 +0000 Subject: [PATCH] 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. --- gdb/ChangeLog | 13 ++++++ gdb/doc/ChangeLog | 5 +++ 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 +++++++++++++++++++++++++++++++++++++ 8 files changed, 134 insertions(+), 71 deletions(-) create mode 100644 gdb/unwind_stop_reasons.def diff --git a/gdb/ChangeLog b/gdb/ChangeLog index f05a246745b..9d469bd1072 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,16 @@ +2011-10-27 Kevin Pouget + + 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 PR python/13331 diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 403675eaea0..2001e0c5c06 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,8 @@ +2011-10-27 Kevin Pouget + + * gdb.texinfo ((Frames In Python): Document + gdb.FRAME_UNWIND_FIRST_ERROR contant. + 2011-10-26 Paul Koning * gdb.texinfo (gdb.types): Document new deepitems function. diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index b451a6afedb..3e78832f96c 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -23473,6 +23473,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 582402099b6..e5e442a7d12 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 a261a911157..55972def85c 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 e192ffab609..20064cab49d 100644 --- a/gdb/python/py-frame.c +++ b/gdb/python/py-frame.c @@ -553,7 +553,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.")); @@ -610,18 +610,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 953d3bd4a34..003725a7252 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 00000000000..9a34feb77c3 --- /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 . */ + +/* 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 -- 2.30.2