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).