public inbox for archer-commits@sourceware.org
help / color / mirror / Atom feed
* [SCM]  archer-pmuldoon-python-backtrace: Add Tom Tromey's remodelled backtrace reference implementation as extracted from archer-tromey-python and patches to the list.
@ 2011-02-21 13:57 pmuldoon
  0 siblings, 0 replies; only message in thread
From: pmuldoon @ 2011-02-21 13:57 UTC (permalink / raw)
  To: archer-commits

The branch, archer-pmuldoon-python-backtrace has been updated
       via  130e8c86b268f68bf0b73615c9d0446a87377c62 (commit)
      from  09363f5ea451879d3bc391b32385a58c58021ebb (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email.

- Log -----------------------------------------------------------------
commit 130e8c86b268f68bf0b73615c9d0446a87377c62
Author: Phil Muldoon <pmuldoon@redhat.com>
Date:   Mon Feb 21 13:56:23 2011 +0000

    Add Tom Tromey's remodelled backtrace reference implementation as
    extracted from archer-tromey-python and patches to the list.

-----------------------------------------------------------------------

Summary of changes:
 gdb/python/lib/gdb/command/backtrace.py |  151 +++++++++++++++++++
 gdb/python/lib/gdb/command/upto.py      |  128 +++++++++++++++++
 gdb/python/lib/gdb/frame.py             |  238 +++++++++++++++++++++++++++++++
 3 files changed, 517 insertions(+), 0 deletions(-)
 create mode 100644 gdb/python/lib/gdb/command/backtrace.py
 create mode 100644 gdb/python/lib/gdb/command/upto.py
 create mode 100644 gdb/python/lib/gdb/frame.py

First 500 lines of diff:
diff --git a/gdb/python/lib/gdb/command/backtrace.py b/gdb/python/lib/gdb/command/backtrace.py
new file mode 100644
index 0000000..f739d1c
--- /dev/null
+++ b/gdb/python/lib/gdb/command/backtrace.py
@@ -0,0 +1,151 @@
+# 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 <http://www.gnu.org/licenses/>.
+
+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/command/upto.py b/gdb/python/lib/gdb/command/upto.py
new file mode 100644
index 0000000..5126531
--- /dev/null
+++ b/gdb/python/lib/gdb/command/upto.py
@@ -0,0 +1,128 @@
+# upto command.
+
+# Copyright (C) 2009, 2010 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 <http://www.gnu.org/licenses/>.
+
+import gdb
+import gdb.frame
+import re
+
+class UptoPrefix (gdb.Command):
+    def __init__ (self):
+        super (UptoPrefix, self).__init__ ("upto", gdb.COMMAND_STACK,
+                                           prefix = True)
+
+class UptoImplementation (gdb.Command):
+    def __init__ (self, subcommand):
+        super (UptoImplementation, self).__init__ ("upto " + subcommand,
+                                                   gdb.COMMAND_STACK)
+
+    def search (self):
+        saved = gdb.selected_frame ()
+        iter = gdb.frame.FrameIterator (saved)
+        found = False
+        try:
+            for frame in iter:
+                frame.select ()
+                try:
+                    if self.filter (frame):
+                        wrapper = gdb.frame.FrameWrapper (frame)
+                        gdb.frame.print_frame(wrapper, sys.stdout)
+                        return
+                except:
+                    pass
+        except:
+            pass
+        saved.select ()
+        raise RuntimeError, 'Could not find a matching frame'
+
+    def invoke (self, arg, from_tty):
+        self.rx = re.compile (arg)
+        self.search ()
+
+class UptoSymbolCommand (UptoImplementation):
+    """Select and print some calling stack frame, based on symbol.
+The argument is a regular expression.  This command moves up the
+stack, stopping at the first frame whose symbol matches the regular
+expression."""
+
+    def __init__ (self):
+        super (UptoSymbolCommand, self).__init__ ("symbol")
+
+    def filter (self, frame):
+        name = frame.name ()
+        if name is not None:
+            if self.rx.search (name) is not None:
+                return True
+        return False
+
+class UptoSourceCommand (UptoImplementation):
+    """Select and print some calling stack frame, based on source file.
+The argument is a regular expression.  This command moves up the
+stack, stopping at the first frame whose source file name matches the
+regular expression."""
+
+    def __init__ (self):
+        super (UptoSourceCommand, self).__init__ ("source")
+
+    def filter (self, frame):
+        name = frame.find_sal ().symtab.filename
+        if name is not None:
+            if self.rx.search (name) is not None:
+                return True
+        return False
+
+class UptoObjectCommand (UptoImplementation):
+    """Select and print some calling stack frame, based on object file.
+The argument is a regular expression.  This command moves up the
+stack, stopping at the first frame whose object file name matches the
+regular expression."""
+
+    def __init__ (self):
+        super (UptoObjectCommand, self).__init__ ("object")
+
+    def filter (self, frame):
+        name = frame.find_sal ().symtab.objfile.filename
+        if name is not None:
+            if self.rx.search (name) is not None:
+                return True
+        return False
+
+class UptoWhereCommand (UptoImplementation):
+    """Select and print some calling stack frame, based on expression.
+The argument is an expression.  This command moves up the stack,
+parsing and evaluating the expression in each frame.  This stops when
+the expression evaluates to a non-zero (true) value."""
+
+    def __init__ (self):
+        super (UptoWhereCommand, self).__init__ ("where")
+
+    def filter (self, frame):
+        try:
+            if gdb.parse_and_eval (self.expression):
+                return True
+        except:
+            pass
+        return False
+
+    def invoke (self, arg, from_tty):
+        self.expression = arg
+        self.search ()
+
+UptoPrefix ()
+UptoSymbolCommand ()
+UptoSourceCommand ()
+UptoObjectCommand ()
+UptoWhereCommand ()
diff --git a/gdb/python/lib/gdb/frame.py b/gdb/python/lib/gdb/frame.py
new file mode 100644
index 0000000..4743cd9
--- /dev/null
+++ b/gdb/python/lib/gdb/frame.py
@@ -0,0 +1,238 @@
+# 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 <http://www.gnu.org/licenses/>.
+
+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(" <function called from gdb>\n")
+    elif frame.type() == gdb.SIGTRAMP_FRAME:
+        stream.write(" <signal handler called>\n")
+    elif frame.type() == gdb.ARCH_FRAME:
+        stream.write(" <cross-architecture call>\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


hooks/post-receive
--
Repository for Project Archer.


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2011-02-21 13:57 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-02-21 13:57 [SCM] archer-pmuldoon-python-backtrace: Add Tom Tromey's remodelled backtrace reference implementation as extracted from archer-tromey-python and patches to the list 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).