From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 14708 invoked by alias); 26 Feb 2013 10:08:55 -0000 Mailing-List: contact archer-commits-help@sourceware.org; run by ezmlm Sender: Precedence: bulk List-Post: List-Help: List-Subscribe: Received: (qmail 14679 invoked by uid 9514); 26 Feb 2013 10:08:53 -0000 Date: Tue, 26 Feb 2013 10:08:00 -0000 Message-ID: <20130226100851.14659.qmail@sourceware.org> From: pmuldoon@sourceware.org To: archer-commits@sourceware.org Subject: [SCM] archer-pmuldoon-python-backtrace: Tom Tromey Review, part 2 X-Git-Refname: refs/heads/archer-pmuldoon-python-backtrace X-Git-Reftype: branch X-Git-Oldrev: a66b32b2338f9ae4675354eb00b0bbb61a1cf6a5 X-Git-Newrev: 28888b26f6b66c0953c27c442d26a509bbdddd01 X-SW-Source: 2013-q1/txt/msg00061.txt.bz2 List-Id: The branch, archer-pmuldoon-python-backtrace has been updated via 28888b26f6b66c0953c27c442d26a509bbdddd01 (commit) from a66b32b2338f9ae4675354eb00b0bbb61a1cf6a5 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email. - Log ----------------------------------------------------------------- commit 28888b26f6b66c0953c27c442d26a509bbdddd01 Author: Phil Muldoon Date: Tue Feb 26 10:08:20 2013 +0000 Tom Tromey Review, part 2 ----------------------------------------------------------------------- Summary of changes: gdb/data-directory/Makefile.in | 1 + gdb/mi/mi-cmd-stack.c | 34 +++-- gdb/python/lib/gdb/command/frame_filters.py | 84 ++-------- gdb/python/lib/gdb/frames.py | 110 +++++++++++ gdb/python/py-framefilter.c | 260 ++++++++++++++------------- gdb/python/py-objfile.c | 10 +- gdb/python/py-progspace.c | 10 +- gdb/python/py-utils.c | 9 +- gdb/python/python.h | 5 +- gdb/stack.c | 18 ++- 10 files changed, 303 insertions(+), 238 deletions(-) create mode 100644 gdb/python/lib/gdb/frames.py First 500 lines of diff: diff --git a/gdb/data-directory/Makefile.in b/gdb/data-directory/Makefile.in index 95e40a8..88634a6 100644 --- a/gdb/data-directory/Makefile.in +++ b/gdb/data-directory/Makefile.in @@ -53,6 +53,7 @@ PYTHON_DIR = python PYTHON_INSTALL_DIR = $(DESTDIR)$(GDB_DATADIR)/$(PYTHON_DIR) PYTHON_FILES = \ gdb/__init__.py \ + gdb/frames.py \ gdb/FrameIterator.py \ gdb/FrameWrapper.py \ gdb/types.py \ diff --git a/gdb/mi/mi-cmd-stack.c b/gdb/mi/mi-cmd-stack.c index 82d92d7..69c6111 100644 --- a/gdb/mi/mi-cmd-stack.c +++ b/gdb/mi/mi-cmd-stack.c @@ -133,14 +133,18 @@ mi_cmd_stack_list_frames (char *command, char **argv, int argc) if (! raw_arg && frame_filters) { - int count = frame_high; int flags = PRINT_LEVEL | PRINT_FRAME_INFO; + int py_frame_low = frame_low; - if (frame_high != -1) - count = (frame_high - frame_low) + 1; + /* We cannot pass -1 to frame_low, as that would signify a + relative backtrace from the tail of the stack. So, in the case + of frame_low == -1, assign and increment it. */ + if (py_frame_low == -1) + py_frame_low++; - result = apply_frame_filter (fi, flags, NO_VALUES, current_uiout, - count); + result = apply_frame_filter (get_current_frame (), flags, + NO_VALUES, current_uiout, + py_frame_low, frame_high); } /* Run the inbuilt backtrace if there are no filters registered, or @@ -236,7 +240,7 @@ mi_cmd_stack_list_locals (char *command, char **argv, int argc) int flags = PRINT_LEVEL | PRINT_LOCALS; result = apply_frame_filter (frame, flags, print_value, - current_uiout, 1); + current_uiout, 0,0); } if (! frame_filters || raw_arg || result == PY_BT_ERROR @@ -300,14 +304,18 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc) if (! raw_arg && frame_filters) { - int count = frame_high; int flags = PRINT_LEVEL | PRINT_ARGS; + int py_frame_low = frame_low; - if (frame_high != -1) - count = (frame_high - frame_low) + 1; + /* We cannot pass -1 to frame_low, as that would signify a + relative backtrace from the tail of the stack. So, in the case + of frame_low == -1, assign and increment it. */ + if (py_frame_low == -1) + py_frame_low++; - result = apply_frame_filter (fi, flags, print_values, - current_uiout, count); + result = apply_frame_filter (get_current_frame (), flags, + print_values, current_uiout, + py_frame_low, frame_high); } if (! frame_filters || raw_arg || result == PY_BT_ERROR @@ -350,7 +358,7 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc) if (argc < 1 || argc > 2 || (argc == 2 && ! raw_arg) || (argc == 1 && raw_arg)) - error (_("-stack-list-arguments: Usage: " \ + error (_("-stack-list-variables: Usage: " \ "[--no-frame-filters] PRINT_VALUES")); frame = get_selected_frame (NULL); @@ -361,7 +369,7 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc) int flags = PRINT_LEVEL | PRINT_ARGS | PRINT_LOCALS; result = apply_frame_filter (frame, flags, print_value, - current_uiout, 1); + current_uiout, 0, 0); } if (! frame_filters || raw_arg || result == PY_BT_ERROR diff --git a/gdb/python/lib/gdb/command/frame_filters.py b/gdb/python/lib/gdb/command/frame_filters.py index 04ee762..4e464e9 100644 --- a/gdb/python/lib/gdb/command/frame_filters.py +++ b/gdb/python/lib/gdb/command/frame_filters.py @@ -163,64 +163,6 @@ def _return_list(name): msg = "Cannot find frame-filter dictionary for '" + name + "'" raise gdb.GdbError(msg) -def _sort_list(): - """ Internal Worker function to merge all known frame-filter - lists, prune any filters with the state set to "disabled", and - sort the list on the frame-filter's "priority" attribute. - - Returns: - sorted_list: A sorted, pruned list of frame filters to - execute. - """ - - all_filters = [] - for objfile in gdb.objfiles(): - all_filters = all_filters + objfile.frame_filters.values() - cp = gdb.current_progspace() - - all_filters = all_filters + cp.frame_filters.values() - all_filters = all_filters + gdb.frame_filters.values() - - sorted_frame_filters = sorted(all_filters, key = _get_priority, - reverse = True) - - sorted_frame_filters = filter(_get_enabled, - sorted_frame_filters) - - return sorted_frame_filters - -def invoke(frame): - """ Public internal function that will execute the chain of frame - filters. Each filter is executed in priority order. - - Arguments: - frame: The initial frame. - - Returns: - frame_iterator: The iterator after all frame filters have - had a change to execute, or None if no frame - filters are registered. - """ - - # Get a sorted list of frame filters. - sorted_list = _sort_list() - - # Check to see if there are any frame-filters. If not, just - # return None and let default backtrace printing occur. - if len(sorted_list) == 0: - return None - - frame_iterator = FrameIterator(frame) - - # Apply base filter to all gdb.Frames. This unifies the - # interface. - frame_iterator = itertools.imap(FrameWrapper, frame_iterator) - - for ff in sorted_list: - frame_iterator = ff.filter(frame_iterator) - - return frame_iterator - # GDB Commands. class SetFilterPrefixCmd(gdb.Command): """Prefix command for 'set' frame-filter related operations.""" @@ -300,7 +242,7 @@ class InfoFrameFilter(gdb.Command): # Internal enable/disable functions. -def do_enable_frame_filter(command_tuple, flag): +def _do_enable_frame_filter(command_tuple, flag): """Worker for enabling/disabling frame_filters. Arguments: @@ -323,7 +265,7 @@ def do_enable_frame_filter(command_tuple, flag): _set_enabled(ff, flag) -def complete_frame_filter_list (text,word): +def _complete_frame_filter_list (text,word): filter_locations = ["global","progspace"] for objfile in gdb.objfiles(): @@ -345,7 +287,7 @@ def complete_frame_filter_list (text,word): # dictioanries that the previous filter operation returned. return flist -def complete_frame_filter_name (word, printer_list): +def _complete_frame_filter_name (word, printer_list): printer_keys = printer_list.keys() if (word == ""): @@ -372,15 +314,15 @@ class EnableFrameFilter(gdb.Command): gdb.COMMAND_DATA) def complete (self,text,word): if text.count(" ") == 0: - return complete_frame_filter_list(text,word) + return _complete_frame_filter_list(text,word) else: printer_list = _return_list (text.split()[0].rstrip()) - return complete_frame_filter_name(word, printer_list) + return _complete_frame_filter_name(word, printer_list) def invoke(self, arg, from_tty): """GDB calls this to perform the command.""" command_tuple = _parse_arg("enable frame-filter", arg) - do_enable_frame_filter(command_tuple, True) + _do_enable_frame_filter(command_tuple, True) class DisableFrameFilter(gdb.Command): @@ -402,15 +344,15 @@ class DisableFrameFilter(gdb.Command): def complete (self,text,word): if text.count(" ") == 0: - return complete_frame_filter_list(text,word) + return _complete_frame_filter_list(text,word) else: printer_list = _return_list (text.split()[0].rstrip()) - return complete_frame_filter_name(word, printer_list) + return _complete_frame_filter_name(word, printer_list) def invoke(self, arg, from_tty): """GDB calls this to perform the command.""" command_tuple = _parse_arg("disable frame-filter", arg) - do_enable_frame_filter(command_tuple, False) + _do_enable_frame_filter(command_tuple, False) class SetFrameFilterPriority(gdb.Command): """GDB command to set the priority of the specified frame-filter. @@ -482,10 +424,10 @@ class SetFrameFilterPriority(gdb.Command): def complete (self,text,word): if text.count(" ") == 0: - return complete_frame_filter_list(text,word) + return _complete_frame_filter_list(text,word) else: printer_list = _return_list (text.split()[0].rstrip()) - return complete_frame_filter_name(word, printer_list) + return _complete_frame_filter_name(word, printer_list) def invoke(self, arg, from_tty): """GDB calls this to perform the command.""" @@ -564,10 +506,10 @@ class ShowFrameFilterPriority(gdb.Command): def complete (self,text,word): if text.count(" ") == 0: - return complete_frame_filter_list(text,word) + return _complete_frame_filter_list(text,word) else: printer_list = _return_list (text.split()[0].rstrip()) - return complete_frame_filter_name(word, printer_list) + return _complete_frame_filter_name(word, printer_list) def invoke(self, arg, from_tty): """GDB calls this to perform the command.""" diff --git a/gdb/python/lib/gdb/frames.py b/gdb/python/lib/gdb/frames.py new file mode 100644 index 0000000..f637a7a --- /dev/null +++ b/gdb/python/lib/gdb/frames.py @@ -0,0 +1,110 @@ +# Frame-filter commands. +# Copyright (C) 2012, 2013 Free Software Foundation, Inc. + +# 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 . + +"""Internal functions for working with frame-filters.""" + +import gdb +from gdb.FrameIterator import FrameIterator +from gdb.FrameWrapper import FrameWrapper +import itertools +import gdb.command.frame_filters as ffc +import collections + +def _sort_list(): + """ Internal Worker function to merge all known frame-filter + lists, prune any filters with the state set to "disabled", and + sort the list on the frame-filter's "priority" attribute. + + Returns: + sorted_list: A sorted, pruned list of frame filters to + execute. + """ + + all_filters = [] + for objfile in gdb.objfiles(): + all_filters = all_filters + objfile.frame_filters.values() + cp = gdb.current_progspace() + + all_filters = all_filters + cp.frame_filters.values() + all_filters = all_filters + gdb.frame_filters.values() + + sorted_frame_filters = sorted(all_filters, key = ffc._get_priority, + reverse = True) + + sorted_frame_filters = filter(ffc._get_enabled, + sorted_frame_filters) + + return sorted_frame_filters + +def execute_frame_filters(frame, frame_low, frame_high): + """ Public internal function that will execute the chain of frame + filters. Each filter is executed in priority order. + + Arguments: + frame: The initial frame. + + Returns: + frame_iterator: The iterator after all frame filters have + had a change to execute, or None if no frame + filters are registered. + """ + + # Get a sorted list of frame filters. + sorted_list = _sort_list() + + # Check to see if there are any frame-filters. If not, just + # return None and let default backtrace printing occur. + if len(sorted_list) == 0: + return None + + frame_iterator = FrameIterator(frame) + + # Apply base filter to all gdb.Frames. This unifies the + # interface. + frame_iterator = itertools.imap(FrameWrapper, frame_iterator) + + for ff in sorted_list: + frame_iterator = ff.filter(frame_iterator) + + # Slicing + + # Is this a relative offset, ie bt -2? + if frame_low < 0: + count = 0 + slice_length = abs(frame_low) + sliced = collections.deque() + + for frame_item in frame_iterator: + if count >= slice_length: + sliced.popleft(); + count = count + 1 + sliced.append(frame_item) + + return iter(sliced) + + # -1 for frame_high means until the end of the stack frame, and + # None means to the end of the iterator to islice. + if frame_high == -1: + frame_high = None + else: + # The end argument for islice is a count, not a position, so + # add one as frames start as zero. + frame_high = frame_high + 1; + + + sliced = itertools.islice(frame_iterator, frame_low, frame_high) + + return sliced diff --git a/gdb/python/py-framefilter.c b/gdb/python/py-framefilter.c index 0e81278..0a118c5 100644 --- a/gdb/python/py-framefilter.c +++ b/gdb/python/py-framefilter.c @@ -61,7 +61,7 @@ extract_sym (PyObject *obj, char **name, struct symbol **sym, PyObject *result = PyObject_CallMethod (obj, "symbol", NULL); if (! result) - return 0; + return PY_BT_ERROR; /* For 'symbol' callback, the function can return a symbol or a string. */ @@ -71,7 +71,7 @@ extract_sym (PyObject *obj, char **name, struct symbol **sym, Py_DECREF (result); if (! *name) - return 0; + return PY_BT_ERROR; *language = python_language; *sym = NULL; } @@ -88,7 +88,7 @@ extract_sym (PyObject *obj, char **name, struct symbol **sym, PyErr_SetString (PyExc_RuntimeError, _("Unexpected value. Expecting a " "gdb.Symbol or a Python string.")); - return 0; + return PY_BT_ERROR; } /* Duplicate the symbol name, so the caller has consistency @@ -121,7 +121,7 @@ extract_value (PyObject *obj, struct value **value) PyObject *vresult = PyObject_CallMethod (obj, "value", NULL); if (! vresult) - return 0; + return PY_BT_ERROR; /* The Python code has returned 'None' for a value, so we set value to NULL. This flags that GDB should read the @@ -138,7 +138,7 @@ extract_value (PyObject *obj, struct value **value) Py_DECREF (vresult); if (*value == NULL) - return 0; + return PY_BT_ERROR; return 1; } @@ -212,7 +212,7 @@ py_print_type (struct ui_out *out, struct value *val) if (except.reason > 0) { gdbpy_convert_exception (except); - return 0; + return PY_BT_ERROR; } return 1; @@ -221,10 +221,9 @@ py_print_type (struct ui_out *out, struct value *val) /* Helper function which outputs a value's name to an output field in a stream. OUT is the ui-out structure the value will be output to, VAL is the value that will be printed, OPTS contains the value - printing options, MI_PRINT_TYPE is the value delimiter for MI - output and LANGUAGE is the language_defn that the value will be - printed with. If the output is detected to be non-MI, - MI_PRINT_TYPE is ignored. Returns 0 on error, with any GDB + printing options, ARGS_TYPE is an enumerater describing the + argument format, and LANGUAGE is the language_defn that the value + will be printed with. Returns PY_BT_ERROR on error, with any GDB exceptions converted to a Python exception. */ static int @@ -273,7 +272,7 @@ py_print_value (struct ui_out *out, struct value *val, if (except.reason > 0) { gdbpy_convert_exception(except); - return 0; + return PY_BT_ERROR; } } @@ -338,7 +337,7 @@ py_print_single_arg (struct ui_out *out, { struct value *val; volatile struct gdb_exception except; - struct cleanup *inner_cleanup = + struct cleanup *cleanups = make_cleanup (null_cleanup, NULL); if (fa) @@ -351,9 +350,12 @@ py_print_single_arg (struct ui_out *out, /* MI has varying rules for tuples, but generally if there is only one element in each item in the list, do not start a tuple. */ - if (print_args_field || args_type != MI_PRINT_NO_VALUES) - make_cleanup_ui_out_tuple_begin_end (out, NULL); - + if (ui_out_is_mi_like_p (out)) + { + if (print_args_field || args_type != MI_PRINT_NO_VALUES) + make_cleanup_ui_out_tuple_begin_end (out, NULL); + } + TRY_CATCH (except, RETURN_MASK_ALL) { annotate_arg_begin (); @@ -446,13 +448,13 @@ py_print_single_arg (struct ui_out *out, } } - do_cleanups (inner_cleanup); + do_cleanups (cleanups); return 1; error: - do_cleanups (inner_cleanup); - return 0; + do_cleanups (cleanups); + return PY_BT_ERROR; } /* Helper function to loop over frame arguments provided by the @@ -462,8 +464,7 @@ py_print_single_arg (struct ui_out *out, enumerater describing the argument format, PRINT_ARGS_FIELD is a flag which indicates if we output "ARGS=1" in MI output in commands where both arguments and locals are printed, and FRAME is the - backing frame. If (all) the frame argument values are provided via - the "value" API call, FRAME is not needed. */ + backing frame. */ static int enumerate_args (PyObject *iter, hooks/post-receive -- Repository for Project Archer.