public inbox for archer-commits@sourceware.org
help / color / mirror / Atom feed
* [SCM] archer-pmuldoon-python-backtrace: Add pretty-printing for frames.
@ 2012-02-20 17:51 pmuldoon
0 siblings, 0 replies; only message in thread
From: pmuldoon @ 2012-02-20 17:51 UTC (permalink / raw)
To: archer-commits
The branch, archer-pmuldoon-python-backtrace has been updated
via 568b2a8edda64ca9e007a92b5bd7037351977a9c (commit)
from 25db7ef99cba168d1c41d4206a2b4e98530ad5dd (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email.
- Log -----------------------------------------------------------------
commit 568b2a8edda64ca9e007a92b5bd7037351977a9c
Author: Phil Muldoon <pmuldoon@redhat.com>
Date: Mon Feb 20 17:51:18 2012 +0000
Add pretty-printing for frames.
-----------------------------------------------------------------------
Summary of changes:
gdb/Makefile.in | 6 +
gdb/python/py-framefilter.c | 427 ++++++++++++++++++++++++++++++++++++++++++
gdb/python/py-objfile.c | 61 ++++++
gdb/python/py-progspace.c | 62 ++++++
gdb/python/python-internal.h | 2 +
gdb/python/python.c | 1 +
gdb/python/python.h | 4 +
gdb/stack.c | 6 +
8 files changed, 569 insertions(+), 0 deletions(-)
create mode 100644 gdb/python/py-framefilter.c
First 500 lines of diff:
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 9f30a61..ef134a5 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -278,6 +278,7 @@ SUBDIR_PYTHON_OBS = \
py-exitedevent.o \
py-finishbreakpoint.o \
py-frame.o \
+ py-framefilter.o \
py-function.o \
py-inferior.o \
py-infthread.o \
@@ -310,6 +311,7 @@ SUBDIR_PYTHON_SRCS = \
python/py-exitedevent.c \
python/py-finishbreakpoint.c \
python/py-frame.c \
+ python/py-framefilter.c \
python/py-function.c \
python/py-inferior.c \
python/py-infthread.c \
@@ -2058,6 +2060,10 @@ py-frame.o: $(srcdir)/python/py-frame.c
$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-frame.c
$(POSTCOMPILE)
+py-framefilter.o: $(srcdir)/python/py-framefilter.c
+ $(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-framefilter.c
+ $(POSTCOMPILE)
+
py-function.o: $(srcdir)/python/py-function.c
$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-function.c
$(POSTCOMPILE)
diff --git a/gdb/python/py-framefilter.c b/gdb/python/py-framefilter.c
new file mode 100644
index 0000000..f8524f6
--- /dev/null
+++ b/gdb/python/py-framefilter.c
@@ -0,0 +1,427 @@
+/* Python frame filters
+
+ Copyright (C) 2012 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/>. */
+
+#include "defs.h"
+#include "exceptions.h"
+#include "objfiles.h"
+#include "symtab.h"
+#include "language.h"
+#include "exceptions.h"
+#include "arch-utils.h"
+#include "language.h"
+#include "python.h"
+#include "ui-out.h"
+#include "valprint.h"
+#include "annotate.h"
+
+#ifdef HAVE_PYTHON
+#include "python-internal.h"
+
+/* Helper function for find_frame_filter which iterates over a list,
+ calls each function and inspects output. This will return a filter
+ object if one of the filters registers interest in FRAME. If no
+ frame filter is found, it will return None. On error, it will set
+ the Python error and return NULL. */
+
+static PyObject *
+search_frame_filter_list (PyObject *list, PyObject *frame,
+ PyObject *level, PyObject *what,
+ PyObject *args)
+
+{
+ Py_ssize_t list_size, list_index;
+ PyObject *function;
+ PyObject *filter = NULL;
+
+ list_size = PyList_Size (list);
+ for (list_index = 0; list_index < list_size; list_index++)
+ {
+ function = PyList_GetItem (list, list_index);
+ if (! function)
+ return NULL;
+
+ /* Skip if disabled. */
+ if (PyObject_HasAttr (function, gdbpy_enabled_cst))
+ {
+ PyObject *attr = PyObject_GetAttr (function, gdbpy_enabled_cst);
+ int cmp;
+
+ if (!attr)
+ return NULL;
+ cmp = PyObject_IsTrue (attr);
+ if (cmp == -1)
+ return NULL;
+
+ if (!cmp)
+ continue;
+ }
+
+ filter = PyObject_CallFunctionObjArgs (function, frame, level,
+ what, args, NULL);
+ if (! filter)
+ return NULL;
+ else if (filter != Py_None)
+ return filter;
+
+ Py_DECREF (filter);
+ }
+
+ Py_RETURN_NONE;
+}
+
+
+/* Subroutine of find_frame_filter to simplify it. Look for a frame
+ filter for FRAME in the gdb module. The result is NULL if there's
+ an error and the search should be terminated. The result is
+ Py_None, if no frame filter is found. Otherwise the result is the
+ frame filter function, suitably inc-ref'd. */
+
+static PyObject *
+find_frame_filter_from_gdb (PyObject *frame, PyObject *level,
+ PyObject *what, PyObject *args)
+{
+ PyObject *filter_list;
+ PyObject *function;
+
+ /* Fetch the global frame filter list. */
+ if (! PyObject_HasAttrString (gdb_module, "frame_filters"))
+ Py_RETURN_NONE;
+ filter_list = PyObject_GetAttrString (gdb_module, "frame_filters");
+ if (filter_list == NULL || ! PyList_Check (filter_list))
+ {
+ Py_XDECREF (filter_list);
+ Py_RETURN_NONE;
+ }
+
+ function = search_frame_filter_list (filter_list, frame, level,
+ what, args);
+ Py_XDECREF (filter_list);
+ return function;
+}
+/* Subroutine of find_frame_filter to simplify it. Look for a frame
+ filter for FRAME in all objfiles. The result is NULL if there's an
+ error and the search should be terminated. The result is Py_None
+ if no frame filter found. Otherwise the result is the
+ pretty-printer function. */
+
+static PyObject *
+find_frame_filter_from_objfiles (PyObject *frame, PyObject *level,
+ PyObject *what, PyObject *args)
+{
+ PyObject *filter_list;
+ PyObject *function;
+ struct objfile *obj;
+
+ ALL_OBJFILES (obj)
+ {
+ PyObject *objf = objfile_to_objfile_object (obj);
+ if (!objf)
+ {
+ /* Ignore the error and continue. */
+ PyErr_Clear ();
+ continue;
+ }
+
+ filter_list = objfpy_get_frame_filters (objf, NULL);
+
+ function = search_frame_filter_list (filter_list, frame, level,
+ what, args);
+
+ Py_XDECREF (filter_list);
+
+ /* If there is an error in any objfile list, abort the search and exit. */
+ if (! function)
+ return NULL;
+
+ if (function != Py_None)
+ return function;
+
+ Py_DECREF (function);
+ }
+
+ Py_RETURN_NONE;
+}
+
+/* Subroutine of find_pretty_printer to simplify it. Look for a frame
+ filter for FRAME in the current program space. The result is NULL
+ if there's an error and the search should be terminated. The
+ result is Py_None, no frame filter was found. Otherwise the result
+ is the pretty-printer function. */
+
+static PyObject *
+find_frame_filter_from_progspace (PyObject *frame, PyObject *level,
+ PyObject *what, PyObject *args)
+{
+ PyObject *filter_list;
+ PyObject *function;
+ PyObject *obj = pspace_to_pspace_object (current_program_space);
+
+ if (!obj)
+ return NULL;
+ filter_list = pspy_get_frame_filters (obj, NULL);
+
+ function = search_frame_filter_list (filter_list, frame, level,
+ what, args);
+ Py_XDECREF (filter_list);
+ return function;
+}
+
+
+/* Find the frame filter constructor function for FRAME. If no
+ frame filter exists, return None. If one exists, return a new
+ reference. On error, set the Python error and return NULL. */
+
+static PyObject *
+find_frame_filter (PyObject *frame, int print_level,
+ enum print_what print_what, int print_args)
+
+{
+ PyObject *function = NULL;
+ PyObject *py_print_level = NULL;
+ PyObject *py_print_args = NULL;
+ PyObject *py_print_what = NULL;
+
+ /* Convert the parameters to Python objects. If any of them fail,
+ abort. */
+ py_print_level = PyBool_FromLong (print_level);
+ if (!py_print_level)
+ goto exit_func;
+
+ py_print_args = PyBool_FromLong (print_args);
+ if (!py_print_args)
+ goto exit_func;
+
+ py_print_what = PyLong_FromLong (print_what);
+ if (!py_print_what)
+ goto exit_func;
+
+ /* Look at the frame filter list for each objfile
+ in the current program-space. */
+ function = find_frame_filter_from_objfiles (frame,
+ py_print_level,
+ py_print_what,
+ py_print_args);
+
+ if (function == NULL || function != Py_None)
+ goto exit_func;
+ Py_DECREF (function);
+
+ /* Look at the frame filter list for the current program-space. */
+ function = find_frame_filter_from_progspace (frame,
+ py_print_level,
+ py_print_what,
+ py_print_args);
+
+ if (function == NULL || function != Py_None)
+ goto exit_func;
+ Py_DECREF (function);
+
+ /* Look at the frame filter list in the gdb module. */
+ function = find_frame_filter_from_gdb (frame,
+ py_print_level,
+ py_print_what,
+ py_print_args);
+ exit_func:
+
+ Py_XDECREF (py_print_level);
+ Py_XDECREF (py_print_what);
+ Py_XDECREF (py_print_args);
+
+ return function;
+}
+
+int
+print_frame (PyObject *filter, int print_level,
+ enum print_what print_what, int print_args,
+ struct ui_out *out,
+ struct value_print_options opts,
+ struct frame_info *frame)
+
+{
+ int level = 0;
+ CORE_ADDR address = 0;
+ struct gdbarch *gdbarch = get_frame_arch (frame);
+ char *func = NULL;
+ char *filename = NULL;
+ int line = 0;
+
+ if (print_level)
+ {
+ if (PyObject_HasAttrString (filter, "level"))
+ {
+ PyObject *result = PyObject_CallMethod (filter, "level", NULL);
+
+ if (result)
+ {
+ level = PyLong_AsLong (result);
+ Py_DECREF (result);
+ }
+ }
+ else
+ level = frame_relative_level (frame);
+ }
+
+ if (PyObject_HasAttrString (filter, "address"))
+ {
+ PyObject *result = PyObject_CallMethod (filter, "address", NULL);
+
+ if (result)
+ {
+ address = PyLong_AsLong (result);
+ Py_DECREF (result);
+ }
+ }
+ else
+ address = 0;
+
+ annotate_frame_begin (print_level ? level : 0,
+ gdbarch, address);
+
+ ui_out_text (out, "#");
+ ui_out_field_fmt_int (out, 2, ui_left, "level",
+ level);
+ if (opts.addressprint)
+ {
+ annotate_frame_address ();
+ ui_out_field_core_addr (out, "addr", gdbarch, address);
+ annotate_frame_address_end ();
+ }
+ ui_out_text (out, " in ");
+
+ if (PyObject_HasAttrString (filter, "function"))
+ {
+ PyObject *result = PyObject_CallMethod (filter, "function", NULL);
+
+ if (result)
+ {
+ char *dup = PyString_AsString (result);
+ if (dup)
+ func = xstrdup (dup);
+ else
+ return 0;
+ Py_DECREF (result);
+ }
+ }
+ else
+ func = xstrdup("<unknown>");
+
+ annotate_frame_function_name ();
+ ui_out_field_string (out, "func", func);
+
+ if (PyObject_HasAttrString (filter, "filename"))
+ {
+ PyObject *result = PyObject_CallMethod (filter, "filename", NULL);
+
+ if (result)
+ {
+ char *dup = PyString_AsString (result);
+ if (dup)
+ filename = xstrdup (dup);
+ else
+ return 0;
+ Py_DECREF (result);
+ }
+ }
+ else
+ func = xstrdup("<unknown function>");
+
+ annotate_frame_source_begin ();
+ ui_out_wrap_hint (out, " ");
+ ui_out_text (out, " at ");
+ annotate_frame_source_file ();
+ ui_out_field_string (out, "file", filename);
+ annotate_frame_source_file_end ();
+
+ if (PyObject_HasAttrString (filter, "line"))
+ {
+ PyObject *result = PyObject_CallMethod (filter, "line", NULL);
+
+ if (result)
+ {
+ line = PyLong_AsLong (result);
+ Py_DECREF (result);
+ }
+ }
+ else
+ line = 0;
+
+ ui_out_text (out, ":");
+ annotate_frame_source_line ();
+ ui_out_field_int (out, "line", line);
+ annotate_frame_source_end ();
+
+ ui_out_text (out, "\n");
+ annotate_frame_end ();
+
+ xfree (func);
+ xfree (filename);
+
+ return 1;
+}
+
+int
+apply_frame_filter (struct frame_info *frame, int print_level,
+ enum print_what print_what, int print_args,
+ struct ui_out *out)
+{
+ struct gdbarch *gdbarch = get_frame_arch (frame);
+ struct cleanup *cleanups;
+ PyObject *frame_obj, *filter;
+ int result = 0;
+ int print_result = 0;
+ struct value_print_options opts;
+
+ cleanups = ensure_python_env (gdbarch, current_language);
+
+ frame_obj = frame_info_to_frame_object (frame);
+ if (! frame_obj)
+ goto done;
+
+ /* Find the constructor. */
+ filter = find_frame_filter (frame_obj, print_level, print_what, print_args);
+ Py_DECREF (frame_obj);
+ make_cleanup_py_decref (filter);
+ if (! filter || filter == Py_None)
+ goto done;
+
+ get_user_print_options (&opts);
+ print_result = print_frame (filter, print_level, print_what,
+ print_args, out, opts, frame);
+
+ if (print_result)
+ result = 1;
+ else
+ gdbpy_print_stack ();
+
+ done:
+ do_cleanups (cleanups);
+ return result;
+}
+
+#else /* HAVE_PYTHON */
+
+int
+apply_frame_filter (struct frame_info *frame, int print_level,
+ enum print_what print_what, int print_args,
+ struct ui_out *out)
+{
+ return 0;
+}
+
+#endif /* HAVE_PYTHON */
diff --git a/gdb/python/py-objfile.c b/gdb/python/py-objfile.c
index 9fa6813..f06226c 100644
--- a/gdb/python/py-objfile.c
+++ b/gdb/python/py-objfile.c
@@ -32,6 +32,9 @@ typedef struct
/* The pretty-printer list of functions. */
PyObject *printers;
+
+ /* The frame filter list of functions. */
+ PyObject *frame_filters;
} objfile_object;
static PyTypeObject objfile_object_type;
@@ -58,6 +61,7 @@ objfpy_dealloc (PyObject *o)
objfile_object *self = (objfile_object *) o;
Py_XDECREF (self->printers);
+ Py_XDECREF (self->frame_filters);
self->ob_type->tp_free ((PyObject *) self);
}
@@ -76,6 +80,15 @@ objfpy_new (PyTypeObject *type, PyObject *args, PyObject *keywords)
Py_DECREF (self);
return NULL;
}
+
+ self->frame_filters = PyList_New (0);
+ if (!self->frame_filters)
+ {
+ Py_DECREF (self->printers);
+ Py_DECREF (self);
+ return NULL;
+ }
+
}
hooks/post-receive
--
Repository for Project Archer.
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2012-02-20 17:51 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-02-20 17:51 [SCM] archer-pmuldoon-python-backtrace: Add pretty-printing for frames pmuldoon
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).