From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 2794 invoked by alias); 10 Apr 2012 14:58:20 -0000 Mailing-List: contact archer-commits-help@sourceware.org; run by ezmlm Sender: Precedence: bulk List-Post: List-Help: List-Subscribe: Received: (qmail 2757 invoked by uid 9514); 10 Apr 2012 14:58:18 -0000 Date: Tue, 10 Apr 2012 14:58:00 -0000 Message-ID: <20120410145818.2742.qmail@sourceware.org> From: pmuldoon@sourceware.org To: archer-commits@sourceware.org Subject: [SCM] archer-pmuldoon-python-backtrace: Simplify frame iterator handling. Add regex and reverse parameters to Frame iterators. X-Git-Refname: refs/heads/archer-pmuldoon-python-backtrace X-Git-Reftype: branch X-Git-Oldrev: 7c3454ab0110e70d0039241c17c819afb6b45f64 X-Git-Newrev: fa69ff9b7cb25b29bc11bea4a500e7eb3d8a0e97 X-SW-Source: 2012-q2/txt/msg00016.txt.bz2 List-Id: The branch, archer-pmuldoon-python-backtrace has been updated via fa69ff9b7cb25b29bc11bea4a500e7eb3d8a0e97 (commit) via 5517225daa7e73f06515788371e8eb3182e07020 (commit) from 7c3454ab0110e70d0039241c17c819afb6b45f64 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email. - Log ----------------------------------------------------------------- commit fa69ff9b7cb25b29bc11bea4a500e7eb3d8a0e97 Author: Phil Muldoon Date: Tue Apr 10 15:57:29 2012 +0100 Simplify frame iterator handling. Add regex and reverse parameters to Frame iterators. commit 5517225daa7e73f06515788371e8eb3182e07020 Author: Phil Muldoon Date: Thu Apr 5 19:44:57 2012 +0100 Remove old Python code ----------------------------------------------------------------------- Summary of changes: gdb/data-directory/Makefile.in | 4 +- gdb/python/lib/gdb/command/backtrace.py | 151 ------------------- gdb/python/lib/gdb/frame.py | 238 ------------------------------- gdb/python/py-frame.c | 124 ++++++++++++---- 4 files changed, 95 insertions(+), 422 deletions(-) delete mode 100644 gdb/python/lib/gdb/command/backtrace.py delete mode 100644 gdb/python/lib/gdb/frame.py First 500 lines of diff: diff --git a/gdb/data-directory/Makefile.in b/gdb/data-directory/Makefile.in index 77338e1..dc6ca2a 100644 --- a/gdb/data-directory/Makefile.in +++ b/gdb/data-directory/Makefile.in @@ -60,9 +60,7 @@ PYTHON_FILES = \ gdb/command/__init__.py \ gdb/command/pretty_printers.py \ gdb/command/prompt.py \ - gdb/command/backtrace.py \ - gdb/command/upto.py \ - gdb/frame.py + gdb/command/upto.py FLAGS_TO_PASS = \ "prefix=$(prefix)" \ diff --git a/gdb/python/lib/gdb/command/backtrace.py b/gdb/python/lib/gdb/command/backtrace.py deleted file mode 100644 index f739d1c..0000000 --- a/gdb/python/lib/gdb/command/backtrace.py +++ /dev/null @@ -1,151 +0,0 @@ -# New backtrace command. - -# Copyright (C) 2008, 2009, 2010, 2011 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 . - -import gdb -import gdb.frame -import itertools -import sys - -class ReverseBacktraceParameter(gdb.Parameter): - """The new-backtrace command can show backtraces in 'reverse' order. -This means that the innermost frame will be printed last. -Note that reverse backtraces are more expensive to compute.""" - - set_doc = "Enable or disable reverse backtraces." - show_doc = "Show whether backtraces will be printed in reverse order." - - def __init__(self): - super(ReverseBacktraceParameter, self).__init__("reverse-backtrace", - gdb.COMMAND_STACK, - gdb.PARAM_BOOLEAN) - - # Default to compatibility with gdb. - self.value = False - -class FilteringBacktrace(gdb.Command): - """Print backtrace of all stack frames, or innermost COUNT frames. - -Usage: new-backtrace [COUNT|QUALIFIER]... - -With a negative argument, print outermost -COUNT frames. - -Valid qualifiers are: - - full Also print the values of the local variables. - raw Avoid any filtering by loadable modules. - reverse Reverse the stack trace. If a reverse trace was - already selected by `set reverse-backtrace', then an - ordinary stack trace is done. Note that reverse - backtraces are more expensive to compute. - all Show frames that have been filtered out. - -""" - - def __init__(self): - # FIXME: this is not working quite well enough to replace - # "backtrace" yet. - super(FilteringBacktrace, self).__init__("new-backtrace", - gdb.COMMAND_STACK) - - self.reverse = ReverseBacktraceParameter() - - def reverse_iter(self, iter): - result = list(iter) - result.reverse() - return result - - def final_n(self, iter, x): - result = list(iter) - return result[x:] - - def invoke(self, arg, from_tty): - i = 0 - count = 0 - filter = True - full = False - reverse = self.reverse.value - showall = False - - for word in arg.split(" "): - if word == '': - continue - elif word == 'raw': - filter = False - elif word == 'full': - full = True - elif word == 'reverse': - reverse = not reverse - elif word == 'all': - showall = True - else: - count = int(word) - - # FIXME: try/catch and wrap in gdb error - newest_frame = gdb.newest_frame() - iter = itertools.imap(gdb.frame.FrameWrapper, - gdb.frame.FrameIterator(newest_frame)) - - if filter: - iter = gdb.frame.create_frame_filter(iter) - - # Now wrap in an iterator that numbers the frames. - iter = itertools.izip(itertools.count(0), iter) - - # Reverse if the user wanted that. - if reverse: - iter = self.reverse_iter(iter) - - # Extract sub-range user wants. - if count < 0: - iter = self.final_n(iter, count) - elif count > 0: - iter = itertools.islice(iter, 0, count) - - for pair in iter: - sys.stdout.write("#%-2d" % pair[0]) - gdb.frame.print_frame(pair[1], sys.stdout, full) - if showall: - for f in pair[1].children(): - gdb.frame.print_frame(f, sys.stdout, full, ' ') - - -FilteringBacktrace() - - -def lame(): - class _Holder(gdb.Command): - def __init__(self, what): - super(_Holder, self).__init__(what + " backtrace filter", - gdb.COMMAND_STACK, - prefix = True) - - def invoke(self, arg, from_tty): - # FIXME - pass - - _Holder("set") - _Holder("show") - - class ShowFilter(gdb.Command): - def __init__(self): - super(ShowFilter, self).__init__("show backtrace filters", - gdb.COMMAND_STACK) - - def invoke(self, arg, from_tty): - gdb.frame.print_filters() - - ShowFilter() diff --git a/gdb/python/lib/gdb/frame.py b/gdb/python/lib/gdb/frame.py deleted file mode 100644 index 4743cd9..0000000 --- a/gdb/python/lib/gdb/frame.py +++ /dev/null @@ -1,238 +0,0 @@ -# Frame-related utilities. - -# Copyright (C) 2008, 2009, 2010, 2011 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 . - -import gdb -import cStringIO - -class FrameIterator(object): - """An iterator that iterates over frames.""" - - def __init__ (self, frame): - "Initialize a FrameIterator. FRAME is the starting frame." - super(FrameIterator, self).__init__() - self.frame = frame - - def __iter__ (self): - return self - - def next (self): - result = self.frame - if result is None: - raise StopIteration - self.frame = result.older () - return result - -class _SymWrapper(object): - def __init__(self, frame, block, sym): - super(_SymWrapper, self).__init__() - self.frame = frame - self.block = block - if len(sym.linkage_name): - nsym, is_field_of_this = gdb.lookup_symbol (sym.linkage_name, block) - if nsym.addr_class != gdb.SYMBOL_LOC_REGISTER: - sym = nsym - self.sym = sym - - def name(self): - return self.sym.print_name - - def value(self): - try: - return self.frame.read_var(self.sym) - except RuntimeError, text: - return text - -class _BlockIterator(object): - def __init__(self, frame, block, just_args): - super(_BlockIterator, self).__init__() - self.frame = frame - self.block = block - self.just_args = just_args - self.iter = iter(self.block) - - def __iter__(self): - return self - - def next(self): - while True: - try: - result = self.iter.next() - if result.is_argument == self.just_args: - return _SymWrapper(self.frame, self.block, result) - except StopIteration: - if self.block.function is not None: - raise StopIteration - self.block = self.block.superblock - self.iter = iter(self.block) - -class FrameWrapper(object): - """A wrapper for a gdb.Frame object that presents a simpler interface. -A FrameWrapper forwards most methods to the underlying Frame. -It omits a few methods, and adds some others. -Any object conforming to this interface may be returned by a frame filter.""" - - def __init__(self, frame): - super(FrameWrapper, self).__init__() - self.frame = frame - - def name(self): - name = self.frame.name() - if name is None: - name = '??' - return name - - def type(self): - return self.frame.type() - - def older(self): - return self.frame.older() - - def arguments(self): - try: - block = self.frame.block() - return _BlockIterator(self.frame, block, True) - except RuntimeError: - # It is ok if block() fails. - return [] - - def locals(self): - try: - block = self.frame.block() - return _BlockIterator(self.frame, block, False) - except RuntimeError: - # It is ok if block() fails. - return [] - - def children(self): - if hasattr(self.frame, 'children'): - return self.frame.children() - return [] - - def file_and_line(self): - sal = self.frame.find_sal() - if sal.symtab and sal.symtab.filename: - return (sal.symtab.filename, sal.line) - return (None, None) - - def library(self): - pc = self.frame.pc() - return gdb.solib_name(pc) - -def _print_symbol(stream, sym, sep): - stream.write(sym.name()) - stream.write(sep) - val = sym.value() - if val is None: - stream.write('???') - else: - stream.write(str(val)) - -def _print_args(frame, stream): - stream.write(' (') - first = True - for arg in frame.arguments(): - if not first: - stream.write(', ') - first = False - _print_symbol(stream, arg, '=') - stream.write(')') - -def _print_locals(frame, stream): - for var in frame.locals(): - _print_symbol(stream, var, ' = ') - stream.write('\n') - -def print_frame(frame, stream, full = False, spaces = ''): - stream.write(spaces) - if frame.type() == gdb.DUMMY_FRAME: - stream.write(" \n") - elif frame.type() == gdb.SIGTRAMP_FRAME: - stream.write(" \n") - elif frame.type() == gdb.ARCH_FRAME: - stream.write(" \n") - else: - stream.write(' ') - stream.write(frame.name()) - _print_args(frame, stream) - (filename, line) = frame.file_and_line() - if filename is not None: - stream.write('\n') - stream.write(spaces) - stream.write(' at ') - stream.write(filename) - stream.write(':') - stream.write(str(line)) - else: - lib = frame.library() - if lib is not None: - stream.write(' from ') - stream.write(lib) - stream.write('\n') - if full: - nstr = cStringIO.StringIO() - _print_locals(frame, nstr) - for line in nstr.getvalue().splitlines(): - stream.write(spaces) - stream.write(' ') - stream.write(line) - stream.write('\n') - nstr.close() - -_frame_filters = {} - -class FrameFilter(gdb.Parameter): - def __init__(self, name): - super(FrameFilter, self).__init__('backtrace filter ' + name, - gdb.COMMAND_STACK, - gdb.PARAM_ZINTEGER) - self.name = name - self.value = 1 - global _frame_filters - _frame_filters[name] = self - - def filter(iter): - return iter - -def _get_value(elt): - return elt.value - -def _value_gt_0(elt): - return elt.value > 0 - -def create_frame_filter(iter): - global _frame_filters - elts = filter(_value_gt_0, _frame_filters.values()) - # FIXME to make it stable, should also sort by name as secondary key - elts.sort(key = _get_value, reverse = True) - for filt in elts: - iter = elts.filter(iter) - return iter - -def print_filters(): - global _frame_filters - elts = _frame_filters.values() - elts.sort(key = _get_value, reverse = True) - if not len(elts): - print 'No frame filters.' - else: - # It would be nice to print a short doc string here. - print 'Priority\tName' - for f in elts: - if f.value > 0: - print '%-8d\t%s' % (f.value, f.name) - else: - print 'Disabled\t%s' % f.name diff --git a/gdb/python/py-frame.c b/gdb/python/py-frame.c index c5ab2fd..3374531 100644 --- a/gdb/python/py-frame.c +++ b/gdb/python/py-frame.c @@ -29,6 +29,7 @@ #include "symfile.h" #include "objfiles.h" #include "dictionary.h" +#include "gdb_regex.h" typedef struct frapy_type_object { PyObject_HEAD @@ -49,8 +50,16 @@ typedef struct frapy_type_object { /* A frame iterator object. */ typedef struct { PyObject_HEAD - struct frapy_type_object *source; - struct frapy_type_object *current; + /* The current frame in the iterator. */ + struct frame_info *current; + int regex; + /* Regex pattern, or null. */ + regex_t pattern; + /* Whether the iteration has started. */ + int started; + /* reversed, if true will get the next frame, if false will get the + previous frame. */ + int reversed; } frame_iterator_object; /* Require a valid frame. This must be called inside a TRY_CATCH, or @@ -766,41 +775,75 @@ frapy_iter (PyObject *self) return NULL; Py_INCREF (self); - frame_iter_obj->source = (frame_object *) self; - frame_iter_obj->current = NULL; + frame_iter_obj->current = frame_object_to_frame_info (self); + if (! frame_iter_obj->current) + return NULL; + frame_iter_obj->regex = 0; + frame_iter_obj->started = 0; + frame_iter_obj->reversed = 0; return (PyObject *) frame_iter_obj; } +static struct frame_info * +frame_navigate (struct frame_info *fi, int reversed) +{ + if (reversed) + return get_next_frame (fi); + + return get_prev_frame (fi); +} + +static struct frame_info * +get_next_iter_frame_h (frame_iterator_object *frame_iter) +{ + struct frame_info *fi; + + if (! frame_iter->current) + return NULL; + + if (frame_iter->started) + fi = frame_navigate (frame_iter->current, frame_iter->reversed); + else + { + fi = frame_iter->current; + frame_iter->started = 1; + } + + if (frame_iter->regex) + { + while (fi) + { + enum language lang; + volatile struct gdb_exception except; + const char *name; + + find_frame_funname (fi, &name, &lang, + NULL); + if (name && regexec (&frame_iter->pattern, name, 0, NULL, 0) == 0) + break; hooks/post-receive -- Repository for Project Archer.