309 lines
11 KiB
Diff
309 lines
11 KiB
Diff
https://bugzilla.redhat.com/show_bug.cgi?id=1020004
|
|
|
|
Index: gdb-7.9.50.20150520/gdb/data-directory/Makefile.in
|
|
===================================================================
|
|
--- gdb-7.9.50.20150520.orig/gdb/data-directory/Makefile.in 2015-05-31 18:05:43.046746351 +0200
|
|
+++ gdb-7.9.50.20150520/gdb/data-directory/Makefile.in 2015-05-31 18:05:58.483841655 +0200
|
|
@@ -60,6 +60,8 @@ PYTHON_FILE_LIST = \
|
|
gdb/frames.py \
|
|
gdb/FrameIterator.py \
|
|
gdb/FrameDecorator.py \
|
|
+ gdb/FrameWrapper.py \
|
|
+ gdb/backtrace.py \
|
|
gdb/types.py \
|
|
gdb/printing.py \
|
|
gdb/unwinder.py \
|
|
@@ -76,6 +78,7 @@ PYTHON_FILE_LIST = \
|
|
gdb/command/pretty_printers.py \
|
|
gdb/command/prompt.py \
|
|
gdb/command/explore.py \
|
|
+ gdb/command/backtrace.py \
|
|
gdb/function/__init__.py \
|
|
gdb/function/caller_is.py \
|
|
gdb/function/strfns.py \
|
|
Index: gdb-7.9.50.20150520/gdb/python/lib/gdb/FrameWrapper.py
|
|
===================================================================
|
|
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
|
+++ gdb-7.9.50.20150520/gdb/python/lib/gdb/FrameWrapper.py 2015-05-31 18:05:58.484841661 +0200
|
|
@@ -0,0 +1,122 @@
|
|
+# Wrapper API for frames.
|
|
+
|
|
+# Copyright (C) 2008, 2009 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
|
|
+
|
|
+# FIXME: arguably all this should be on Frame somehow.
|
|
+class FrameWrapper:
|
|
+ def __init__ (self, frame):
|
|
+ self.frame = frame;
|
|
+
|
|
+ def write_symbol (self, stream, sym, 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
|
|
+
|
|
+ stream.write (sym.print_name + "=")
|
|
+ try:
|
|
+ val = self.read_var (sym)
|
|
+ if val != None:
|
|
+ val = str (val)
|
|
+ # FIXME: would be nice to have a more precise exception here.
|
|
+ except RuntimeError, text:
|
|
+ val = text
|
|
+ if val == None:
|
|
+ stream.write ("???")
|
|
+ else:
|
|
+ stream.write (str (val))
|
|
+
|
|
+ def print_frame_locals (self, stream, func):
|
|
+
|
|
+ try:
|
|
+ block = self.frame.block()
|
|
+ except RuntimeError:
|
|
+ block = None
|
|
+
|
|
+ while block != None:
|
|
+ if block.is_global or block.is_static:
|
|
+ break
|
|
+
|
|
+ for sym in block:
|
|
+ if sym.is_argument:
|
|
+ continue;
|
|
+
|
|
+ self.write_symbol (stream, sym, block)
|
|
+ stream.write ('\n')
|
|
+
|
|
+ def print_frame_args (self, stream, func):
|
|
+
|
|
+ try:
|
|
+ block = self.frame.block()
|
|
+ except RuntimeError:
|
|
+ block = None
|
|
+
|
|
+ while block != None:
|
|
+ if block.function != None:
|
|
+ break
|
|
+ block = block.superblock
|
|
+
|
|
+ first = True
|
|
+ for sym in block:
|
|
+ if not sym.is_argument:
|
|
+ continue;
|
|
+
|
|
+ if not first:
|
|
+ stream.write (", ")
|
|
+
|
|
+ self.write_symbol (stream, sym, block)
|
|
+ first = False
|
|
+
|
|
+ # FIXME: this should probably just be a method on gdb.Frame.
|
|
+ # But then we need stream wrappers.
|
|
+ def describe (self, stream, full):
|
|
+ if self.type () == gdb.DUMMY_FRAME:
|
|
+ stream.write (" <function called from gdb>\n")
|
|
+ elif self.type () == gdb.SIGTRAMP_FRAME:
|
|
+ stream.write (" <signal handler called>\n")
|
|
+ else:
|
|
+ sal = self.find_sal ()
|
|
+ pc = self.pc ()
|
|
+ name = self.name ()
|
|
+ if not name:
|
|
+ name = "??"
|
|
+ if pc != sal.pc or not sal.symtab:
|
|
+ stream.write (" 0x%08x in" % pc)
|
|
+ stream.write (" " + name + " (")
|
|
+
|
|
+ func = self.function ()
|
|
+ self.print_frame_args (stream, func)
|
|
+
|
|
+ stream.write (")")
|
|
+
|
|
+ if sal.symtab and sal.symtab.filename:
|
|
+ stream.write (" at " + sal.symtab.filename)
|
|
+ stream.write (":" + str (sal.line))
|
|
+
|
|
+ if not self.name () or (not sal.symtab or not sal.symtab.filename):
|
|
+ lib = gdb.solib_name (pc)
|
|
+ if lib:
|
|
+ stream.write (" from " + lib)
|
|
+
|
|
+ stream.write ("\n")
|
|
+
|
|
+ if full:
|
|
+ self.print_frame_locals (stream, func)
|
|
+
|
|
+ def __getattr__ (self, name):
|
|
+ return getattr (self.frame, name)
|
|
Index: gdb-7.9.50.20150520/gdb/python/lib/gdb/backtrace.py
|
|
===================================================================
|
|
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
|
+++ gdb-7.9.50.20150520/gdb/python/lib/gdb/backtrace.py 2015-05-31 18:05:58.484841661 +0200
|
|
@@ -0,0 +1,42 @@
|
|
+# Filtering backtrace.
|
|
+
|
|
+# Copyright (C) 2008, 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 itertools
|
|
+
|
|
+# Our only exports.
|
|
+__all__ = ['push_frame_filter', 'create_frame_filter']
|
|
+
|
|
+old_frame_filter = None
|
|
+
|
|
+def push_frame_filter (constructor):
|
|
+ """Register a new backtrace filter class with the 'backtrace' command.
|
|
+The filter will be passed an iterator as an argument. The iterator
|
|
+will return gdb.Frame-like objects. The filter should in turn act as
|
|
+an iterator returning such objects."""
|
|
+ global old_frame_filter
|
|
+ if old_frame_filter == None:
|
|
+ old_frame_filter = constructor
|
|
+ else:
|
|
+ old_frame_filter = lambda iterator, filter = frame_filter: constructor (filter(iterator))
|
|
+
|
|
+def create_frame_filter (iter):
|
|
+ global old_frame_filter
|
|
+ if old_frame_filter is None:
|
|
+ return iter
|
|
+ return old_frame_filter (iter)
|
|
+
|
|
Index: gdb-7.9.50.20150520/gdb/python/lib/gdb/command/backtrace.py
|
|
===================================================================
|
|
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
|
+++ gdb-7.9.50.20150520/gdb/python/lib/gdb/command/backtrace.py 2015-05-31 18:05:58.484841661 +0200
|
|
@@ -0,0 +1,106 @@
|
|
+# New backtrace command.
|
|
+
|
|
+# Copyright (C) 2008, 2009, 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.backtrace
|
|
+import itertools
|
|
+from gdb.FrameIterator import FrameIterator
|
|
+from gdb.FrameWrapper import FrameWrapper
|
|
+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):
|
|
+ gdb.Parameter.__init__ (self, "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.
|
|
+With a negative argument, print outermost -COUNT frames.
|
|
+Use of the 'full' qualifier also prints the values of the local variables.
|
|
+Use of the 'raw' qualifier avoids any filtering by loadable modules.
|
|
+"""
|
|
+
|
|
+ def __init__ (self):
|
|
+ # FIXME: this is not working quite well enough to replace
|
|
+ # "backtrace" yet.
|
|
+ gdb.Command.__init__ (self, "new-backtrace", gdb.COMMAND_STACK)
|
|
+ self.reverse = ReverseBacktraceParameter()
|
|
+
|
|
+ def reverse_iter (self, iter):
|
|
+ result = []
|
|
+ for item in iter:
|
|
+ result.append (item)
|
|
+ result.reverse()
|
|
+ return result
|
|
+
|
|
+ def final_n (self, iter, x):
|
|
+ result = []
|
|
+ for item in iter:
|
|
+ result.append (item)
|
|
+ return result[x:]
|
|
+
|
|
+ def invoke (self, arg, from_tty):
|
|
+ i = 0
|
|
+ count = 0
|
|
+ filter = True
|
|
+ full = False
|
|
+
|
|
+ for word in arg.split (" "):
|
|
+ if word == '':
|
|
+ continue
|
|
+ elif word == 'raw':
|
|
+ filter = False
|
|
+ elif word == 'full':
|
|
+ full = True
|
|
+ else:
|
|
+ count = int (word)
|
|
+
|
|
+ # FIXME: provide option to start at selected frame
|
|
+ # However, should still number as if starting from newest
|
|
+ newest_frame = gdb.newest_frame()
|
|
+ iter = itertools.imap (FrameWrapper,
|
|
+ FrameIterator (newest_frame))
|
|
+ if filter:
|
|
+ iter = gdb.backtrace.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 self.reverse.value:
|
|
+ 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])
|
|
+ pair[1].describe (sys.stdout, full)
|
|
+
|
|
+FilteringBacktrace()
|