public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
* [rpms/gdb] gdb-17.2-rebase-f44: Backported Python frame filters (Phil Muldoon).
@ 2026-06-27 23:56 Jan Kratochvil
  0 siblings, 0 replies; only message in thread
From: Jan Kratochvil @ 2026-06-27 23:56 UTC (permalink / raw)
  To: git-commits

            A new commit has been pushed.

            Repo   : rpms/gdb
            Branch : gdb-17.2-rebase-f44
            Commit : 89fbbfccaf093284eadb1af638486ee5b1701a81
            Author : Jan Kratochvil <jan.kratochvil@redhat.com>
            Date   : 2013-05-21T13:54:33+02:00
            Stats  : +5861/-562 in 7 file(s)
            URL    : https://src.fedoraproject.org/rpms/gdb/c/89fbbfccaf093284eadb1af638486ee5b1701a81?branch=gdb-17.2-rebase-f44

            Log:
            Backported Python frame filters (Phil Muldoon).

- Backported breakpoint conditions crash fix (Sergio Durigan Junior).

---
diff --git a/gdb-6.3-gstack-20050411.patch b/gdb-6.3-gstack-20050411.patch
index 5fe902c..b73eeff 100644
--- a/gdb-6.3-gstack-20050411.patch
+++ b/gdb-6.3-gstack-20050411.patch
@@ -4,11 +4,11 @@
 	to install and uninstall.
 	* gstack.sh, gstack.1: New files.
 
-Index: gdb-7.5.91.20130407/gdb/Makefile.in
+Index: gdb-7.6/gdb/Makefile.in
 ===================================================================
---- gdb-7.5.91.20130407.orig/gdb/Makefile.in	2013-04-11 16:50:33.000000000 +0200
-+++ gdb-7.5.91.20130407/gdb/Makefile.in	2013-04-11 16:52:51.032280294 +0200
-@@ -1027,7 +1027,7 @@ info install-info clean-info dvi pdf ins
+--- gdb-7.6.orig/gdb/Makefile.in	2013-05-21 13:26:33.496820763 +0200
++++ gdb-7.6/gdb/Makefile.in	2013-05-21 13:26:33.609819579 +0200
+@@ -1029,7 +1029,7 @@ info install-info clean-info dvi pdf ins
  install: all
  	@$(MAKE) $(FLAGS_TO_PASS) install-only
  
@@ -17,7 +17,7 @@ Index: gdb-7.5.91.20130407/gdb/Makefile.in
  	transformed_name=`t='$(program_transform_name)'; \
  			  echo gdb | sed -e "$$t"` ; \
  		if test "x$$transformed_name" = x; then \
-@@ -1058,7 +1058,25 @@ install-only: $(CONFIG_INSTALL)
+@@ -1060,7 +1060,25 @@ install-only: $(CONFIG_INSTALL)
  install-python:
  	$(SHELL) $(srcdir)/../mkinstalldirs $(DESTDIR)$(GDB_DATADIR)/python/gdb
  
@@ -44,7 +44,7 @@ Index: gdb-7.5.91.20130407/gdb/Makefile.in
  	transformed_name=`t='$(program_transform_name)'; \
  			  echo gdb | sed -e $$t` ; \
  		if test "x$$transformed_name" = x; then \
-@@ -1081,6 +1099,18 @@ uninstall: force $(CONFIG_UNINSTALL)
+@@ -1083,6 +1101,18 @@ uninstall: force $(CONFIG_UNINSTALL)
  	fi
  	@$(MAKE) DO=uninstall "DODIRS=$(SUBDIRS)" $(FLAGS_TO_PASS) subdir_do
  
@@ -63,10 +63,10 @@ Index: gdb-7.5.91.20130407/gdb/Makefile.in
  # The C++ name parser can be built standalone for testing.
  test-cp-name-parser.o: cp-name-parser.c
  	$(COMPILE) -DTEST_CPNAMES cp-name-parser.c
-Index: gdb-7.5.91.20130407/gdb/gstack.sh
+Index: gdb-7.6/gdb/gstack.sh
 ===================================================================
 --- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ gdb-7.5.91.20130407/gdb/gstack.sh	2013-04-11 16:52:22.093281616 +0200
++++ gdb-7.6/gdb/gstack.sh	2013-05-21 13:26:55.434625908 +0200
 @@ -0,0 +1,43 @@
 +#!/bin/sh
 +
@@ -101,7 +101,7 @@ Index: gdb-7.5.91.20130407/gdb/gstack.sh
 +
 +# Run GDB, strip out unwanted noise.
 +# --readnever is no longer used since .gdb_index is now in use.
-+$GDB --quiet -nx /proc/$1/exe $1 <<EOF 2>&1 | 
++$GDB --quiet -nx $GDBARGS /proc/$1/exe $1 <<EOF 2>&1 | 
 +set width 0
 +set height 0
 +set pagination no
@@ -111,10 +111,10 @@ Index: gdb-7.5.91.20130407/gdb/gstack.sh
 +    -e 's/^\((gdb) \)*//' \
 +    -e '/^#/p' \
 +    -e '/^Thread/p'
-Index: gdb-7.5.91.20130407/gdb/testsuite/gdb.base/gstack.exp
+Index: gdb-7.6/gdb/testsuite/gdb.base/gstack.exp
 ===================================================================
 --- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ gdb-7.5.91.20130407/gdb/testsuite/gdb.base/gstack.exp	2013-04-11 16:52:22.093281616 +0200
++++ gdb-7.6/gdb/testsuite/gdb.base/gstack.exp	2013-05-21 13:26:55.434625908 +0200
 @@ -0,0 +1,66 @@
 +# Copyright (C) 2012 Free Software Foundation, Inc.
 +
@@ -167,7 +167,7 @@ Index: gdb-7.5.91.20130407/gdb/testsuite/gdb.base/gstack.exp
 +# exiting the function.  Still we could retry the gstack command if we fail.
 +
 +set test "spawn gstack"
-+set command "sh -c GDB=$GDB\\ sh\\ ${srcdir}/../gstack.sh\\ $pid\\;echo\\ GSTACK-END"
++set command "sh -c GDB=$GDB\\ GDBARGS=-data-directory\\\\\\ $BUILD_DATA_DIRECTORY\\ sh\\ ${srcdir}/../gstack.sh\\ $pid\\;echo\\ GSTACK-END"
 +set res [remote_spawn host $command];
 +if { $res < 0 || $res == "" } {
 +    perror "Spawning $command failed."
@@ -182,10 +182,10 @@ Index: gdb-7.5.91.20130407/gdb/testsuite/gdb.base/gstack.exp
 +gdb_exit
 +
 +remote_exec host "kill -9 $pid"
-Index: gdb-7.5.91.20130407/gdb/testsuite/gdb.base/gstack.c
+Index: gdb-7.6/gdb/testsuite/gdb.base/gstack.c
 ===================================================================
 --- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ gdb-7.5.91.20130407/gdb/testsuite/gdb.base/gstack.c	2013-04-11 16:52:22.093281616 +0200
++++ gdb-7.6/gdb/testsuite/gdb.base/gstack.c	2013-05-21 13:26:33.610819569 +0200
 @@ -0,0 +1,43 @@
 +/* This testcase is part of GDB, the GNU debugger.
 +

diff --git a/gdb-6.5-BEA-testsuite.patch b/gdb-6.5-BEA-testsuite.patch
index 76d7566..7c5778c 100644
--- a/gdb-6.5-BEA-testsuite.patch
+++ b/gdb-6.5-BEA-testsuite.patch
@@ -1,9 +1,7 @@
-Index: ./gdb/testsuite/gdb.threads/threadcrash.c
+Index: gdb-7.6/gdb/testsuite/gdb.threads/threadcrash.c
 ===================================================================
-RCS file: gdb/testsuite/gdb.threads/threadcrash.c
-diff -N gdb/testsuite/gdb.threads/threadcrash.c
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ ./gdb/testsuite/gdb.threads/threadcrash.c	31 Oct 2006 17:54:38 -0000
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ gdb-7.6/gdb/testsuite/gdb.threads/threadcrash.c	2013-05-21 13:35:45.592059786 +0200
 @@ -0,0 +1,301 @@
 +/*
 + * The point of this program is to crash in a multi-threaded app.
@@ -306,12 +304,10 @@ diff -N gdb/testsuite/gdb.threads/threadcrash.c
 +   
 +   return 0;
 +}
-Index: ./gdb/testsuite/gdb.threads/threadcrash.exp
+Index: gdb-7.6/gdb/testsuite/gdb.threads/threadcrash.exp
 ===================================================================
-RCS file: gdb/testsuite/gdb.threads/threadcrash.exp
-diff -N gdb/testsuite/gdb.threads/threadcrash.exp
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ ./gdb/testsuite/gdb.threads/threadcrash.exp	31 Oct 2006 17:54:38 -0000
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ gdb-7.6/gdb/testsuite/gdb.threads/threadcrash.exp	2013-05-21 13:36:01.451056746 +0200
 @@ -0,0 +1,37 @@
 +# threadcrash.exp - The point of this program is to crash in a multi-threaded app.
 +
@@ -337,7 +333,7 @@ diff -N gdb/testsuite/gdb.threads/threadcrash.exp
 +}
 +
 +# ${shellfile} argument must not contain any directories.
-+set fd [open "|bash ${shellfile} ${binfile} $GDB -nw $GDBFLAGS" r]
++set fd [open "|bash ${shellfile} ${binfile} $GDB $INTERNAL_GDBFLAGS $GDBFLAGS [host_info gdb_opts]" r]
 +while { [gets $fd line] >= 0 } {
 +    if [regexp " PASS: (.*)$" $line trash message] {
 +	pass $message
@@ -350,12 +346,10 @@ diff -N gdb/testsuite/gdb.threads/threadcrash.exp
 +}
 +
 +return 0
-Index: ./gdb/testsuite/gdb.threads/threadcrash.sh
+Index: gdb-7.6/gdb/testsuite/gdb.threads/threadcrash.sh
 ===================================================================
-RCS file: gdb/testsuite/gdb.threads/threadcrash.sh
-diff -N gdb/testsuite/gdb.threads/threadcrash.sh
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ ./gdb/testsuite/gdb.threads/threadcrash.sh	31 Oct 2006 17:54:38 -0000
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ gdb-7.6/gdb/testsuite/gdb.threads/threadcrash.sh	2013-05-21 13:35:45.593059786 +0200
 @@ -0,0 +1,324 @@
 +#! /bin/bash
 +
@@ -681,12 +675,10 @@ diff -N gdb/testsuite/gdb.threads/threadcrash.sh
 +rm -rf $WORKDIR
 +
 +exit $FAILURES
-Index: ./gdb/testsuite/gdb.threads/threadcrash.sh-orig
+Index: gdb-7.6/gdb/testsuite/gdb.threads/threadcrash.sh-orig
 ===================================================================
-RCS file: gdb/testsuite/gdb.threads/threadcrash.sh-orig
-diff -N gdb/testsuite/gdb.threads/threadcrash.sh-orig
---- /dev/null	1 Jan 1970 00:00:00 -0000
-+++ ./gdb/testsuite/gdb.threads/threadcrash.sh-orig	31 Oct 2006 17:54:38 -0000
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ gdb-7.6/gdb/testsuite/gdb.threads/threadcrash.sh-orig	2013-05-21 13:35:45.593059786 +0200
 @@ -0,0 +1,248 @@
 +#! /bin/bash
 +

diff --git a/gdb-archer.patch b/gdb-archer.patch
index 4060cc0..ab0657f 100644
--- a/gdb-archer.patch
+++ b/gdb-archer.patch
@@ -2,7 +2,7 @@ http://sourceware.org/gdb/wiki/ProjectArcher
 http://sourceware.org/gdb/wiki/ArcherBranchManagement
 
 GIT snapshot:
-commit 92cf2d53a9c69b4fb361de662de9100c6e72caa0
+commit b1f8c6821303f6eb087fb7f57405483ac8812227
 
 branch jankratochvil/fedora19 - the merge of branches:
 jankratochvil/vla
@@ -169,22 +169,17 @@ index ca8d89b..811ad72 100644
  			    plongest (high_bound - low_bound + 1));
  	fprintf_filtered (stream, (is_vector ? ")))" : "]"));
 diff --git a/gdb/data-directory/Makefile.in b/gdb/data-directory/Makefile.in
-index d98ac77..e248399 100644
+index d98ac77..f6a4b99 100644
 --- a/gdb/data-directory/Makefile.in
 +++ b/gdb/data-directory/Makefile.in
-@@ -52,17 +52,28 @@ SYSCALLS_FILES = \
- PYTHON_DIR = python
+@@ -53,16 +53,21 @@ PYTHON_DIR = python
  PYTHON_INSTALL_DIR = $(DESTDIR)$(GDB_DATADIR)/$(PYTHON_DIR)
  PYTHON_FILES = \
-+	gdb/FrameIterator.py \
-+	gdb/FrameWrapper.py \
  	gdb/__init__.py \
 -	gdb/types.py \
 -	gdb/printing.py \
 -	gdb/prompt.py \
-+	gdb/backtrace.py \
  	gdb/command/__init__.py \
-+	gdb/command/backtrace.py \
 +	gdb/command/ignore_errors.py \
 +	gdb/command/pahole.py \
  	gdb/command/type_printers.py \
@@ -194,8 +189,6 @@ index d98ac77..e248399 100644
  	gdb/function/__init__.py \
 -	gdb/function/strfns.py
 +	gdb/function/strfns.py \
-+	gdb/command/require.py \
-+	gdb/command/upto.py \
 +	gdb/function/__init__.py \
 +	gdb/function/caller_is.py \
 +	gdb/function/in_scope.py \
@@ -3778,323 +3771,6 @@ index 155703d..545a615 100644
 +  observer_attach_mark_used (print_types_mark_used);
 +#endif
  }
-diff --git a/gdb/python/lib/gdb/FrameIterator.py b/gdb/python/lib/gdb/FrameIterator.py
-new file mode 100644
-index 0000000..5654546
---- /dev/null
-+++ b/gdb/python/lib/gdb/FrameIterator.py
-@@ -0,0 +1,33 @@
-+# Iterator over 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/>.
-+
-+class FrameIterator:
-+    """An iterator that iterates over frames."""
-+
-+    def __init__ (self, frame):
-+        "Initialize a FrameIterator.  FRAME is the starting frame."
-+        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
-diff --git a/gdb/python/lib/gdb/FrameWrapper.py b/gdb/python/lib/gdb/FrameWrapper.py
-new file mode 100644
-index 0000000..b790a54
---- /dev/null
-+++ b/gdb/python/lib/gdb/FrameWrapper.py
-@@ -0,0 +1,112 @@
-+# 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):
-+        if not func:
-+            return
-+
-+        first = True
-+        block = func.value
-+
-+        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):
-+        if not func:
-+            return
-+
-+        first = True
-+        block = func.value
-+
-+        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_address (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)
-diff --git a/gdb/python/lib/gdb/backtrace.py b/gdb/python/lib/gdb/backtrace.py
-new file mode 100644
-index 0000000..6bb4fb1
---- /dev/null
-+++ b/gdb/python/lib/gdb/backtrace.py
-@@ -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']
-+
-+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 frame_filter
-+    if frame_filter == None:
-+        frame_filter = constructor
-+    else:
-+        frame_filter = lambda iterator, filter = frame_filter: constructor (filter (iterator))
-+
-+def create_frame_filter (iter):
-+    global frame_filter
-+    if frame_filter is None:
-+        return iter
-+    return frame_filter (iter)
-+
-diff --git a/gdb/python/lib/gdb/command/backtrace.py b/gdb/python/lib/gdb/command/backtrace.py
-new file mode 100644
-index 0000000..eeea909
---- /dev/null
-+++ b/gdb/python/lib/gdb/command/backtrace.py
-@@ -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()
 diff --git a/gdb/python/lib/gdb/command/ignore_errors.py b/gdb/python/lib/gdb/command/ignore_errors.py
 new file mode 100644
 index 0000000..6fa48ff
@@ -4225,204 +3901,6 @@ index 0000000..636f99d
 +        self.pahole (type, 0, '')
 +
 +Pahole()
-diff --git a/gdb/python/lib/gdb/command/require.py b/gdb/python/lib/gdb/command/require.py
-new file mode 100644
-index 0000000..1fbc1e8
---- /dev/null
-+++ b/gdb/python/lib/gdb/command/require.py
-@@ -0,0 +1,57 @@
-+# Demand-loading commands.
-+
-+# 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
-+import os
-+
-+class RequireCommand (gdb.Command):
-+    """Prefix command for requiring features."""
-+
-+    def __init__ (self):
-+        super (RequireCommand, self).__init__ ("require",
-+                                               gdb.COMMAND_SUPPORT,
-+                                               gdb.COMPLETE_NONE,
-+                                               True)
-+
-+class RequireSubcommand (gdb.Command):
-+    """Demand-load a command by name."""
-+
-+    def __init__ (self, name):
-+        self.__doc__ = "Demand-load a %s by name." % name
-+        super (RequireSubcommand, self).__init__ ("require %s" % name,
-+                                                  gdb.COMMAND_SUPPORT)
-+        self.name = name
-+
-+    def invoke (self, arg, from_tty):
-+        for cmd in arg.split():
-+            exec ('import gdb.' + self.name + '.' + cmd, globals ())
-+
-+    def complete (self, text, word):
-+        dir = gdb.pythondir + '/gdb/' + self.name
-+        result = []
-+        for file in os.listdir(dir):
-+            if not file.startswith (word) or not file.endswith ('.py'):
-+                continue
-+            feature = file[0:-3]
-+            if feature == 'require' or feature == '__init__':
-+                continue
-+            result.append (feature)
-+        return result
-+
-+RequireCommand()
-+RequireSubcommand("command")
-+RequireSubcommand("function")
-diff --git a/gdb/python/lib/gdb/command/upto.py b/gdb/python/lib/gdb/command/upto.py
-new file mode 100644
-index 0000000..faf54ed
---- /dev/null
-+++ b/gdb/python/lib/gdb/command/upto.py
-@@ -0,0 +1,129 @@
-+# upto command.
-+
-+# Copyright (C) 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
-+import re
-+from gdb.FrameIterator import FrameIterator
-+from gdb.FrameWrapper import FrameWrapper
-+
-+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 = FrameIterator (saved)
-+        found = False
-+        try:
-+            for frame in iter:
-+                frame.select ()
-+                try:
-+                    if self.filter (frame):
-+                        wrapper = FrameWrapper (frame)
-+                        wrapper.describe (sys.stdout, False)
-+                        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/function/caller_is.py b/gdb/python/lib/gdb/function/caller_is.py
 new file mode 100644
 index 0000000..2b9c5c7

diff --git a/gdb-upstream-framefilters-1of2.patch b/gdb-upstream-framefilters-1of2.patch
new file mode 100644
index 0000000..d0ab188
--- /dev/null
+++ b/gdb-upstream-framefilters-1of2.patch
@@ -0,0 +1,5551 @@
+http://sourceware.org/ml/gdb-cvs/2013-05/msg00084.html
+
+### src/gdb/ChangeLog	2013/05/09 18:03:27	1.15539
+### src/gdb/ChangeLog	2013/05/10 10:26:01	1.15540
+## -1,3 +1,52 @@
++2013-05-10  Phil Muldoon  <pmuldoon@redhat.com>
++
++	* stack.c (backtrace_command_1): Add "no-filters", and Python frame
++	filter logic.
++	(backtrace_command): Add "no-filters" option parsing.
++	(_initialize_stack): Alter help to reflect "no-filters" option.
++	* Makefile.in (SUBDIR_PYTHON_OBS): Add py-framefilter.o
++	(SUBDIR_PYTHON_SRCS): Add py-framefilter.c
++	(py-frame.o): Add target
++	* data-directory/Makefile.in (PYTHON_DIR): Add Python frame
++	filter files.
++	* python/python.h: Add new frame filter constants, and flag enum.
++	(apply_frame_filter): Add definition.
++	* python/python.c (apply_frame_filter): New non-Python
++	enabled function.
++	* python/py-utils.c (py_xdecref): New function.
++	(make_cleanup_py_xdecref): Ditto.
++	* python/py-objfile.c: Declare frame_filters dictionary.
++	(objfpy_dealloc): Add frame_filters dealloc.
++	(objfpy_new): Initialize frame_filters attribute.
++	(objfile_to_objfile_object): Ditto.
++	(objfpy_get_frame_filters): New function.
++	(objfpy_set_frame_filters): New function.
++	* python/py-progspace.c: Declare frame_filters dictionary.
++	(pspy_dealloc): Add frame_filters dealloc.
++	(pspy_new): Initialize frame_filters attribute.
++	(pspacee_to_pspace_object): Ditto.
++	(pspy_get_frame_filters): New function.
++	(pspy_set_frame_filters): New function.
++	* python/py-framefilter.c: New file.
++	* python/lib/gdb/command/frame_filters.py: New file.
++	* python/lib/gdb/frames.py: New file.
++	* python/lib/gdb/__init__.py: Initialize global frame_filters
++	dictionary
++	* python/lib/gdb/FrameDecorator.py: New file.
++	* python/lib/gdb/FrameIterator.py: New file.
++	* mi/mi-cmds.c (mi_cmds): Add frame filters command.
++	* mi/mi-cmds.h: Declare.
++	* mi/mi-cmd-stack.c (mi_cmd_stack_list_frames): Add
++	--no-frame-filter logic, and Python frame filter logic.
++	(stack_enable_frame_filters): New function.
++	(parse_no_frame_option): Ditto.
++	(mi_cmd_stack_list_frames): Add --no-frame-filter and Python frame
++	filter logic.
++	(mi_cmd_stack_list_locals): Ditto.
++	(mi_cmd_stack_list_args): Ditto.
++	(mi_cmd_stack_list_variables): Ditto.
++	* NEWS: Add frame filter note.
++
+ 2013-05-09  Doug Evans  <dje@google.com>
+ 
+ 	* symfile.c (syms_from_objfile_1): Delete args offsets, num_offsets.
+Index: gdb-7.6/gdb/Makefile.in
+===================================================================
+--- gdb-7.6.orig/gdb/Makefile.in	2013-05-20 22:23:36.748215146 +0200
++++ gdb-7.6/gdb/Makefile.in	2013-05-20 22:25:52.096165773 +0200
+@@ -284,6 +284,7 @@ SUBDIR_PYTHON_OBS = \
+ 	py-exitedevent.o \
+ 	py-finishbreakpoint.o \
+ 	py-frame.o \
++	py-framefilter.o \
+ 	py-function.o \
+ 	py-gdb-readline.o \
+ 	py-inferior.o \
+@@ -318,6 +319,7 @@ SUBDIR_PYTHON_SRCS = \
+ 	python/py-exitedevent.c \
+ 	python/py-finishbreakpoint.c \
+ 	python/py-frame.c \
++	python/py-framefilter.c \
+ 	python/py-function.c \
+ 	python/py-gdb-readline.c \
+ 	python/py-inferior.c \
+@@ -2135,6 +2137,10 @@ py-frame.o: $(srcdir)/python/py-frame.c
+ 	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-frame.c
+ 	$(POSTCOMPILE)
+ 
++py-framefilter.o: $(srcdir)/python/py-framefilter.c
++	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-framefilter.c
++	$(POSTCOMPILE)
++
+ py-function.o: $(srcdir)/python/py-function.c
+ 	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-function.c
+ 	$(POSTCOMPILE)
+Index: gdb-7.6/gdb/NEWS
+===================================================================
+--- gdb-7.6.orig/gdb/NEWS	2013-05-20 22:23:36.748215146 +0200
++++ gdb-7.6/gdb/NEWS	2013-05-20 22:25:52.097165772 +0200
+@@ -4,6 +4,10 @@
+ * Newly installed $prefix/bin/gcore acts as a shell interface for the
+   GDB command gcore.
+ 
++* Python scripting
++
++  ** Frame filters and frame decorators have been added.
++
+ *** Changes in GDB 7.6
+ 
+ * Target record has been renamed to record-full.
+Index: gdb-7.6/gdb/stack.c
+===================================================================
+--- gdb-7.6.orig/gdb/stack.c	2013-05-20 22:23:36.748215146 +0200
++++ gdb-7.6/gdb/stack.c	2013-05-20 22:25:52.098165772 +0200
+@@ -54,6 +54,7 @@
+ 
+ #include "psymtab.h"
+ #include "symfile.h"
++#include "python/python.h"
+ 
+ void (*deprecated_selected_frame_level_changed_hook) (int);
+ 
+@@ -1655,13 +1656,15 @@ frame_info (char *addr_exp, int from_tty
+    frames.  */
+ 
+ static void
+-backtrace_command_1 (char *count_exp, int show_locals, int from_tty)
++backtrace_command_1 (char *count_exp, int show_locals, int no_filters,
++		     int from_tty)
+ {
+   struct frame_info *fi;
+   int count;
+   int i;
+   struct frame_info *trailing;
+-  int trailing_level;
++  int trailing_level, py_start = 0, py_end = 0;
++  enum py_bt_status result = PY_BT_ERROR;
+ 
+   if (!target_has_stack)
+     error (_("No stack."));
+@@ -1680,6 +1683,7 @@ backtrace_command_1 (char *count_exp, in
+ 	{
+ 	  struct frame_info *current;
+ 
++	  py_start = count;
+ 	  count = -count;
+ 
+ 	  current = trailing;
+@@ -1701,9 +1705,17 @@ backtrace_command_1 (char *count_exp, in
+ 
+ 	  count = -1;
+ 	}
++      else
++	{
++	  py_start = 0;
++	  py_end = count;
++	}
+     }
+   else
+-    count = -1;
++    {
++      py_end = -1;
++      count = -1;
++    }
+ 
+   if (info_verbose)
+     {
+@@ -1723,16 +1735,40 @@ backtrace_command_1 (char *count_exp, in
+ 	}
+     }
+ 
+-  for (i = 0, fi = trailing; fi && count--; i++, fi = get_prev_frame (fi))
++  if (! no_filters)
+     {
+-      QUIT;
++      int flags = PRINT_LEVEL | PRINT_FRAME_INFO | PRINT_ARGS;
++      enum py_frame_args arg_type;
+ 
+-      /* Don't use print_stack_frame; if an error() occurs it probably
+-         means further attempts to backtrace would fail (on the other
+-         hand, perhaps the code does or could be fixed to make sure
+-         the frame->prev field gets set to NULL in that case).  */
+-      print_frame_info (fi, 1, LOCATION, 1);
+       if (show_locals)
++	flags |= PRINT_LOCALS;
++
++      if (!strcmp (print_frame_arguments, "scalars"))
++	arg_type = CLI_SCALAR_VALUES;
++      else if (!strcmp (print_frame_arguments, "all"))
++	arg_type = CLI_ALL_VALUES;
++      else
++	arg_type = NO_VALUES;
++
++      result = apply_frame_filter (get_current_frame (), flags, arg_type,
++				   current_uiout, py_start, py_end);
++
++    }
++  /* Run the inbuilt backtrace if there are no filters registered, or
++     "no-filters" has been specified from the command.  */
++  if (no_filters ||  result == PY_BT_NO_FILTERS)
++    {
++      for (i = 0, fi = trailing; fi && count--; i++, fi = get_prev_frame (fi))
++	{
++	  QUIT;
++
++	  /* Don't use print_stack_frame; if an error() occurs it probably
++	     means further attempts to backtrace would fail (on the other
++	     hand, perhaps the code does or could be fixed to make sure
++	     the frame->prev field gets set to NULL in that case).  */
++
++	  print_frame_info (fi, 1, LOCATION, 1);
++	  if (show_locals)
+ 	{
+ 	  struct frame_id frame_id = get_frame_id (fi);
+ 
+@@ -1748,24 +1784,25 @@ backtrace_command_1 (char *count_exp, in
+ 	    }
+ 	}
+ 
+-      /* Save the last frame to check for error conditions.  */
+-      trailing = fi;
+-    }
++	  /* Save the last frame to check for error conditions.  */
++	  trailing = fi;
++	}
+ 
+-  /* If we've stopped before the end, mention that.  */
+-  if (fi && from_tty)
+-    printf_filtered (_("(More stack frames follow...)\n"));
++      /* If we've stopped before the end, mention that.  */
++      if (fi && from_tty)
++	printf_filtered (_("(More stack frames follow...)\n"));
+ 
+-  /* If we've run out of frames, and the reason appears to be an error
+-     condition, print it.  */
+-  if (fi == NULL && trailing != NULL)
+-    {
+-      enum unwind_stop_reason reason;
++      /* If we've run out of frames, and the reason appears to be an error
++	 condition, print it.  */
++      if (fi == NULL && trailing != NULL)
++	{
++	  enum unwind_stop_reason reason;
+ 
+-      reason = get_frame_unwind_stop_reason (trailing);
+-      if (reason >= UNWIND_FIRST_ERROR)
+-	printf_filtered (_("Backtrace stopped: %s\n"),
+-			 frame_stop_reason_string (reason));
++	  reason = get_frame_unwind_stop_reason (trailing);
++	  if (reason >= UNWIND_FIRST_ERROR)
++	    printf_filtered (_("Backtrace stopped: %s\n"),
++			     frame_stop_reason_string (reason));
++	}
+     }
+ }
+ 
+@@ -1773,7 +1810,8 @@ static void
+ backtrace_command (char *arg, int from_tty)
+ {
+   struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
+-  int fulltrace_arg = -1, arglen = 0, argc = 0;
++  int fulltrace_arg = -1, arglen = 0, argc = 0, no_filters  = -1;
++  int user_arg = 0;
+ 
+   if (arg)
+     {
+@@ -1790,25 +1828,31 @@ backtrace_command (char *arg, int from_t
+ 	  for (j = 0; j < strlen (argv[i]); j++)
+ 	    argv[i][j] = tolower (argv[i][j]);
+ 
+-	  if (fulltrace_arg < 0 && subset_compare (argv[i], "full"))
+-	    fulltrace_arg = argc;
++	  if (no_filters < 0 && subset_compare (argv[i], "no-filters"))
++	    no_filters = argc;
+ 	  else
+ 	    {
+-	      arglen += strlen (argv[i]);
+-	      argc++;
++	      if (fulltrace_arg < 0 && subset_compare (argv[i], "full"))
++		fulltrace_arg = argc;
++	      else
++		{
++		  user_arg++;
++		  arglen += strlen (argv[i]);
++		}
+ 	    }
++	  argc++;
+ 	}
+-      arglen += argc;
+-      if (fulltrace_arg >= 0)
++      arglen += user_arg;
++      if (fulltrace_arg >= 0 || no_filters >= 0)
+ 	{
+ 	  if (arglen > 0)
+ 	    {
+ 	      arg = xmalloc (arglen + 1);
+ 	      make_cleanup (xfree, arg);
+ 	      arg[0] = 0;
+-	      for (i = 0; i < (argc + 1); i++)
++	      for (i = 0; i < argc; i++)
+ 		{
+-		  if (i != fulltrace_arg)
++		  if (i != fulltrace_arg && i != no_filters)
+ 		    {
+ 		      strcat (arg, argv[i]);
+ 		      strcat (arg, " ");
+@@ -1820,7 +1864,8 @@ backtrace_command (char *arg, int from_t
+ 	}
+     }
+ 
+-  backtrace_command_1 (arg, fulltrace_arg >= 0 /* show_locals */, from_tty);
++  backtrace_command_1 (arg, fulltrace_arg >= 0 /* show_locals */,
++		       no_filters >= 0 /* no frame-filters */, from_tty);
+ 
+   do_cleanups (old_chain);
+ }
+@@ -1828,7 +1873,7 @@ backtrace_command (char *arg, int from_t
+ static void
+ backtrace_full_command (char *arg, int from_tty)
+ {
+-  backtrace_command_1 (arg, 1 /* show_locals */, from_tty);
++  backtrace_command_1 (arg, 1 /* show_locals */, 0, from_tty);
+ }
+ \f
+ 
+@@ -2562,7 +2607,9 @@ It can be a stack frame number or the ad
+   add_com ("backtrace", class_stack, backtrace_command, _("\
+ Print backtrace of all stack frames, or innermost COUNT frames.\n\
+ With a negative argument, print outermost -COUNT frames.\nUse of the \
+-'full' qualifier also prints the values of the local variables.\n"));
++'full' qualifier also prints the values of the local variables.\n\
++Use of the 'no-filters' qualifier prohibits frame filters from executing\n\
++on this backtrace.\n"));
+   add_com_alias ("bt", "backtrace", class_stack, 0);
+   if (xdb_commands)
+     {
+Index: gdb-7.6/gdb/data-directory/Makefile.in
+===================================================================
+--- gdb-7.6.orig/gdb/data-directory/Makefile.in	2013-05-20 22:23:36.748215146 +0200
++++ gdb-7.6/gdb/data-directory/Makefile.in	2013-05-20 22:25:52.098165772 +0200
+@@ -53,7 +53,11 @@ PYTHON_DIR = python
+ PYTHON_INSTALL_DIR = $(DESTDIR)$(GDB_DATADIR)/$(PYTHON_DIR)
+ PYTHON_FILES = \
+ 	gdb/__init__.py \
++	gdb/frames.py \
++	gdb/FrameIterator.py \
++	gdb/FrameDecorator.py \
+ 	gdb/command/__init__.py \
++	gdb/command/frame_filters.py \
+ 	gdb/command/ignore_errors.py \
+ 	gdb/command/pahole.py \
+ 	gdb/command/type_printers.py \
+Index: gdb-7.6/gdb/doc/gdb.texinfo
+===================================================================
+--- gdb-7.6.orig/gdb/doc/gdb.texinfo	2013-05-20 22:23:36.748215146 +0200
++++ gdb-7.6/gdb/doc/gdb.texinfo	2013-05-20 22:25:52.110165767 +0200
+@@ -6453,6 +6453,7 @@ currently executing frame and describes
+ @menu
+ * Frames::                      Stack frames
+ * Backtrace::                   Backtraces
++* Frame Filter Management::     Managing frame filters
+ * Selection::                   Selecting a frame
+ * Frame Info::                  Information on a frame
+ 
+@@ -6540,6 +6541,7 @@ line per frame, for many frames, startin
+ frame (frame zero), followed by its caller (frame one), and on up the
+ stack.
+ 
++@anchor{backtrace-command}
+ @table @code
+ @kindex backtrace
+ @kindex bt @r{(@code{backtrace})}
+@@ -6565,6 +6567,19 @@ Similar, but print only the outermost @v
+ @itemx bt full -@var{n}
+ Print the values of the local variables also.  @var{n} specifies the
+ number of frames to print, as described above.
++
++@item backtrace no-filters
++@itemx bt no-filters
++@itemx bt no-filters @var{n}
++@itemx bt no-filters -@var{n}
++@itemx bt no-filters full
++@itemx bt no-filters full @var{n}
++@itemx bt no-filters full -@var{n}
++Do not run Python frame filters on this backtrace.  @xref{Frame
++Filter API}, for more information.  Additionally use @ref{disable
++frame-filter all} to turn off all frame filters.  This is only
++relevant when @value{GDBN} has been configured with @code{Python}
++support.
+ @end table
+ 
+ @kindex where
+@@ -6714,6 +6729,149 @@ Display an absolute filename.
+ Show the current way to display filenames.
+ @end table
+ 
++@node Frame Filter Management
++@section Management of Frame Filters.
++@cindex managing frame filters
++
++Frame filters are Python based utilities to manage and decorate the
++output of frames.  @xref{Frame Filter API}, for further information.
++
++Managing frame filters is performed by several commands available
++within @value{GDBN}, detailed here.
++
++@table @code
++@kindex info frame-filter
++@item info frame-filter
++Print a list of installed frame filters from all dictionaries, showing
++their name, priority and enabled status.
++
++@kindex disable frame-filter
++@anchor{disable frame-filter all}
++@item disable frame-filter @var{filter-dictionary} @var{filter-name}
++Disable a frame filter in the dictionary matching
++@var{filter-dictionary}, or @code{all}, and @var{filter-name}.
++@var{filter-dictionary} may be @code{all}, @code{global},
++@code{progspace} or the name of the object file where the frame filter
++dictionary resides.  When @code{all} is specified, all frame filters
++across all dictionaries are disabled.  @var{filter-name} is the name
++of the frame filter and is used when @code{all} is not the option for
++@var{filter-dictionary}.  A disabled frame-filter is not deleted, it
++may be enabled again later.
++
++@kindex enable frame-filter
++@item enable frame-filter @var{filter-dictionary} @var{filter-name}
++Enable a frame filter in the dictionary matching
++@var{filter-dictionary}, or @code{all}, and @var{filter-name}.
++@var{filter-dictionary} may be @code{all}, @code{global},
++@code{progspace} or the name of the object file where the frame filter
++dictionary resides.  When @code{all} is specified, all frame filters across
++all dictionaries are enabled.  @var{filter-name} is the name of the frame
++filter and is used when @code{all} is not the option for
++@var{filter-dictionary}.
++
++Example:
++
++@smallexample
++(gdb) info frame-filter
++
++global frame-filters:
++  Priority  Enabled  Name
++  1000      No       PrimaryFunctionFilter
++  100       Yes      Reverse
++
++progspace /build/test frame-filters:
++  Priority  Enabled  Name
++  100       Yes      ProgspaceFilter
++
++objfile /build/test frame-filters:
++  Priority  Enabled  Name
++  999       Yes      BuildProgra Filter
++
++(gdb) disable frame-filter /build/test BuildProgramFilter
++(gdb) info frame-filter
++
++global frame-filters:
++  Priority  Enabled  Name
++  1000      No       PrimaryFunctionFilter
++  100       Yes      Reverse
++
++progspace /build/test frame-filters:
++  Priority  Enabled  Name
++  100       Yes      ProgspaceFilter
++
++objfile /build/test frame-filters:
++  Priority  Enabled  Name
++  999       No       BuildProgramFilter
++
++(gdb) enable frame-filter global PrimaryFunctionFilter
++(gdb) info frame-filter
++
++global frame-filters:
++  Priority  Enabled  Name
++  1000      Yes      PrimaryFunctionFilter
++  100       Yes      Reverse
++
++progspace /build/test frame-filters:
++  Priority  Enabled  Name
++  100       Yes      ProgspaceFilter
++
++objfile /build/test frame-filters:
++  Priority  Enabled  Name
++  999       No       BuildProgramFilter
++@end smallexample
++
++@kindex set frame-filter priority
++@item set frame-filter priority @var{filter-dictionary} @var{filter-name} @var{priority}
++Set the @var{priority} of a frame filter in the dictionary matching
++@var{filter-dictionary}, and the frame filter name matching
++@var{filter-name}.  @var{filter-dictionary} may be @code{global},
++@code{progspace} or the name of the object file where the frame filter
++dictionary resides.  @var{priority} is an integer.
++
++@kindex show frame-filter priority
++@item show frame-filter priority @var{filter-dictionary} @var{filter-name}
++Show the @var{priority} of a frame filter in the dictionary matching
++@var{filter-dictionary}, and the frame filter name matching
++@var{filter-name}.  @var{filter-dictionary} may be @code{global},
++@code{progspace} or the name of the object file where the frame filter
++dictionary resides.
++
++Example:
++
++@smallexample
++(gdb) info frame-filter
++
++global frame-filters:
++  Priority  Enabled  Name
++  1000      Yes      PrimaryFunctionFilter
++  100       Yes      Reverse
++
++progspace /build/test frame-filters:
++  Priority  Enabled  Name
++  100       Yes      ProgspaceFilter
++
++objfile /build/test frame-filters:
++  Priority  Enabled  Name
++  999       No       BuildProgramFilter
++
++(gdb) set frame-filter priority global Reverse 50
++(gdb) info frame-filter
++
++global frame-filters:
++  Priority  Enabled  Name
++  1000      Yes      PrimaryFunctionFilter
++  50        Yes      Reverse
++
++progspace /build/test frame-filters:
++  Priority  Enabled  Name
++  100       Yes      ProgspaceFilter
++
++objfile /build/test frame-filters:
++  Priority  Enabled  Name
++  999       No       BuildProgramFilter
++@end smallexample
++@end table
++
+ @node Selection
+ @section Selecting a Frame
+ 
+@@ -23065,6 +23223,9 @@ situation, a Python @code{KeyboardInterr
+ * Selecting Pretty-Printers::   How GDB chooses a pretty-printer.
+ * Writing a Pretty-Printer::    Writing a Pretty-Printer.
+ * Type Printing API::		Pretty-printing types.
++* Frame Filter API::            Filtering Frames.
++* Frame Decorator API::         Decorating Frames.
++* Writing a Frame Filter::      Writing a Frame Filter.
+ * Inferiors In Python::         Python representation of inferiors (processes)
+ * Events In Python::            Listening for events from @value{GDBN}.
+ * Threads In Python::           Accessing inferior threads from Python.
+@@ -24415,6 +24576,636 @@ done then type printers would have to ma
+ order to avoid holding information that could become stale as the
+ inferior changed.
+ 
++@node Frame Filter API
++@subsubsection Filtering Frames.
++@cindex frame filters api
++
++Frame filters are Python objects that manipulate the visibility of a
++frame or frames when a backtrace (@pxref{Backtrace}) is printed by
++@value{GDBN}.
++
++Only commands that print a backtrace, or, in the case of @sc{gdb/mi}
++commands (@pxref{GDB/MI}), those that return a collection of frames
++are affected.  The commands that work with frame filters are:
++
++@code{backtrace} (@pxref{backtrace-command,, The backtrace command}),
++@code{-stack-list-frames}
++(@pxref{-stack-list-frames,, The -stack-list-frames command}),
++@code{-stack-list-variables} (@pxref{-stack-list-variables,, The
++-stack-list-variables command}), @code{-stack-list-arguments}
++@pxref{-stack-list-arguments,, The -stack-list-arguments command}) and
++@code{-stack-list-locals} (@pxref{-stack-list-locals,, The
++-stack-list-locals command}).
++
++A frame filter works by taking an iterator as an argument, applying
++actions to the contents of that iterator, and returning another
++iterator (or, possibly, the same iterator it was provided in the case
++where the filter does not perform any operations).  Typically, frame
++filters utilize tools such as the Python's @code{itertools} module to
++work with and create new iterators from the source iterator.
++Regardless of how a filter chooses to apply actions, it must not alter
++the underlying @value{GDBN} frame or frames, or attempt to alter the
++call-stack within @value{GDBN}.  This preserves data integrity within
++@value{GDBN}.  Frame filters are executed on a priority basis and care
++should be taken that some frame filters may have been executed before,
++and that some frame filters will be executed after.
++
++An important consideration when designing frame filters, and well
++worth reflecting upon, is that frame filters should avoid unwinding
++the call stack if possible.  Some stacks can run very deep, into the
++tens of thousands in some cases.  To search every frame when a frame
++filter executes may be too expensive at that step.  The frame filter
++cannot know how many frames it has to iterate over, and it may have to
++iterate through them all.  This ends up duplicating effort as
++@value{GDBN} performs this iteration when it prints the frames.  If
++the filter can defer unwinding frames until frame decorators are
++executed, after the last filter has executed, it should.  @xref{Frame
++Decorator API}, for more information on decorators.  Also, there are
++examples for both frame decorators and filters in later chapters.
++@xref{Writing a Frame Filter}, for more information.
++
++The Python dictionary @code{gdb.frame_filters} contains key/object
++pairings that comprise a frame filter.  Frame filters in this
++dictionary are called @code{global} frame filters, and they are
++available when debugging all inferiors.  These frame filters must
++register with the dictionary directly.  In addition to the
++@code{global} dictionary, there are other dictionaries that are loaded
++with different inferiors via auto-loading (@pxref{Python
++Auto-loading}).  The two other areas where frame filter dictionaries
++can be found are: @code{gdb.Progspace} which contains a
++@code{frame_filters} dictionary attribute, and each @code{gdb.Objfile}
++object which also contains a @code{frame_filters} dictionary
++attribute.
++
++When a command is executed from @value{GDBN} that is compatible with
++frame filters, @value{GDBN} combines the @code{global},
++@code{gdb.Progspace} and all @code{gdb.Objfile} dictionaries currently
++loaded.  All of the @code{gdb.Objfile} dictionaries are combined, as
++several frames, and thus several object files, might be in use.
++@value{GDBN} then prunes any frame filter whose @code{enabled}
++attribute is @code{False}.  This pruned list is then sorted according
++to the @code{priority} attribute in each filter.
++
++Once the dictionaries are combined, pruned and sorted, @value{GDBN}
++creates an iterator which wraps each frame in the call stack in a
++@code{FrameDecorator} object, and calls each filter in order.  The
++output from the previous filter will always be the input to the next
++filter, and so on.
++
++Frame filters have a mandatory interface which each frame filter must
++implement, defined here:
++
++@defun FrameFilter.filter (iterator)
++@value{GDBN} will call this method on a frame filter when it has
++reached the order in the priority list for that filter.
++
++For example, if there are four frame filters:
++
++@smallexample
++Name         Priority
++
++Filter1      5
++Filter2      10
++Filter3      100
++Filter4      1
++@end smallexample
++
++The order that the frame filters will be called is:
++
++@smallexample
++Filter3 -> Filter2 -> Filter1 -> Filter4
++@end smallexample
++
++Note that the output from @code{Filter3} is passed to the input of
++@code{Filter2}, and so on.
++
++This @code{filter} method is passed a Python iterator.  This iterator
++contains a sequence of frame decorators that wrap each
++@code{gdb.Frame}, or a frame decorator that wraps another frame
++decorator.  The first filter that is executed in the sequence of frame
++filters will receive an iterator entirely comprised of default
++@code{FrameDecorator} objects.  However, after each frame filter is
++executed, the previous frame filter may have wrapped some or all of
++the frame decorators with their own frame decorator.  As frame
++decorators must also conform to a mandatory interface, these
++decorators can be assumed to act in a uniform manner (@pxref{Frame
++Decorator API}).
++
++This method must return an object conforming to the Python iterator
++protocol.  Each item in the iterator must be an object conforming to
++the frame decorator interface.  If a frame filter does not wish to
++perform any operations on this iterator, it should return that
++iterator untouched.
++
++This method is not optional.  If it does not exist, @value{GDBN} will
++raise and print an error.
++@end defun
++
++@defvar FrameFilter.name
++The @code{name} attribute must be Python string which contains the
++name of the filter displayed by @value{GDBN} (@pxref{Frame Filter
++Management}).  This attribute may contain any combination of letters
++or numbers.  Care should be taken to ensure that it is unique.  This
++attribute is mandatory.
++@end defvar
++
++@defvar FrameFilter.enabled
++The @code{enabled} attribute must be Python boolean.  This attribute
++indicates to @value{GDBN} whether the frame filter is enabled, and
++should be considered when frame filters are executed.  If
++@code{enabled} is @code{True}, then the frame filter will be executed
++when any of the backtrace commands detailed earlier in this chapter
++are executed.  If @code{enabled} is @code{False}, then the frame
++filter will not be executed.  This attribute is mandatory.
++@end defvar
++
++@defvar FrameFilter.priority
++The @code{priority} attribute must be Python integer.  This attribute
++controls the order of execution in relation to other frame filters.
++There are no imposed limits on the range of @code{priority} other than
++it must be a valid integer.  The higher the @code{priority} attribute,
++the sooner the frame filter will be executed in relation to other
++frame filters.  Although @code{priority} can be negative, it is
++recommended practice to assume zero is the lowest priority that a
++frame filter can be assigned.  Frame filters that have the same
++priority are executed in unsorted order in that priority slot.  This
++attribute is mandatory.
++@end defvar
++
++@node Frame Decorator API
++@subsubsection Decorating Frames.
++@cindex frame decorator api
++
++Frame decorators are sister objects to frame filters (@pxref{Frame
++Filter API}).  Frame decorators are applied by a frame filter and can
++only be used in conjunction with frame filters.
++
++The purpose of a frame decorator is to customize the printed content
++of each @code{gdb.Frame} in commands where frame filters are executed.
++This concept is called decorating a frame.  Frame decorators decorate
++a @code{gdb.Frame} with Python code contained within each API call.
++This separates the actual data contained in a @code{gdb.Frame} from
++the decorated data produced by a frame decorator.  This abstraction is
++necessary to maintain integrity of the data contained in each
++@code{gdb.Frame}.
++
++Frame decorators have a mandatory interface, defined below.
++
++@value{GDBN} already contains a frame decorator called
++@code{FrameDecorator}.  This contains substantial amounts of
++boilerplate code to decorate the content of a @code{gdb.Frame}.  It is
++recommended that other frame decorators inherit and extend this
++object, and only to override the methods needed.
++
++@defun FrameDecorator.elided (self)
++
++The @code{elided} method groups frames together in a hierarchical
++system.  An example would be an interpreter, where multiple low-level
++frames make up a single call in the interpreted language.  In this
++example, the frame filter would elide the low-level frames and present
++a single high-level frame, representing the call in the interpreted
++language, to the user.
++
++The @code{elided} function must return an iterable and this iterable
++must contain the frames that are being elided wrapped in a suitable
++frame decorator.  If no frames are being elided this function may
++return an empty iterable, or @code{None}.  Elided frames are indented
++from normal frames in a @code{CLI} backtrace, or in the case of
++@code{GDB/MI}, are placed in the @code{children} field of the eliding
++frame.
++
++It is the frame filter's task to also filter out the elided frames from
++the source iterator.  This will avoid printing the frame twice.
++@end defun
++
++@defun FrameDecorator.function (self)
++
++This method returns the name of the function in the frame that is to
++be printed.
++
++This method must return a Python string describing the function, or
++@code{None}.
++
++If this function returns @code{None}, @value{GDBN} will not print any
++data for this field.
++@end defun
++
++@defun FrameDecorator.address (self)
++
++This method returns the address of the frame that is to be printed.
++
++This method must return a Python numeric integer type of sufficient
++size to describe the address of the frame, or @code{None}.
++
++If this function returns a @code{None}, @value{GDBN} will not print
++any data for this field.
++@end defun
++
++@defun FrameDecorator.filename (self)
++
++This method returns the filename and path associated with this frame.
++
++This method must return a Python string containing the filename and
++the path to the object file backing the frame, or @code{None}.
++
++If this function returns a @code{None}, @value{GDBN} will not print
++any data for this field.
++@end defun
++
++@defun FrameDecorator.line (self):
++
++This method returns the line number associated with the current
++position within the function addressed by this frame.
++
++This method must return a Python integer type, or @code{None}.
++
++If this function returns a @code{None}, @value{GDBN} will not print
++any data for this field.
++@end defun
++
++@defun FrameDecorator.frame_args (self)
++@anchor{frame_args}
++
++This method must return an iterable, or @code{None}.  Returning an
++empty iterable, or @code{None} means frame arguments will not be
++printed for this frame.  This iterable must contain objects that
++implement two methods, described here.
++
++This object must implement a @code{argument} method which takes a
++single @code{self} parameter and must return a @code{gdb.Symbol}
++(@pxref{Symbols In Python}), or a Python string.  The object must also
++implement a @code{value} method which takes a single @code{self}
++parameter and must return a @code{gdb.Value} (@pxref{Values From
++Inferior}), a Python value, or @code{None}.  If the @code{value}
++method returns @code{None}, and the @code{argument} method returns a
++@code{gdb.Symbol}, @value{GDBN} will look-up and print the value of
++the @code{gdb.Symbol} automatically.
++
++A brief example:
++
++@smallexample
++class SymValueWrapper():
++
++    def __init__(self, symbol, value):
++        self.sym = symbol
++        self.val = value
++
++    def value(self):
++        return self.val
++
++    def symbol(self):
++        return self.sym
++
++class SomeFrameDecorator()
++...
++...
++    def frame_args(self):
++        args = []
++        try:
++            block = self.inferior_frame.block()
++        except:
++            return None
++
++        # Iterate over all symbols in a block.  Only add
++        # symbols that are arguments.
++        for sym in block:
++            if not sym.is_argument:
++                continue
++            args.append(SymValueWrapper(sym,None))
++
++        # Add example synthetic argument.
++        args.append(SymValueWrapper(``foo'', 42))
++
++        return args
++@end smallexample
++@end defun
++
++@defun FrameDecorator.frame_locals (self)
++
++This method must return an iterable or @code{None}.  Returning an
++empty iterable, or @code{None} means frame local arguments will not be
++printed for this frame.
++
++The object interface, the description of the various strategies for
++reading frame locals, and the example are largely similar to those
++described in the @code{frame_args} function, (@pxref{frame_args,,The
++frame filter frame_args function}).  Below is a modified example:
++
++@smallexample
++class SomeFrameDecorator()
++...
++...
++    def frame_locals(self):
++        vars = []
++        try:
++            block = self.inferior_frame.block()
++        except:
++            return None
++
++        # Iterate over all symbols in a block.  Add all
++        # symbols, except arguments.
++        for sym in block:
++            if sym.is_argument:
++                continue
++            vars.append(SymValueWrapper(sym,None))
++
++        # Add an example of a synthetic local variable.
++        vars.append(SymValueWrapper(``bar'', 99))
++
++        return vars
++@end smallexample
++@end defun
++
++@defun FrameDecorator.inferior_frame (self):
++
++This method must return the underlying @code{gdb.Frame} that this
++frame decorator is decorating.  @value{GDBN} requires the underlying
++frame for internal frame information to determine how to print certain
++values when printing a frame.
++@end defun
++
++@node Writing a Frame Filter
++@subsubsection Writing a Frame Filter
++@cindex writing a frame filter
++
++There are three basic elements that a frame filter must implement: it
++must correctly implement the documented interface (@pxref{Frame Filter
++API}), it must register itself with @value{GDBN}, and finally, it must
++decide if it is to work on the data provided by @value{GDBN}.  In all
++cases, whether it works on the iterator or not, each frame filter must
++return an iterator.  A bare-bones frame filter follows the pattern in
++the following example.
++
++@smallexample
++import gdb
++
++class FrameFilter():
++
++    def __init__(self):
++        # Frame filter attribute creation.
++        #
++        # 'name' is the name of the filter that GDB will display.
++        #
++        # 'priority' is the priority of the filter relative to other
++        # filters.
++        #
++        # 'enabled' is a boolean that indicates whether this filter is
++        # enabled and should be executed.
++
++        self.name = "Foo"
++        self.priority = 100
++        self.enabled = True
++
++        # Register this frame filter with the global frame_filters
++        # dictionary.
++        gdb.frame_filters[self.name] = self
++
++    def filter(self, frame_iter):
++        # Just return the iterator.
++        return frame_iter
++@end smallexample
++
++The frame filter in the example above implements the three
++requirements for all frame filters.  It implements the API, self
++registers, and makes a decision on the iterator (in this case, it just
++returns the iterator untouched).
++
++The first step is attribute creation and assignment, and as shown in
++the comments the filter assigns the following attributes:  @code{name},
++@code{priority} and whether the filter should be enabled with the
++@code{enabled} attribute.
++
++The second step is registering the frame filter with the dictionary or
++dictionaries that the frame filter has interest in.  As shown in the
++comments, this filter just registers itself with the global dictionary
++@code{gdb.frame_filters}.  As noted earlier, @code{gdb.frame_filters}
++is a dictionary that is initialized in the @code{gdb} module when
++@value{GDBN} starts.  What dictionary a filter registers with is an
++important consideration.  Generally, if a filter is specific to a set
++of code, it should be registered either in the @code{objfile} or
++@code{progspace} dictionaries as they are specific to the program
++currently loaded in @value{GDBN}.  The global dictionary is always
++present in @value{GDBN} and is never unloaded.  Any filters registered
++with the global dictionary will exist until @value{GDBN} exits.  To
++avoid filters that may conflict, it is generally better to register
++frame filters against the dictionaries that more closely align with
++the usage of the filter currently in question.  @xref{Python
++Auto-loading}, for further information on auto-loading Python scripts.
++
++@value{GDBN} takes a hands-off approach to frame filter registration,
++therefore it is the frame filter's responsibility to ensure
++registration has occurred, and that any exceptions are handled
++appropriately.  In particular, you may wish to handle exceptions
++relating to Python dictionary key uniqueness.  It is mandatory that
++the dictionary key is the same as frame filter's @code{name}
++attribute.  When a user manages frame filters (@pxref{Frame Filter
++Management}), the names @value{GDBN} will display are those contained
++in the @code{name} attribute.
++
++The final step of this example is the implementation of the
++@code{filter} method.  As shown in the example comments, we define the
++@code{filter} method and note that the method must take an iterator,
++and also must return an iterator.  In this bare-bones example, the
++frame filter is not very useful as it just returns the iterator
++untouched.  However this is a valid operation for frame filters that
++have the @code{enabled} attribute set, but decide not to operate on
++any frames.
++
++In the next example, the frame filter operates on all frames and
++utilizes a frame decorator to perform some work on the frames.
++@xref{Frame Decorator API}, for further information on the frame
++decorator interface.
++
++This example works on inlined frames.  It highlights frames which are
++inlined by tagging them with an ``[inlined]'' tag.  By applying a
++frame decorator to all frames with the Python @code{itertools imap}
++method, the example defers actions to the frame decorator.  Frame
++decorators are only processed when @value{GDBN} prints the backtrace.
++
++This introduces a new decision making topic: whether to perform
++decision making operations at the filtering step, or at the printing
++step.  In this example's approach, it does not perform any filtering
++decisions at the filtering step beyond mapping a frame decorator to
++each frame.  This allows the actual decision making to be performed
++when each frame is printed.  This is an important consideration, and
++well worth reflecting upon when designing a frame filter.  An issue
++that frame filters should avoid is unwinding the stack if possible.
++Some stacks can run very deep, into the tens of thousands in some
++cases.  To search every frame to determine if it is inlined ahead of
++time may be too expensive at the filtering step.  The frame filter
++cannot know how many frames it has to iterate over, and it would have
++to iterate through them all.  This ends up duplicating effort as
++@value{GDBN} performs this iteration when it prints the frames.
++
++In this example decision making can be deferred to the printing step.
++As each frame is printed, the frame decorator can examine each frame
++in turn when @value{GDBN} iterates.  From a performance viewpoint,
++this is the most appropriate decision to make as it avoids duplicating
++the effort that the printing step would undertake anyway.  Also, if
++there are many frame filters unwinding the stack during filtering, it
++can substantially delay the printing of the backtrace which will
++result in large memory usage, and a poor user experience.
++
++@smallexample
++class InlineFilter():
++
++    def __init__(self):
++        self.name = "InlinedFrameFilter"
++        self.priority = 100
++        self.enabled = True
++        gdb.frame_filters[self.name] = self
++
++    def filter(self, frame_iter):
++        frame_iter = itertools.imap(InlinedFrameDecorator,
++                                    frame_iter)
++        return frame_iter
++@end smallexample
++
++This frame filter is somewhat similar to the earlier example, except
++that the @code{filter} method applies a frame decorator object called
++@code{InlinedFrameDecorator} to each element in the iterator.  The
++@code{imap} Python method is light-weight.  It does not proactively
++iterate over the iterator, but rather creates a new iterator which
++wraps the existing one.
++
++Below is the frame decorator for this example.
++
++@smallexample
++class InlinedFrameDecorator(FrameDecorator):
++
++    def __init__(self, fobj):
++        super(InlinedFrameDecorator, self).__init__(fobj)
++
++    def function(self):
++        frame = fobj.inferior_frame()
++        name = str(frame.name())
++
++        if frame.type() == gdb.INLINE_FRAME:
++            name = name + " [inlined]"
++
++        return name
++@end smallexample
++
++This frame decorator only defines and overrides the @code{function}
++method.  It lets the supplied @code{FrameDecorator}, which is shipped
++with @value{GDBN}, perform the other work associated with printing
++this frame.
++
++The combination of these two objects create this output from a
++backtrace:
++
++@smallexample
++#0  0x004004e0 in bar () at inline.c:11
++#1  0x00400566 in max [inlined] (b=6, a=12) at inline.c:21
++#2  0x00400566 in main () at inline.c:31
++@end smallexample
++
++So in the case of this example, a frame decorator is applied to all
++frames, regardless of whether they may be inlined or not.  As
++@value{GDBN} iterates over the iterator produced by the frame filters,
++@value{GDBN} executes each frame decorator which then makes a decision
++on what to print in the @code{function} callback.  Using a strategy
++like this is a way to defer decisions on the frame content to printing
++time.
++
++@subheading Eliding Frames
++
++It might be that the above example is not desirable for representing
++inlined frames, and a hierarchical approach may be preferred.  If we
++want to hierarchically represent frames, the @code{elided} frame
++decorator interface might be preferable.
++
++This example approaches the issue with the @code{elided} method.  This
++example is quite long, but very simplistic.  It is out-of-scope for
++this section to write a complete example that comprehensively covers
++all approaches of finding and printing inlined frames.  However, this
++example illustrates the approach an author might use.
++
++This example comprises of three sections.
++
++@smallexample
++class InlineFrameFilter():
++
++    def __init__(self):
++        self.name = "InlinedFrameFilter"
++        self.priority = 100
++        self.enabled = True
++        gdb.frame_filters[self.name] = self
++
++    def filter(self, frame_iter):
++        return ElidingInlineIterator(frame_iter)
++@end smallexample
++
++This frame filter is very similar to the other examples.  The only
++difference is this frame filter is wrapping the iterator provided to
++it (@code{frame_iter}) with a custom iterator called
++@code{ElidingInlineIterator}.  This again defers actions to when
++@value{GDBN} prints the backtrace, as the iterator is not traversed
++until printing.
++
++The iterator for this example is as follows.  It is in this section of
++the example where decisions are made on the content of the backtrace.
++
++@smallexample
++class ElidingInlineIterator:
++    def __init__(self, ii):
++        self.input_iterator = ii
++
++    def __iter__(self):
++        return self
++
++    def next(self):
++        frame = next(self.input_iterator)
++
++        if frame.inferior_frame().type() != gdb.INLINE_FRAME:
++            return frame
++
++        try:
++            eliding_frame = next(self.input_iterator)
++        except StopIteration:
++            return frame
++        return ElidingFrameDecorator(eliding_frame, [frame])
++@end smallexample
++
++This iterator implements the Python iterator protocol.  When the
++@code{next} function is called (when @value{GDBN} prints each frame),
++the iterator checks if this frame decorator, @code{frame}, is wrapping
++an inlined frame.  If it is not, it returns the existing frame decorator
++untouched.  If it is wrapping an inlined frame, it assumes that the
++inlined frame was contained within the next oldest frame,
++@code{eliding_frame}, which it fetches.  It then creates and returns a
++frame decorator, @code{ElidingFrameDecorator}, which contains both the
++elided frame, and the eliding frame.
++
++@smallexample
++class ElidingInlineDecorator(FrameDecorator):
++
++    def __init__(self, frame, elided_frames):
++        super(ElidingInlineDecorator, self).__init__(frame)
++        self.frame = frame
++        self.elided_frames = elided_frames
++
++    def elided(self):
++        return iter(self.elided_frames)
++@end smallexample
++
++This frame decorator overrides one function and returns the inlined
++frame in the @code{elided} method.  As before it lets
++@code{FrameDecorator} do the rest of the work involved in printing
++this frame.  This produces the following output.
++
++@smallexample
++#0  0x004004e0 in bar () at inline.c:11
++#2  0x00400529 in main () at inline.c:25
++    #1  0x00400529 in max (b=6, a=12) at inline.c:15
++@end smallexample
++
++In that output, @code{max} which has been inlined into @code{main} is
++printed hierarchically.  Another approach would be to combine the
++@code{function} method, and the @code{elided} method to both print a
++marker in the inlined frame, and also show the hierarchical
++relationship.
++
+ @node Inferiors In Python
+ @subsubsection Inferiors In Python
+ @cindex inferiors in Python
+@@ -25245,6 +26036,11 @@ The @code{type_printers} attribute is a
+ @xref{Type Printing API}, for more information.
+ @end defvar
+ 
++@defvar Progspace.frame_filters
++The @code{frame_filters} attribute is a dictionary of frame filter
++objects.  @xref{Frame Filter API}, for more information.
++@end defvar
++
+ @node Objfiles In Python
+ @subsubsection Objfiles In Python
+ 
+@@ -25295,6 +26091,11 @@ The @code{type_printers} attribute is a
+ @xref{Type Printing API}, for more information.
+ @end defvar
+ 
++@defvar Objfile.frame_filters
++The @code{frame_filters} attribute is a dictionary of frame filter
++objects.  @xref{Frame Filter API}, for more information.
++@end defvar
++
+ A @code{gdb.Objfile} object has the following methods:
+ 
+ @defun Objfile.is_valid ()
+@@ -26313,7 +27114,7 @@ No     my-foo-pretty-printers.py
+ When reading an auto-loaded file, @value{GDBN} sets the
+ @dfn{current objfile}.  This is available via the @code{gdb.current_objfile}
+ function (@pxref{Objfiles In Python}).  This can be useful for
+-registering objfile-specific pretty-printers.
++registering objfile-specific pretty-printers and frame-filters.
+ 
+ @menu
+ * objfile-gdb.py file::          The @file{@var{objfile}-gdb.py} file
+@@ -30184,6 +30985,22 @@ Is this going away????
+ @node GDB/MI Stack Manipulation
+ @section @sc{gdb/mi} Stack Manipulation Commands
+ 
++@subheading The @code{-enable-frame-filters} Command
++@findex -enable-frame-filters
++
++@smallexample
++-enable-frame-filters
++@end smallexample
++
++@value{GDBN} allows Python-based frame filters to affect the output of
++the MI commands relating to stack traces.  As there is no way to
++implement this in a fully backward-compatible way, a front end must
++request that this functionality be enabled.
++
++Once enabled, this feature cannot be disabled.
++
++Note that if Python support has not been compiled into @value{GDBN},
++this command will still succeed (and do nothing).
+ 
+ @subheading The @code{-stack-info-frame} Command
+ @findex -stack-info-frame
+@@ -30251,13 +31068,14 @@ For a stack with frame levels 0 through
+ (gdb)
+ @end smallexample
+ 
++@anchor{-stack-list-arguments}
+ @subheading The @code{-stack-list-arguments} Command
+ @findex -stack-list-arguments
+ 
+ @subsubheading Synopsis
+ 
+ @smallexample
+- -stack-list-arguments @var{print-values}
++ -stack-list-arguments [ --no-frame-filters ] @var{print-values}
+     [ @var{low-frame} @var{high-frame} ]
+ @end smallexample
+ 
+@@ -30274,7 +31092,9 @@ If @var{print-values} is 0 or @code{--no
+ the variables; if it is 1 or @code{--all-values}, print also their
+ values; and if it is 2 or @code{--simple-values}, print the name,
+ type and value for simple data types, and the name and type for arrays,
+-structures and unions.
++structures and unions.  If the option @code{--no-frame-filters} is
++supplied, then Python frame filters will not be executed.
++
+ 
+ Use of this command to obtain arguments in a single frame is
+ deprecated in favor of the @samp{-stack-list-variables} command.
+@@ -30345,13 +31165,14 @@ args=[@{name="intarg",value="2"@},
+ @c @subheading -stack-list-exception-handlers
+ 
+ 
++@anchor{-stack-list-frames}
+ @subheading The @code{-stack-list-frames} Command
+ @findex -stack-list-frames
+ 
+ @subsubheading Synopsis
+ 
+ @smallexample
+- -stack-list-frames [ @var{low-frame} @var{high-frame} ]
++ -stack-list-frames [ --no-frame-filters @var{low-frame} @var{high-frame} ]
+ @end smallexample
+ 
+ List the frames currently on the stack.  For each frame it displays the
+@@ -30381,7 +31202,9 @@ levels are between the two arguments (in
+ are equal, it shows the single frame at the corresponding level.  It is
+ an error if @var{low-frame} is larger than the actual number of
+ frames.  On the other hand, @var{high-frame} may be larger than the
+-actual number of frames, in which case only existing frames will be returned.
++actual number of frames, in which case only existing frames will be
++returned.  If the option @code{--no-frame-filters} is supplied, then
++Python frame filters will not be executed.
+ 
+ @subsubheading @value{GDBN} Command
+ 
+@@ -30451,11 +31274,12 @@ Show a single frame:
+ 
+ @subheading The @code{-stack-list-locals} Command
+ @findex -stack-list-locals
++@anchor{-stack-list-locals}
+ 
+ @subsubheading Synopsis
+ 
+ @smallexample
+- -stack-list-locals @var{print-values}
++ -stack-list-locals [ --no-frame-filters ] @var{print-values}
+ @end smallexample
+ 
+ Display the local variable names for the selected frame.  If
+@@ -30466,7 +31290,8 @@ type and value for simple data types, an
+ structures and unions.  In this last case, a frontend can immediately
+ display the value of simple data types and create variable objects for
+ other data types when the user wishes to explore their values in
+-more detail.
++more detail.  If the option @code{--no-frame-filters} is supplied, then
++Python frame filters will not be executed.
+ 
+ This command is deprecated in favor of the
+ @samp{-stack-list-variables} command.
+@@ -30491,13 +31316,14 @@ This command is deprecated in favor of t
+ (gdb)
+ @end smallexample
+ 
++@anchor{-stack-list-variables}
+ @subheading The @code{-stack-list-variables} Command
+ @findex -stack-list-variables
+ 
+ @subsubheading Synopsis
+ 
+ @smallexample
+- -stack-list-variables @var{print-values}
++ -stack-list-variables [ --no-frame-filters ] @var{print-values}
+ @end smallexample
+ 
+ Display the names of local variables and function arguments for the selected frame.  If
+@@ -30505,7 +31331,8 @@ Display the names of local variables and
+ the variables; if it is 1 or @code{--all-values}, print also their
+ values; and if it is 2 or @code{--simple-values}, print the name,
+ type and value for simple data types, and the name and type for arrays,
+-structures and unions.  
++structures and unions.  If the option @code{--no-frame-filters} is
++supplied, then Python frame filters will not be executed.
+ 
+ @subsubheading Example
+ 
+Index: gdb-7.6/gdb/mi/mi-cmd-stack.c
+===================================================================
+--- gdb-7.6.orig/gdb/mi/mi-cmd-stack.c	2013-05-20 22:23:36.748215146 +0200
++++ gdb-7.6/gdb/mi/mi-cmd-stack.c	2013-05-20 22:25:52.111165767 +0200
+@@ -31,6 +31,10 @@
+ #include "language.h"
+ #include "valprint.h"
+ #include "exceptions.h"
++#include "utils.h"
++#include "mi-getopt.h"
++#include "python/python.h"
++#include <ctype.h>
+ 
+ enum what_to_list { locals, arguments, all };
+ 
+@@ -38,6 +42,28 @@ static void list_args_or_locals (enum wh
+ 				 enum print_values values,
+ 				 struct frame_info *fi);
+ 
++/* True if we want to allow Python-based frame filters.  */
++static int frame_filters = 0;
++
++void
++mi_cmd_enable_frame_filters (char *command, char **argv, int argc)
++{
++  if (argc != 0)
++    error (_("-enable-frame-filters: no arguments allowed"));
++  frame_filters = 1;
++}
++
++/* Parse the --no-frame-filters option in commands where we cannot use
++   mi_getopt. */
++static int
++parse_no_frames_option (const char *arg)
++{
++  if (arg && (strcmp (arg, "--no-frame-filters") == 0))
++    return 1;
++
++  return 0;
++}
++
+ /* Print a list of the stack frames.  Args can be none, in which case
+    we want to print the whole backtrace, or a pair of numbers
+    specifying the frame numbers at which to start and stop the
+@@ -52,14 +78,46 @@ mi_cmd_stack_list_frames (char *command,
+   int i;
+   struct cleanup *cleanup_stack;
+   struct frame_info *fi;
++  enum py_bt_status result = PY_BT_ERROR;
++  int raw_arg = 0;
++  int oind = 0;
++  enum opt
++    {
++      NO_FRAME_FILTERS
++    };
++  static const struct mi_opt opts[] =
++    {
++      {"-no-frame-filters", NO_FRAME_FILTERS, 0},
++      { 0, 0, 0 }
++    };
++
++  /* Parse arguments.  In this instance we are just looking for
++     --no-frame-filters.  */
++  while (1)
++    {
++      char *oarg;
++      int opt = mi_getopt ("-stack-list-frames", argc, argv,
++			   opts, &oind, &oarg);
++      if (opt < 0)
++	break;
++      switch ((enum opt) opt)
++	{
++	case NO_FRAME_FILTERS:
++	  raw_arg = oind;
++	  break;
++	}
++    }
+ 
+-  if (argc > 2 || argc == 1)
+-    error (_("-stack-list-frames: Usage: [FRAME_LOW FRAME_HIGH]"));
++  /* After the last option is parsed, there should either be low -
++     high range, or no further arguments.  */
++  if ((argc - oind != 0) && (argc - oind != 2))
++    error (_("-stack-list-frames: Usage: [--no-frame-filters] [FRAME_LOW FRAME_HIGH]"));
+ 
+-  if (argc == 2)
++  /* If there is a range, set it.  */
++  if (argc - oind == 2)
+     {
+-      frame_low = atoi (argv[0]);
+-      frame_high = atoi (argv[1]);
++      frame_low = atoi (argv[0 + oind]);
++      frame_high = atoi (argv[1 + oind]);
+     }
+   else
+     {
+@@ -81,16 +139,37 @@ mi_cmd_stack_list_frames (char *command,
+ 
+   cleanup_stack = make_cleanup_ui_out_list_begin_end (current_uiout, "stack");
+ 
+-  /* Now let's print the frames up to frame_high, or until there are
+-     frames in the stack.  */
+-  for (;
+-       fi && (i <= frame_high || frame_high == -1);
+-       i++, fi = get_prev_frame (fi))
++  if (! raw_arg && frame_filters)
+     {
+-      QUIT;
+-      /* Print the location and the address always, even for level 0.
+-         If args is 0, don't print the arguments.  */
+-      print_frame_info (fi, 1, LOC_AND_ADDRESS, 0 /* args */ );
++      int flags = PRINT_LEVEL | PRINT_FRAME_INFO;
++      int py_frame_low = frame_low;
++
++      /* 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 (get_current_frame (), flags,
++				   NO_VALUES,  current_uiout,
++				   py_frame_low, frame_high);
++    }
++
++  /* Run the inbuilt backtrace if there are no filters registered, or
++     if "--no-frame-filters" has been specified from the command.  */
++  if (! frame_filters || raw_arg  || result == PY_BT_NO_FILTERS)
++    {
++      /* Now let's print the frames up to frame_high, or until there are
++	 frames in the stack.  */
++      for (;
++	   fi && (i <= frame_high || frame_high == -1);
++	   i++, fi = get_prev_frame (fi))
++	{
++	  QUIT;
++	  /* Print the location and the address always, even for level 0.
++	     If args is 0, don't print the arguments.  */
++	  print_frame_info (fi, 1, LOC_AND_ADDRESS, 0 /* args */ );
++	}
+     }
+ 
+   do_cleanups (cleanup_stack);
+@@ -147,13 +226,34 @@ void
+ mi_cmd_stack_list_locals (char *command, char **argv, int argc)
+ {
+   struct frame_info *frame;
++  int raw_arg = 0;
++  enum py_bt_status result = PY_BT_ERROR;
++  int print_value;
++
++  if (argc > 0)
++    raw_arg = parse_no_frames_option (argv[0]);
++
++  if (argc < 1 || argc > 2 || (argc == 2 && ! raw_arg)
++      || (argc == 1 && raw_arg))
++    error (_("-stack-list-locals: Usage: [--no-frame-filters] PRINT_VALUES"));
+ 
+-  if (argc != 1)
+-    error (_("-stack-list-locals: Usage: PRINT_VALUES"));
+-
+-   frame = get_selected_frame (NULL);
++  frame = get_selected_frame (NULL);
++  print_value = parse_print_values (argv[raw_arg]);
+ 
+-   list_args_or_locals (locals, parse_print_values (argv[0]), frame);
++   if (! raw_arg && frame_filters)
++     {
++       int flags = PRINT_LEVEL | PRINT_LOCALS;
++
++       result = apply_frame_filter (frame, flags, print_value,
++				    current_uiout, 0, 0);
++     }
++
++   /* Run the inbuilt backtrace if there are no filters registered, or
++      if "--no-frame-filters" has been specified from the command.  */
++   if (! frame_filters || raw_arg  || result == PY_BT_NO_FILTERS)
++     {
++       list_args_or_locals (locals, print_value, frame);
++     }
+ }
+ 
+ /* Print a list of the arguments for the current frame.  With argument
+@@ -170,15 +270,20 @@ mi_cmd_stack_list_args (char *command, c
+   struct cleanup *cleanup_stack_args;
+   enum print_values print_values;
+   struct ui_out *uiout = current_uiout;
++  int raw_arg = 0;
++  enum py_bt_status result = PY_BT_ERROR;
+ 
+-  if (argc < 1 || argc > 3 || argc == 2)
+-    error (_("-stack-list-arguments: Usage: "
+-	     "PRINT_VALUES [FRAME_LOW FRAME_HIGH]"));
++  if (argc > 0)
++    raw_arg = parse_no_frames_option (argv[0]);
+ 
+-  if (argc == 3)
++  if (argc < 1 || (argc > 3 && ! raw_arg) || (argc == 2 && ! raw_arg))
++    error (_("-stack-list-arguments: Usage: " \
++	     "[--no-frame-filters] PRINT_VALUES [FRAME_LOW FRAME_HIGH]"));
++
++  if (argc >= 3)
+     {
+-      frame_low = atoi (argv[1]);
+-      frame_high = atoi (argv[2]);
++      frame_low = atoi (argv[1 + raw_arg]);
++      frame_high = atoi (argv[2 + raw_arg]);
+     }
+   else
+     {
+@@ -188,7 +293,7 @@ mi_cmd_stack_list_args (char *command, c
+       frame_high = -1;
+     }
+ 
+-  print_values = parse_print_values (argv[0]);
++  print_values = parse_print_values (argv[raw_arg]);
+ 
+   /* Let's position fi on the frame at which to start the
+      display. Could be the innermost frame if the whole stack needs
+@@ -203,21 +308,41 @@ mi_cmd_stack_list_args (char *command, c
+   cleanup_stack_args
+     = make_cleanup_ui_out_list_begin_end (uiout, "stack-args");
+ 
+-  /* Now let's print the frames up to frame_high, or until there are
+-     frames in the stack.  */
+-  for (;
+-       fi && (i <= frame_high || frame_high == -1);
+-       i++, fi = get_prev_frame (fi))
++  if (! raw_arg && frame_filters)
+     {
+-      struct cleanup *cleanup_frame;
++      int flags = PRINT_LEVEL | PRINT_ARGS;
++      int py_frame_low = frame_low;
+ 
+-      QUIT;
+-      cleanup_frame = make_cleanup_ui_out_tuple_begin_end (uiout, "frame");
+-      ui_out_field_int (uiout, "level", i);
+-      list_args_or_locals (arguments, print_values, fi);
+-      do_cleanups (cleanup_frame);
++      /* 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 (get_current_frame (), flags,
++				   print_values, current_uiout,
++				   py_frame_low, frame_high);
+     }
+ 
++     /* Run the inbuilt backtrace if there are no filters registered, or
++      if "--no-frame-filters" has been specified from the command.  */
++   if (! frame_filters || raw_arg  || result == PY_BT_NO_FILTERS)
++     {
++      /* Now let's print the frames up to frame_high, or until there are
++	 frames in the stack.  */
++      for (;
++	   fi && (i <= frame_high || frame_high == -1);
++	   i++, fi = get_prev_frame (fi))
++	{
++	  struct cleanup *cleanup_frame;
++
++	  QUIT;
++	  cleanup_frame = make_cleanup_ui_out_tuple_begin_end (uiout, "frame");
++	  ui_out_field_int (uiout, "level", i);
++	  list_args_or_locals (arguments, print_values, fi);
++	  do_cleanups (cleanup_frame);
++	}
++    }
+   do_cleanups (cleanup_stack_args);
+ }
+ 
+@@ -230,13 +355,35 @@ void
+ mi_cmd_stack_list_variables (char *command, char **argv, int argc)
+ {
+   struct frame_info *frame;
++  int raw_arg = 0;
++  enum py_bt_status result = PY_BT_ERROR;
++  int print_value;
++
++  if (argc > 0)
++    raw_arg = parse_no_frames_option (argv[0]);
++
++  if (argc < 1 || argc > 2 || (argc == 2 && ! raw_arg)
++      || (argc == 1 && raw_arg))
++    error (_("-stack-list-variables: Usage: " \
++	     "[--no-frame-filters] PRINT_VALUES"));
+ 
+-  if (argc != 1)
+-    error (_("Usage: PRINT_VALUES"));
+-
+-  frame = get_selected_frame (NULL);
++   frame = get_selected_frame (NULL);
++   print_value = parse_print_values (argv[raw_arg]);
+ 
+-  list_args_or_locals (all, parse_print_values (argv[0]), frame);
++   if (! raw_arg && frame_filters)
++     {
++       int flags = PRINT_LEVEL | PRINT_ARGS | PRINT_LOCALS;
++
++       result = apply_frame_filter (frame, flags, print_value,
++				    current_uiout, 0, 0);
++     }
++
++   /* Run the inbuilt backtrace if there are no filters registered, or
++      if "--no-frame-filters" has been specified from the command.  */
++   if (! frame_filters || raw_arg  || result == PY_BT_NO_FILTERS)
++     {
++       list_args_or_locals (all, print_value, frame);
++     }
+ }
+ 
+ /* Print single local or argument.  ARG must be already read in.  For
+Index: gdb-7.6/gdb/mi/mi-cmds.c
+===================================================================
+--- gdb-7.6.orig/gdb/mi/mi-cmds.c	2013-05-20 22:23:36.748215146 +0200
++++ gdb-7.6/gdb/mi/mi-cmds.c	2013-05-20 22:25:52.111165767 +0200
+@@ -86,6 +86,7 @@ static struct mi_cmd mi_cmds[] =
+ 		 mi_cmd_data_write_register_values),
+   DEF_MI_CMD_MI ("enable-timings", mi_cmd_enable_timings),
+   DEF_MI_CMD_MI ("enable-pretty-printing", mi_cmd_enable_pretty_printing),
++  DEF_MI_CMD_MI ("enable-frame-filters", mi_cmd_enable_frame_filters),
+   DEF_MI_CMD_MI ("environment-cd", mi_cmd_env_cd),
+   DEF_MI_CMD_MI ("environment-directory", mi_cmd_env_dir),
+   DEF_MI_CMD_MI ("environment-path", mi_cmd_env_path),
+Index: gdb-7.6/gdb/mi/mi-cmds.h
+===================================================================
+--- gdb-7.6.orig/gdb/mi/mi-cmds.h	2013-05-20 22:23:36.748215146 +0200
++++ gdb-7.6/gdb/mi/mi-cmds.h	2013-05-20 22:25:52.111165767 +0200
+@@ -118,6 +118,7 @@ extern mi_cmd_argv_ftype mi_cmd_var_show
+ extern mi_cmd_argv_ftype mi_cmd_var_show_format;
+ extern mi_cmd_argv_ftype mi_cmd_var_update;
+ extern mi_cmd_argv_ftype mi_cmd_enable_pretty_printing;
++extern mi_cmd_argv_ftype mi_cmd_enable_frame_filters;
+ extern mi_cmd_argv_ftype mi_cmd_var_set_update_range;
+ 
+ /* Description of a single command.  */
+Index: gdb-7.6/gdb/python/py-framefilter.c
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ gdb-7.6/gdb/python/py-framefilter.c	2013-05-20 22:26:53.029143068 +0200
+@@ -0,0 +1,1528 @@
++/* Python frame filters
++
++   Copyright (C) 2013 Free Software Foundation, Inc.
++
++   This file is part of GDB.
++
++   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/>.  */
++
++#include "defs.h"
++#include "objfiles.h"
++#include "symtab.h"
++#include "language.h"
++#include "exceptions.h"
++#include "arch-utils.h"
++#include "python.h"
++#include "ui-out.h"
++#include "valprint.h"
++#include "annotate.h"
++#include "hashtab.h"
++#include "demangle.h"
++#include "mi/mi-cmds.h"
++#include "python-internal.h"
++
++enum mi_print_types
++{
++  MI_PRINT_ARGS,
++  MI_PRINT_LOCALS
++};
++
++/* Helper  function  to  extract  a  symbol, a  name  and  a  language
++   definition from a Python object that conforms to the "Symbol Value"
++   interface.  OBJ  is the Python  object to extract the  values from.
++   NAME is a  pass-through argument where the name of  the symbol will
++   be written.  NAME is allocated in  this function, but the caller is
++   responsible for clean up.  SYM is a pass-through argument where the
++   symbol will be written.  In the case of the API returning a string,
++   this will be set to NULL.  LANGUAGE is also a pass-through argument
++   denoting the language attributed to the Symbol.  In the case of SYM
++   being  NULL, this  will be  set to  the current  language.  Returns
++   PY_BT_ERROR on error with the appropriate Python exception set, and
++   PY_BT_OK on success.  */
++
++static enum py_bt_status
++extract_sym (PyObject *obj, char **name, struct symbol **sym,
++	     const struct language_defn **language)
++{
++  PyObject *result = PyObject_CallMethod (obj, "symbol", NULL);
++
++  if (result == NULL)
++    return PY_BT_ERROR;
++
++  /* For 'symbol' callback, the function can return a symbol or a
++     string.  */
++  if (gdbpy_is_string (result))
++    {
++      *name = python_string_to_host_string (result);
++      Py_DECREF (result);
++
++      if (*name == NULL)
++	return PY_BT_ERROR;
++      /* If the API returns a string (and not a symbol), then there is
++	no symbol derived language available and the frame filter has
++	either overridden the symbol with a string, or supplied a
++	entirely synthetic symbol/value pairing.  In that case, use
++	python_language.  */
++      *language = python_language;
++      *sym = NULL;
++    }
++  else
++    {
++      /* This type checks 'result' during the conversion so we
++	 just call it unconditionally and check the return.  */
++      *sym = symbol_object_to_symbol (result);
++
++      Py_DECREF (result);
++
++      if (*sym == NULL)
++	{
++	  PyErr_SetString (PyExc_RuntimeError,
++			   _("Unexpected value.  Expecting a "
++			     "gdb.Symbol or a Python string."));
++	  return PY_BT_ERROR;
++	}
++
++      /* Duplicate the symbol name, so the caller has consistency
++	 in garbage collection.  */
++      *name = xstrdup (SYMBOL_PRINT_NAME (*sym));
++
++      /* If a symbol is specified attempt to determine the language
++	 from the symbol.  If mode is not "auto", then the language
++	 has been explicitly set, use that.  */
++      if (language_mode == language_mode_auto)
++	*language = language_def (SYMBOL_LANGUAGE (*sym));
++      else
++	*language = current_language;
++    }
++
++  return PY_BT_OK;
++}
++
++/* Helper function to extract a value from an object that conforms to
++   the "Symbol Value" interface.  OBJ is the Python object to extract
++   the value from.  VALUE is a pass-through argument where the value
++   will be written.  If the object does not have the value attribute,
++   or provides the Python None for a value, VALUE will be set to NULL
++   and this function will return as successful.  Returns PY_BT_ERROR
++   on error with the appropriate Python exception set, and PY_BT_OK on
++   success.  */
++
++static enum py_bt_status
++extract_value (PyObject *obj, struct value **value)
++{
++  if (PyObject_HasAttrString (obj, "value"))
++    {
++      PyObject *vresult = PyObject_CallMethod (obj, "value", NULL);
++
++      if (vresult == NULL)
++	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
++	 value.  */
++      if (vresult == Py_None)
++	{
++	  Py_DECREF (vresult);
++	  *value = NULL;
++	  return PY_BT_OK;
++	}
++      else
++	{
++	  *value = convert_value_from_python (vresult);
++	  Py_DECREF (vresult);
++
++	  if (*value == NULL)
++	    return PY_BT_ERROR;
++
++	  return PY_BT_OK;
++	}
++    }
++  else
++    *value = NULL;
++
++  return PY_BT_OK;
++}
++
++/* MI prints only certain values according to the type of symbol and
++   also what the user has specified.  SYM is the symbol to check, and
++   MI_PRINT_TYPES is an enum specifying what the user wants emitted
++   for the MI command in question.  */
++static int
++mi_should_print (struct symbol *sym, enum mi_print_types type)
++{
++  int print_me = 0;
++
++  switch (SYMBOL_CLASS (sym))
++    {
++    default:
++    case LOC_UNDEF:	/* catches errors        */
++    case LOC_CONST:	/* constant              */
++    case LOC_TYPEDEF:	/* local typedef         */
++    case LOC_LABEL:	/* local label           */
++    case LOC_BLOCK:	/* local function        */
++    case LOC_CONST_BYTES:	/* loc. byte seq.        */
++    case LOC_UNRESOLVED:	/* unresolved static     */
++    case LOC_OPTIMIZED_OUT:	/* optimized out         */
++      print_me = 0;
++      break;
++
++    case LOC_ARG:	/* argument              */
++    case LOC_REF_ARG:	/* reference arg         */
++    case LOC_REGPARM_ADDR:	/* indirect register arg */
++    case LOC_LOCAL:	/* stack local           */
++    case LOC_STATIC:	/* static                */
++    case LOC_REGISTER:	/* register              */
++    case LOC_COMPUTED:	/* computed location     */
++      if (type == MI_PRINT_LOCALS)
++	print_me = ! SYMBOL_IS_ARGUMENT (sym);
++      else
++	print_me = SYMBOL_IS_ARGUMENT (sym);
++    }
++  return print_me;
++}
++
++/* Helper function which outputs a type name extracted from VAL to a
++   "type" field in the output stream OUT.  OUT is the ui-out structure
++   the type name will be output too, and VAL is the value that the
++   type will be extracted from.  Returns PY_BT_ERROR on error, with
++   any GDB exceptions converted to a Python exception, or PY_BT_OK on
++   success.  */
++
++static enum py_bt_status
++py_print_type (struct ui_out *out, struct value *val)
++{
++  volatile struct gdb_exception except;
++
++  TRY_CATCH (except, RETURN_MASK_ALL)
++    {
++      struct type *type;
++      struct ui_file *stb;
++      struct cleanup *cleanup;
++
++      stb = mem_fileopen ();
++      cleanup = make_cleanup_ui_file_delete (stb);
++      type = check_typedef (value_type (val));
++      type_print (value_type (val), "", stb, -1);
++      ui_out_field_stream (out, "type", stb);
++      do_cleanups (cleanup);
++    }
++  if (except.reason < 0)
++    {
++      gdbpy_convert_exception (except);
++      return PY_BT_ERROR;
++    }
++
++  return PY_BT_OK;
++}
++
++/* Helper function which outputs a value 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, ARGS_TYPE is an enumerator 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, or PY_BT_OK on
++   success. */
++
++static enum py_bt_status
++py_print_value (struct ui_out *out, struct value *val,
++		const struct value_print_options *opts,
++		int indent,
++		enum py_frame_args args_type,
++		const struct language_defn *language)
++{
++  int should_print = 0;
++  volatile struct gdb_exception except;
++  int local_indent = (4 * indent);
++
++  /* Never set an indent level for common_val_print if MI.  */
++  if (ui_out_is_mi_like_p (out))
++    local_indent = 0;
++
++  /* MI does not print certain values, differentiated by type,
++     depending on what ARGS_TYPE indicates.  Test type against option.
++     For CLI print all values.  */
++  if (args_type == MI_PRINT_SIMPLE_VALUES
++      || args_type == MI_PRINT_ALL_VALUES)
++    {
++      struct type *type = NULL;
++
++      TRY_CATCH (except, RETURN_MASK_ALL)
++	{
++	  type = check_typedef (value_type (val));
++	}
++      if (except.reason < 0)
++	{
++	  gdbpy_convert_exception (except);
++	  return PY_BT_ERROR;
++	}
++
++      if (args_type == MI_PRINT_ALL_VALUES)
++	should_print = 1;
++      else if (args_type == MI_PRINT_SIMPLE_VALUES
++	       && TYPE_CODE (type) != TYPE_CODE_ARRAY
++	       && TYPE_CODE (type) != TYPE_CODE_STRUCT
++	       && TYPE_CODE (type) != TYPE_CODE_UNION)
++	should_print = 1;
++    }
++  else if (args_type != NO_VALUES)
++    should_print = 1;
++
++  if (should_print)
++    {
++      TRY_CATCH (except, RETURN_MASK_ALL)
++	{
++	  struct ui_file *stb;
++	  struct cleanup *cleanup;
++
++	  stb = mem_fileopen ();
++	  cleanup = make_cleanup_ui_file_delete (stb);
++	  common_val_print (val, stb, indent, opts, language);
++	  ui_out_field_stream (out, "value", stb);
++	  do_cleanups (cleanup);
++	}
++      if (except.reason < 0)
++	{
++	  gdbpy_convert_exception (except);
++	  return PY_BT_ERROR;
++	}
++    }
++
++  return PY_BT_OK;
++}
++
++/* Helper function to call a Python method and extract an iterator
++   from the result.  If the function returns anything but an iterator
++   the exception is preserved and NULL is returned.  FILTER is the
++   Python object to call, and FUNC is the name of the method.  Returns
++   a PyObject, or NULL on error with the appropriate exception set.
++   This function can return an iterator, or NULL.  */
++
++static PyObject *
++get_py_iter_from_func (PyObject *filter, char *func)
++{
++  if (PyObject_HasAttrString (filter, func))
++    {
++      PyObject *result = PyObject_CallMethod (filter, func, NULL);
++
++      if (result != NULL)
++	{
++	  if (result == Py_None)
++	    {
++	      return result;
++	    }
++	  else
++	    {
++	      PyObject *iterator = PyObject_GetIter (result);
++
++	      Py_DECREF (result);
++	      return iterator;
++	    }
++	}
++    }
++  else
++    Py_RETURN_NONE;
++
++  return NULL;
++}
++
++/*  Helper function to output a single frame argument and value to an
++    output stream.  This function will account for entry values if the
++    FV parameter is populated, the frame argument has entry values
++    associated with them, and the appropriate "set entry-value"
++    options are set.  Will output in CLI or MI like format depending
++    on the type of output stream detected.  OUT is the output stream,
++    SYM_NAME is the name of the symbol.  If SYM_NAME is populated then
++    it must have an accompanying value in the parameter FV.  FA is a
++    frame argument structure.  If FA is populated, both SYM_NAME and
++    FV are ignored.  OPTS contains the value printing options,
++    ARGS_TYPE is an enumerator 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.  Returns PY_BT_ERROR on error, with any GDB exceptions
++    converted to a Python exception, or PY_BT_OK on success.  */
++
++static enum py_bt_status
++py_print_single_arg (struct ui_out *out,
++		     const char *sym_name,
++		     struct frame_arg *fa,
++		     struct value *fv,
++		     const struct value_print_options *opts,
++		     enum py_frame_args args_type,
++		     int print_args_field,
++		     const struct language_defn *language)
++{
++  struct value *val;
++  volatile struct gdb_exception except;
++
++  if (fa != NULL)
++    {
++      language = language_def (SYMBOL_LANGUAGE (fa->sym));
++      val = fa->val;
++    }
++  else
++    val = fv;
++
++  TRY_CATCH (except, RETURN_MASK_ALL)
++    {
++      struct cleanup *cleanups = make_cleanup (null_cleanup, NULL);
++
++      /*  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.  The
++      exception is -stack-list-variables which emits an ARGS="1" field
++      if the value is a frame argument.  This is denoted in this
++      function with PRINT_ARGS_FIELD which is flag from the caller to
++      emit the ARGS field.  */
++      if (ui_out_is_mi_like_p (out))
++	{
++	  if (print_args_field || args_type != NO_VALUES)
++	    make_cleanup_ui_out_tuple_begin_end (out, NULL);
++	}
++
++      annotate_arg_begin ();
++
++      /* If frame argument is populated, check for entry-values and the
++	 entry value options.  */
++      if (fa != NULL)
++	{
++	  struct ui_file *stb;
++
++	  stb = mem_fileopen ();
++	  make_cleanup_ui_file_delete (stb);
++	  fprintf_symbol_filtered (stb, SYMBOL_PRINT_NAME (fa->sym),
++				   SYMBOL_LANGUAGE (fa->sym),
++				   DMGL_PARAMS | DMGL_ANSI);
++	  if (fa->entry_kind == print_entry_values_compact)
++	    {
++	      fputs_filtered ("=", stb);
++
++	      fprintf_symbol_filtered (stb, SYMBOL_PRINT_NAME (fa->sym),
++				       SYMBOL_LANGUAGE (fa->sym),
++				       DMGL_PARAMS | DMGL_ANSI);
++	    }
++	  if (fa->entry_kind == print_entry_values_only
++	      || fa->entry_kind == print_entry_values_compact)
++	    {
++	      fputs_filtered ("@entry", stb);
++	    }
++	  ui_out_field_stream (out, "name", stb);
++	}
++      else
++	/* Otherwise, just output the name.  */
++	ui_out_field_string (out, "name", sym_name);
++
++      annotate_arg_name_end ();
++
++      if (! ui_out_is_mi_like_p (out))
++	ui_out_text (out, "=");
++
++      if (print_args_field)
++	ui_out_field_int (out, "arg", 1);
++
++      /* For MI print the type, but only for simple values.  This seems
++	 weird, but this is how MI choose to format the various output
++	 types.  */
++      if (args_type == MI_PRINT_SIMPLE_VALUES)
++	{
++	  if (py_print_type (out, val) == PY_BT_ERROR)
++	    {
++	      do_cleanups (cleanups);
++	      goto error;
++	    }
++	}
++
++      annotate_arg_value (value_type (val));
++
++      /* If the output is to the CLI, and the user option "set print
++	 frame-arguments" is set to none, just output "...".  */
++      if (! ui_out_is_mi_like_p (out) && args_type == NO_VALUES)
++	ui_out_field_string (out, "value", "...");
++      else
++	{
++	  /* Otherwise, print the value for both MI and the CLI, except
++	     for the case of MI_PRINT_NO_VALUES.  */
++	  if (args_type != NO_VALUES)
++	    {
++	      if (py_print_value (out, val, opts, 0, args_type, language)
++		  == PY_BT_ERROR)
++		{
++		  do_cleanups (cleanups);
++		  goto error;
++		}
++	    }
++	}
++
++      do_cleanups (cleanups);
++    }
++  if (except.reason < 0)
++    {
++      gdbpy_convert_exception (except);
++      goto error;
++    }
++
++  return PY_BT_OK;
++
++ error:
++  return PY_BT_ERROR;
++}
++
++/* Helper function to loop over frame arguments provided by the
++   "frame_arguments" Python API.  Elements in the iterator must
++   conform to the "Symbol Value" interface.  ITER is the Python
++   iterable object, OUT is the output stream, ARGS_TYPE is an
++   enumerator 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.  Returns PY_BT_ERROR on error, with any GDB
++   exceptions converted to a Python exception, or PY_BT_OK on
++   success.  */
++
++static enum py_bt_status
++enumerate_args (PyObject *iter,
++		struct ui_out *out,
++		enum py_frame_args args_type,
++		int print_args_field,
++		struct frame_info *frame)
++{
++  PyObject *item;
++  struct value_print_options opts;
++  volatile struct gdb_exception except;
++
++  get_user_print_options (&opts);
++
++  if (args_type == CLI_SCALAR_VALUES)
++    {
++      /* True in "summary" mode, false otherwise.  */
++      opts.summary = 1;
++    }
++
++  opts.deref_ref = 1;
++
++  TRY_CATCH (except, RETURN_MASK_ALL)
++    {
++      annotate_frame_args ();
++    }
++  if (except.reason < 0)
++    {
++      gdbpy_convert_exception (except);
++      goto error;
++    }
++
++  /*  Collect the first argument outside of the loop, so output of
++      commas in the argument output is correct.  At the end of the
++      loop block collect another item from the iterator, and, if it is
++      not null emit a comma.  */
++  item = PyIter_Next (iter);
++  if (item == NULL && PyErr_Occurred ())
++    goto error;
++
++  while (item)
++    {
++      const struct language_defn *language;
++      char *sym_name;
++      struct symbol *sym;
++      struct value *val;
++      enum py_bt_status success = PY_BT_ERROR;
++
++      success = extract_sym (item, &sym_name, &sym, &language);
++      if (success == PY_BT_ERROR)
++	{
++	  Py_DECREF (item);
++	  goto error;
++	}
++
++      success = extract_value (item, &val);
++      if (success == PY_BT_ERROR)
++	{
++	  xfree (sym_name);
++	  Py_DECREF (item);
++	  goto error;
++	}
++
++      Py_DECREF (item);
++      item = NULL;
++
++      if (sym && ui_out_is_mi_like_p (out)
++	  && ! mi_should_print (sym, MI_PRINT_ARGS))
++	{
++	  xfree (sym_name);
++	  continue;
++	}
++
++      /* If the object did not provide a value, read it using
++	 read_frame_args and account for entry values, if any.  */
++      if (val == NULL)
++	{
++	  struct frame_arg arg, entryarg;
++
++	  /* If there is no value, and also no symbol, set error and
++	     exit.  */
++	  if (sym == NULL)
++	    {
++	      PyErr_SetString (PyExc_RuntimeError,
++			       _("No symbol or value provided."));
++	      xfree (sym_name);
++	      goto error;
++	    }
++
++	  TRY_CATCH (except, RETURN_MASK_ALL)
++	    {
++	      read_frame_arg (sym, frame, &arg, &entryarg);
++	    }
++	  if (except.reason < 0)
++	    {
++	      xfree (sym_name);
++	      gdbpy_convert_exception (except);
++	      goto error;
++	    }
++
++	  /* The object has not provided a value, so this is a frame
++	     argument to be read by GDB.  In this case we have to
++	     account for entry-values.  */
++
++	  if (arg.entry_kind != print_entry_values_only)
++	    {
++	      if (py_print_single_arg (out, NULL, &arg,
++				       NULL, &opts,
++				       args_type,
++				       print_args_field,
++				       NULL) == PY_BT_ERROR)
++		{
++		  xfree (arg.error);
++		  xfree (entryarg.error);
++		  xfree (sym_name);
++		  goto error;
++		}
++	    }
++
++	  if (entryarg.entry_kind != print_entry_values_no)
++	    {
++	      if (arg.entry_kind != print_entry_values_only)
++		{
++		  TRY_CATCH (except, RETURN_MASK_ALL)
++		    {
++		      ui_out_text (out, ", ");
++		      ui_out_wrap_hint (out, "    ");
++		    }
++		  if (except.reason < 0)
++		    {
++		      xfree (arg.error);
++		      xfree (entryarg.error);
++		      xfree (sym_name);
++		      gdbpy_convert_exception (except);
++		      goto error;
++		    }
++		}
++
++	      if (py_print_single_arg (out, NULL, &entryarg, NULL,
++				      &opts, args_type,
++				      print_args_field, NULL) == PY_BT_ERROR)
++		{
++		      xfree (arg.error);
++		      xfree (entryarg.error);
++		      xfree (sym_name);
++		      goto error;
++		}
++	    }
++
++	  xfree (arg.error);
++	  xfree (entryarg.error);
++	}
++      else
++	{
++	  /* If the object has provided a value, we just print that.  */
++	  if (val != NULL)
++	    {
++	      if (py_print_single_arg (out, sym_name, NULL, val, &opts,
++				       args_type, print_args_field,
++				       language) == PY_BT_ERROR)
++		{
++		  xfree (sym_name);
++		  goto error;
++		}
++	    }
++	}
++
++      xfree (sym_name);
++
++      /* Collect the next item from the iterator.  If
++	 this is the last item, do not print the
++	 comma.  */
++      item = PyIter_Next (iter);
++      if (item != NULL)
++	{
++	  TRY_CATCH (except, RETURN_MASK_ALL)
++	    {
++	      ui_out_text (out, ", ");
++	    }
++	  if (except.reason < 0)
++	    {
++	      Py_DECREF (item);
++	      gdbpy_convert_exception (except);
++	      goto error;
++	    }
++	}
++      else if (PyErr_Occurred ())
++	goto error;
++
++      TRY_CATCH (except, RETURN_MASK_ALL)
++	{
++	  annotate_arg_end ();
++	}
++      if (except.reason < 0)
++	{
++	  Py_DECREF (item);
++	  gdbpy_convert_exception (except);
++	  goto error;
++	}
++    }
++
++  return PY_BT_OK;
++
++ error:
++  return PY_BT_ERROR;
++}
++
++
++/* Helper function to loop over variables provided by the
++   "frame_locals" Python API.  Elements in the iterable must conform
++   to the "Symbol Value" interface.  ITER is the Python iterable
++   object, OUT is the output stream, INDENT is whether we should
++   indent the output (for CLI), ARGS_TYPE is an enumerator describing
++   the argument format, PRINT_ARGS_FIELD is flag which indicates
++   whether to output the ARGS field in the case of
++   -stack-list-variables and FRAME is the backing frame.  Returns
++   PY_BT_ERROR on error, with any GDB exceptions converted to a Python
++   exception, or PY_BT_OK on success.  */
++
++static enum py_bt_status
++enumerate_locals (PyObject *iter,
++		  struct ui_out *out,
++		  int indent,
++		  enum py_frame_args args_type,
++		  int print_args_field,
++		  struct frame_info *frame)
++{
++  PyObject *item;
++  struct value_print_options opts;
++
++  get_user_print_options (&opts);
++  opts.deref_ref = 1;
++
++  while ((item = PyIter_Next (iter)))
++    {
++      const struct language_defn *language;
++      char *sym_name;
++      struct value *val;
++      enum py_bt_status  success = PY_BT_ERROR;
++      struct symbol *sym;
++      volatile struct gdb_exception except;
++      int local_indent = 8 + (8 * indent);
++      struct cleanup *locals_cleanups;
++
++      locals_cleanups = make_cleanup_py_decref (item);
++
++      success = extract_sym (item, &sym_name, &sym, &language);
++      if (success == PY_BT_ERROR)
++	{
++	  do_cleanups (locals_cleanups);
++	  goto error;
++	}
++
++      make_cleanup (xfree, sym_name);
++
++      success = extract_value (item, &val);
++      if (success == PY_BT_ERROR)
++	{
++	  do_cleanups (locals_cleanups);
++	  goto error;
++	}
++
++      if (sym != NULL && ui_out_is_mi_like_p (out)
++	  && ! mi_should_print (sym, MI_PRINT_LOCALS))
++	{
++	  do_cleanups (locals_cleanups);
++	  continue;
++	}
++
++      /* If the object did not provide a value, read it.  */
++      if (val == NULL)
++	{
++	  TRY_CATCH (except, RETURN_MASK_ALL)
++	    {
++	      val = read_var_value (sym, frame);
++	    }
++	  if (except.reason < 0)
++	    {
++	      gdbpy_convert_exception (except);
++	      do_cleanups (locals_cleanups);
++	      goto error;
++	    }
++	}
++
++      /* With PRINT_NO_VALUES, MI does not emit a tuple normally as
++	 each output contains only one field.  The exception is
++	 -stack-list-variables, which always provides a tuple.  */
++      if (ui_out_is_mi_like_p (out))
++	{
++	  if (print_args_field || args_type != NO_VALUES)
++	    make_cleanup_ui_out_tuple_begin_end (out, NULL);
++	}
++      TRY_CATCH (except, RETURN_MASK_ALL)
++	{
++	  if (! ui_out_is_mi_like_p (out))
++	    {
++	      /* If the output is not MI we indent locals.  */
++	      ui_out_spaces (out, local_indent);
++	    }
++
++	  ui_out_field_string (out, "name", sym_name);
++
++	  if (! ui_out_is_mi_like_p (out))
++	    ui_out_text (out, " = ");
++	}
++      if (except.reason < 0)
++	{
++	  gdbpy_convert_exception (except);
++	  do_cleanups (locals_cleanups);
++	  goto error;
++	}
++
++      if (args_type == MI_PRINT_SIMPLE_VALUES)
++	{
++	  if (py_print_type (out, val) == PY_BT_ERROR)
++	    {
++	      do_cleanups (locals_cleanups);
++	      goto error;
++	    }
++	}
++
++      /* CLI always prints values for locals.  MI uses the
++	 simple/no/all system.  */
++      if (! ui_out_is_mi_like_p (out))
++	{
++	  int val_indent = (indent + 1) * 4;
++
++	  if (py_print_value (out, val, &opts, val_indent, args_type,
++			      language) ==  PY_BT_ERROR)
++	    {
++	      do_cleanups (locals_cleanups);
++	      goto error;
++	    }
++	}
++      else
++	{
++	  if (args_type != NO_VALUES)
++	    {
++	      if (py_print_value (out, val, &opts, 0, args_type,
++				  language) ==  PY_BT_ERROR)
++		{
++		  do_cleanups (locals_cleanups);
++		  goto error;
++		}
++	    }
++	}
++
++      do_cleanups (locals_cleanups);
++
++      TRY_CATCH (except, RETURN_MASK_ALL)
++	{
++	  ui_out_text (out, "\n");
++	}
++      if (except.reason < 0)
++	{
++	  gdbpy_convert_exception (except);
++	  goto error;
++	}
++    }
++
++  if (item == NULL && PyErr_Occurred ())
++    goto error;
++
++  return PY_BT_OK;
++
++ error:
++  return PY_BT_ERROR;
++}
++
++/*  Helper function for -stack-list-variables.  Returns PY_BT_ERROR on
++    error, or PY_BT_OK on success.  */
++
++static enum py_bt_status
++py_mi_print_variables (PyObject *filter, struct ui_out *out,
++		       struct value_print_options *opts,
++		       enum py_frame_args args_type,
++		       struct frame_info *frame)
++{
++  struct cleanup *old_chain;
++  PyObject *args_iter;
++  PyObject *locals_iter;
++
++  args_iter = get_py_iter_from_func (filter, "frame_args");
++  old_chain = make_cleanup_py_xdecref (args_iter);
++  if (args_iter == NULL)
++    goto error;
++
++  locals_iter = get_py_iter_from_func (filter, "frame_locals");
++  if (locals_iter == NULL)
++    goto error;
++
++  make_cleanup_py_decref (locals_iter);
++  make_cleanup_ui_out_list_begin_end (out, "variables");
++
++  if (args_iter != Py_None)
++    if (enumerate_args (args_iter, out, args_type, 1, frame) == PY_BT_ERROR)
++      goto error;
++
++  if (locals_iter != Py_None)
++    if (enumerate_locals (locals_iter, out, 1, args_type, 1, frame)
++	== PY_BT_ERROR)
++      goto error;
++
++  do_cleanups (old_chain);
++  return PY_BT_OK;
++
++ error:
++  do_cleanups (old_chain);
++  return PY_BT_ERROR;
++}
++
++/* Helper function for printing locals.  This function largely just
++   creates the wrapping tuple, and calls enumerate_locals.  Returns
++   PY_BT_ERROR on error, or PY_BT_OK on success.*/
++
++static enum py_bt_status
++py_print_locals (PyObject *filter,
++		 struct ui_out *out,
++		 enum py_frame_args args_type,
++		 int indent,
++		 struct frame_info *frame)
++{
++  PyObject *locals_iter = get_py_iter_from_func (filter,
++						 "frame_locals");
++  struct cleanup *old_chain = make_cleanup_py_xdecref (locals_iter);
++
++  if (locals_iter == NULL)
++    goto locals_error;
++
++  make_cleanup_ui_out_list_begin_end (out, "locals");
++
++  if (locals_iter != Py_None)
++    if (enumerate_locals (locals_iter, out, indent, args_type,
++			  0, frame) == PY_BT_ERROR)
++      goto locals_error;
++
++  do_cleanups (old_chain);
++  return PY_BT_OK;;
++
++ locals_error:
++  do_cleanups (old_chain);
++  return PY_BT_ERROR;
++}
++
++/* Helper function for printing frame arguments.  This function
++   largely just creates the wrapping tuple, and calls enumerate_args.
++   Returns PY_BT_ERROR on error, with any GDB exceptions converted to
++   a Python exception, or PY_BT_OK on success.  */
++
++static enum py_bt_status
++py_print_args (PyObject *filter,
++	       struct ui_out *out,
++	       enum py_frame_args args_type,
++	       struct frame_info *frame)
++{
++  PyObject *args_iter  = get_py_iter_from_func (filter, "frame_args");
++  struct cleanup *old_chain = make_cleanup_py_xdecref (args_iter);
++  volatile struct gdb_exception except;
++
++  if (args_iter == NULL)
++    goto args_error;
++
++  make_cleanup_ui_out_list_begin_end (out, "args");
++
++  TRY_CATCH (except, RETURN_MASK_ALL)
++    {
++      annotate_frame_args ();
++      if (! ui_out_is_mi_like_p (out))
++	ui_out_text (out, " (");
++    }
++  if (except.reason < 0)
++    {
++      gdbpy_convert_exception (except);
++      goto args_error;
++    }
++
++  if (args_iter != Py_None)
++    if (enumerate_args (args_iter, out, args_type, 0, frame) == PY_BT_ERROR)
++      goto args_error;
++
++  TRY_CATCH (except, RETURN_MASK_ALL)
++    {
++      if (! ui_out_is_mi_like_p (out))
++	ui_out_text (out, ")");
++    }
++  if (except.reason < 0)
++    {
++      gdbpy_convert_exception (except);
++      goto args_error;
++    }
++
++  do_cleanups (old_chain);
++  return PY_BT_OK;
++
++ args_error:
++  do_cleanups (old_chain);
++  return PY_BT_ERROR;
++}
++
++/*  Print a single frame to the designated output stream, detecting
++    whether the output is MI or console, and formatting the output
++    according to the conventions of that protocol.  FILTER is the
++    frame-filter associated with this frame.  FLAGS is an integer
++    describing the various print options.  The FLAGS variables is
++    described in "apply_frame_filter" function.  ARGS_TYPE is an
++    enumerator describing the argument format.  OUT is the output
++    stream to print, INDENT is the level of indention for this frame
++    (in the case of elided frames), and LEVELS_PRINTED is a hash-table
++    containing all the frames level that have already been printed.
++    If a frame level has been printed, do not print it again (in the
++    case of elided frames).  Returns PY_BT_ERROR on error, with any
++    GDB exceptions converted to a Python exception, or PY_BT_COMPLETED
++    on success.  */
++
++static enum py_bt_status
++py_print_frame (PyObject *filter, int flags, enum py_frame_args args_type,
++		struct ui_out *out, int indent, htab_t levels_printed)
++{
++  int has_addr = 0;
++  CORE_ADDR address = 0;
++  struct gdbarch *gdbarch = NULL;
++  struct frame_info *frame = NULL;
++  struct cleanup *cleanup_stack = make_cleanup (null_cleanup, NULL);
++  struct value_print_options opts;
++  PyObject *py_inf_frame, *elided;
++  int print_level, print_frame_info, print_args, print_locals;
++  volatile struct gdb_exception except;
++
++  /* Extract print settings from FLAGS.  */
++  print_level = (flags & PRINT_LEVEL) ? 1 : 0;
++  print_frame_info = (flags & PRINT_FRAME_INFO) ? 1 : 0;
++  print_args = (flags & PRINT_ARGS) ? 1 : 0;
++  print_locals = (flags & PRINT_LOCALS) ? 1 : 0;
++
++  get_user_print_options (&opts);
++
++  /* Get the underlying frame.  This is needed to determine GDB
++  architecture, and also, in the cases of frame variables/arguments to
++  read them if they returned filter object requires us to do so.  */
++  py_inf_frame = PyObject_CallMethod (filter, "inferior_frame", NULL);
++  if (py_inf_frame == NULL)
++    goto error;
++
++  frame = frame_object_to_frame_info (py_inf_frame);;
++
++  Py_DECREF (py_inf_frame);
++
++  if (frame == NULL)
++    goto error;
++
++  TRY_CATCH (except, RETURN_MASK_ALL)
++    {
++      gdbarch = get_frame_arch (frame);
++    }
++  if (except.reason < 0)
++    {
++      gdbpy_convert_exception (except);
++      goto error;
++    }
++
++
++  /* stack-list-variables.  */
++  if (print_locals && print_args && ! print_frame_info)
++    {
++      if (py_mi_print_variables (filter, out, &opts,
++				 args_type, frame) == PY_BT_ERROR)
++	goto error;
++      else
++	{
++	  do_cleanups (cleanup_stack);
++	  return PY_BT_COMPLETED;
++	}
++    }
++
++  /* -stack-list-locals does not require a
++     wrapping frame attribute.  */
++  if (print_frame_info || (print_args && ! print_locals))
++    make_cleanup_ui_out_tuple_begin_end (out, "frame");
++
++  if (print_frame_info)
++    {
++      /* Elided frames are also printed with this function (recursively)
++	 and are printed with indention.  */
++      if (indent > 0)
++	{
++	TRY_CATCH (except, RETURN_MASK_ALL)
++	  {
++	    ui_out_spaces (out, indent*4);
++	  }
++	if (except.reason < 0)
++	  {
++	    gdbpy_convert_exception (except);
++	    goto error;
++	  }
++	}
++
++      /* The address is required for frame annotations, and also for
++	 address printing.  */
++      if (PyObject_HasAttrString (filter, "address"))
++	{
++	  PyObject *paddr = PyObject_CallMethod (filter, "address", NULL);
++	  if (paddr != NULL)
++	    {
++	      if (paddr != Py_None)
++		{
++		  address = PyLong_AsLong (paddr);
++		  has_addr = 1;
++		}
++	      Py_DECREF (paddr);
++	    }
++	  else
++	    goto error;
++	}
++    }
++
++  /* Print frame level.  MI does not require the level if
++     locals/variables only are being printed.  */
++  if ((print_frame_info || print_args) && print_level)
++    {
++      struct frame_info **slot;
++      int level;
++      volatile struct gdb_exception except;
++
++      slot = (struct frame_info **) htab_find_slot (levels_printed,
++						    frame, INSERT);
++      TRY_CATCH (except, RETURN_MASK_ALL)
++	{
++	  level = frame_relative_level (frame);
++
++	  /* Check if this frame has already been printed (there are cases
++	     where elided synthetic dummy-frames have to 'borrow' the frame
++	     architecture from the eliding frame.  If that is the case, do
++	     not print 'level', but print spaces.  */
++	  if (*slot == frame)
++	    ui_out_field_skip (out, "level");
++	  else
++	    {
++	      *slot = frame;
++	      annotate_frame_begin (print_level ? level : 0,
++				    gdbarch, address);
++	      ui_out_text (out, "#");
++	      ui_out_field_fmt_int (out, 2, ui_left, "level",
++				    level);
++	    }
++	}
++      if (except.reason < 0)
++	{
++	  gdbpy_convert_exception (except);
++	  goto error;
++	}
++    }
++
++  if (print_frame_info)
++    {
++      /* Print address to the address field.  If an address is not provided,
++	 print nothing.  */
++      if (opts.addressprint && has_addr)
++	{
++	  TRY_CATCH (except, RETURN_MASK_ALL)
++	    {
++	      annotate_frame_address ();
++	      ui_out_field_core_addr (out, "addr", gdbarch, address);
++	      annotate_frame_address_end ();
++	      ui_out_text (out, " in ");
++	    }
++	  if (except.reason < 0)
++	    {
++	      gdbpy_convert_exception (except);
++	      goto error;
++	    }
++	}
++
++      /* Print frame function name.  */
++      if (PyObject_HasAttrString (filter, "function"))
++	{
++	  PyObject *py_func = PyObject_CallMethod (filter, "function", NULL);
++
++	  if (py_func != NULL)
++	    {
++	      const char *function = NULL;
++
++	      if (gdbpy_is_string (py_func))
++		{
++		  function = PyString_AsString (py_func);
++
++		  if (function == NULL)
++		    {
++		      Py_DECREF (py_func);
++		      goto error;
++		    }
++		}
++	      else if (PyLong_Check (py_func))
++		{
++		  CORE_ADDR addr = PyLong_AsUnsignedLongLong (py_func);
++		  struct minimal_symbol *msymbol;
++
++		  if (PyErr_Occurred ())
++		    goto error;
++
++		  msymbol = lookup_minimal_symbol_by_pc (addr);
++		  if (msymbol != NULL)
++		    function = SYMBOL_PRINT_NAME (msymbol);
++		}
++	      else if (py_func != Py_None)
++		{
++		  PyErr_SetString (PyExc_RuntimeError,
++				   _("FrameDecorator.function: expecting a " \
++				     "String, integer or None."));
++		  Py_DECREF (py_func);
++		  goto error;
++		}
++
++
++	      TRY_CATCH (except, RETURN_MASK_ALL)
++		{
++		  annotate_frame_function_name ();
++		  if (function == NULL)
++		    ui_out_field_skip (out, "func");
++		  else
++		    ui_out_field_string (out, "func", function);
++		}
++	      if (except.reason < 0)
++		{
++		  Py_DECREF (py_func);
++		  gdbpy_convert_exception (except);
++		  goto error;
++		}
++	    }
++	  Py_DECREF (py_func);
++	}
++      else
++	goto error;
++    }
++
++
++  /* Frame arguments.  Check the result, and error if something went
++     wrong.  */
++  if (print_args)
++    {
++      if (py_print_args (filter, out, args_type, frame) == PY_BT_ERROR)
++	goto error;
++    }
++
++  /* File name/source/line number information.  */
++  if (print_frame_info)
++    {
++      TRY_CATCH (except, RETURN_MASK_ALL)
++	{
++	  annotate_frame_source_begin ();
++	}
++      if (except.reason < 0)
++	{
++	  gdbpy_convert_exception (except);
++	  goto error;
++	}
++
++      if (PyObject_HasAttrString (filter, "filename"))
++	{
++	  PyObject *py_fn = PyObject_CallMethod (filter, "filename",
++						 NULL);
++	  if (py_fn != NULL)
++	    {
++	      if (py_fn != Py_None)
++		{
++		  char *filename = PyString_AsString (py_fn);
++
++		  if (filename == NULL)
++		    {
++		      Py_DECREF (py_fn);
++		      goto error;
++		    }
++		  TRY_CATCH (except, RETURN_MASK_ALL)
++		    {
++		      ui_out_wrap_hint (out, "   ");
++		      ui_out_text (out, " at ");
++		      annotate_frame_source_file ();
++		      ui_out_field_string (out, "file", filename);
++		      annotate_frame_source_file_end ();
++		    }
++		  if (except.reason < 0)
++		    {
++		      Py_DECREF (py_fn);
++		      gdbpy_convert_exception (except);
++		      goto error;
++		    }
++		}
++	      Py_DECREF (py_fn);
++	    }
++	  else
++	    goto error;
++	}
++
++      if (PyObject_HasAttrString (filter, "line"))
++	{
++	  PyObject *py_line = PyObject_CallMethod (filter, "line", NULL);
++	  int line;
++
++	  if (py_line != NULL)
++	    {
++	      if (py_line != Py_None)
++		{
++		  line = PyLong_AsLong (py_line);
++		  TRY_CATCH (except, RETURN_MASK_ALL)
++		    {
++		      ui_out_text (out, ":");
++		      annotate_frame_source_line ();
++		      ui_out_field_int (out, "line", line);
++		    }
++		  if (except.reason < 0)
++		    {
++		      Py_DECREF (py_line);
++		      gdbpy_convert_exception (except);
++		      goto error;
++		    }
++		}
++	      Py_DECREF (py_line);
++	    }
++	  else
++	    goto error;
++	}
++    }
++
++  /* For MI we need to deal with the "children" list population of
++     elided frames, so if MI output detected do not send newline.  */
++  if (! ui_out_is_mi_like_p (out))
++    {
++      TRY_CATCH (except, RETURN_MASK_ALL)
++	{
++	  annotate_frame_end ();
++	  ui_out_text (out, "\n");
++	}
++      if (except.reason < 0)
++	{
++	  gdbpy_convert_exception (except);
++	  goto error;
++	}
++    }
++
++  if (print_locals)
++    {
++      if (py_print_locals (filter, out, args_type, indent,
++			   frame) == PY_BT_ERROR)
++	goto error;
++    }
++
++  /* Finally recursively print elided frames, if any.  */
++  elided  = get_py_iter_from_func (filter, "elided");
++  if (elided == NULL)
++    goto error;
++
++  make_cleanup_py_decref (elided);
++  if (elided != Py_None)
++    {
++      PyObject *item;
++
++      make_cleanup_ui_out_list_begin_end (out, "children");
++
++      if (! ui_out_is_mi_like_p (out))
++	indent++;
++
++      while ((item = PyIter_Next (elided)))
++	{
++	  enum py_bt_status success = py_print_frame (item, flags,
++						      args_type, out,
++						      indent,
++						      levels_printed);
++
++	  if (success == PY_BT_ERROR)
++	    {
++	      Py_DECREF (item);
++	      goto error;
++	    }
++
++	  Py_DECREF (item);
++	}
++      if (item == NULL && PyErr_Occurred ())
++	goto error;
++    }
++
++
++  do_cleanups (cleanup_stack);
++  return PY_BT_COMPLETED;
++
++ error:
++  do_cleanups (cleanup_stack);
++  return PY_BT_ERROR;
++}
++
++/* Helper function to initiate frame filter invocation at starting
++   frame FRAME.  */
++
++static PyObject *
++bootstrap_python_frame_filters (struct frame_info *frame,
++				int frame_low, int frame_high)
++{
++  struct cleanup *cleanups =
++    make_cleanup (null_cleanup, NULL);
++  PyObject *module, *sort_func, *iterable, *frame_obj, *iterator;
++  PyObject *py_frame_low, *py_frame_high;
++
++  frame_obj = frame_info_to_frame_object (frame);
++  if (frame_obj == NULL)
++    goto error;
++  make_cleanup_py_decref (frame_obj);
++
++  module = PyImport_ImportModule ("gdb.frames");
++  if (module == NULL)
++    goto error;
++  make_cleanup_py_decref (module);
++
++  sort_func = PyObject_GetAttrString (module, "execute_frame_filters");
++  if (sort_func == NULL)
++    goto error;
++  make_cleanup_py_decref (sort_func);
++
++  py_frame_low = PyInt_FromLong (frame_low);
++  if (py_frame_low == NULL)
++    goto error;
++  make_cleanup_py_decref (py_frame_low);
++
++  py_frame_high = PyInt_FromLong (frame_high);
++  if (py_frame_high == NULL)
++    goto error;
++  make_cleanup_py_decref (py_frame_high);
++
++  iterable = PyObject_CallFunctionObjArgs (sort_func, frame_obj,
++					   py_frame_low,
++					   py_frame_high,
++					   NULL);
++  if (iterable == NULL)
++    goto error;
++
++  do_cleanups (cleanups);
++
++  if (iterable != Py_None)
++    {
++      iterator = PyObject_GetIter (iterable);
++      Py_DECREF (iterable);
++    }
++  else
++    {
++      return iterable;
++    }
++
++  return iterator;
++
++ error:
++  do_cleanups (cleanups);
++  return NULL;
++}
++
++/*  This is the only publicly exported function in this file.  FRAME
++    is the source frame to start frame-filter invocation.  FLAGS is an
++    integer holding the flags for printing.  The following elements of
++    the FRAME_FILTER_FLAGS enum denotes the make-up of FLAGS:
++    PRINT_LEVEL is a flag indicating whether to print the frame's
++    relative level in the output.  PRINT_FRAME_INFO is a flag that
++    indicates whether this function should print the frame
++    information, PRINT_ARGS is a flag that indicates whether to print
++    frame arguments, and PRINT_LOCALS, likewise, with frame local
++    variables.  ARGS_TYPE is an enumerator describing the argument
++    format, OUT is the output stream to print.  FRAME_LOW is the
++    beginning of the slice of frames to print, and FRAME_HIGH is the
++    upper limit of the frames to count.  Returns PY_BT_ERROR on error,
++    or PY_BT_COMPLETED on success.*/
++
++enum py_bt_status
++apply_frame_filter (struct frame_info *frame, int flags,
++		    enum py_frame_args args_type,
++		    struct ui_out *out, int frame_low,
++		    int frame_high)
++
++{
++  struct gdbarch *gdbarch = NULL;
++  struct cleanup *cleanups;
++  enum py_bt_status success = PY_BT_ERROR;
++  PyObject *iterable;
++  volatile struct gdb_exception except;
++  PyObject *item;
++  htab_t levels_printed;
++
++  cleanups = ensure_python_env (gdbarch, current_language);
++
++  TRY_CATCH (except, RETURN_MASK_ALL)
++    {
++      gdbarch = get_frame_arch (frame);
++    }
++  if (except.reason < 0)
++    {
++      gdbpy_convert_exception (except);
++      goto error;
++    }
++
++  iterable = bootstrap_python_frame_filters (frame, frame_low, frame_high);
++
++  if (iterable == NULL)
++    goto error;
++
++  /* If iterable is None, then there are no frame filters registered.
++     If this is the case, defer to default GDB printing routines in MI
++     and CLI.  */
++  make_cleanup_py_decref (iterable);
++  if (iterable == Py_None)
++    {
++      success = PY_BT_NO_FILTERS;
++      goto done;
++    }
++
++  levels_printed = htab_create (20,
++				htab_hash_pointer,
++				htab_eq_pointer,
++				NULL);
++  make_cleanup_htab_delete (levels_printed);
++
++  while ((item = PyIter_Next (iterable)))
++    {
++      success = py_print_frame (item, flags, args_type, out, 0,
++				levels_printed);
++
++      /* Do not exit on error printing a single frame.  Print the
++	 error and continue with other frames.  */
++      if (success == PY_BT_ERROR)
++	gdbpy_print_stack ();
++
++      Py_DECREF (item);
++    }
++
++  if (item == NULL && PyErr_Occurred ())
++    goto error;
++
++ done:
++  do_cleanups (cleanups);
++  return success;
++
++ error:
++  gdbpy_print_stack ();
++  do_cleanups (cleanups);
++  return PY_BT_ERROR;
++}
+Index: gdb-7.6/gdb/python/py-objfile.c
+===================================================================
+--- gdb-7.6.orig/gdb/python/py-objfile.c	2013-05-20 22:23:36.748215146 +0200
++++ gdb-7.6/gdb/python/py-objfile.c	2013-05-20 22:25:52.112165767 +0200
+@@ -33,6 +33,8 @@ typedef struct
+   /* The pretty-printer list of functions.  */
+   PyObject *printers;
+ 
++  /* The frame filter list of functions.  */
++  PyObject *frame_filters;
+   /* The type-printer list.  */
+   PyObject *type_printers;
+ } objfile_object;
+@@ -61,6 +63,7 @@ objfpy_dealloc (PyObject *o)
+   objfile_object *self = (objfile_object *) o;
+ 
+   Py_XDECREF (self->printers);
++  Py_XDECREF (self->frame_filters);
+   Py_XDECREF (self->type_printers);
+   Py_TYPE (self)->tp_free (self);
+ }
+@@ -81,6 +84,13 @@ objfpy_new (PyTypeObject *type, PyObject
+ 	  return NULL;
+ 	}
+ 
++      self->frame_filters = PyDict_New ();
++      if (!self->frame_filters)
++	{
++	  Py_DECREF (self);
++	  return NULL;
++	}
++
+       self->type_printers = PyList_New (0);
+       if (!self->type_printers)
+ 	{
+@@ -129,6 +139,47 @@ objfpy_set_printers (PyObject *o, PyObje
+   return 0;
+ }
+ 
++/* Return the Python dictionary attribute containing frame filters for
++   this object file.  */
++PyObject *
++objfpy_get_frame_filters (PyObject *o, void *ignore)
++{
++  objfile_object *self = (objfile_object *) o;
++
++  Py_INCREF (self->frame_filters);
++  return self->frame_filters;
++}
++
++/* Set this object file's frame filters dictionary to FILTERS.  */
++static int
++objfpy_set_frame_filters (PyObject *o, PyObject *filters, void *ignore)
++{
++  PyObject *tmp;
++  objfile_object *self = (objfile_object *) o;
++
++  if (! filters)
++    {
++      PyErr_SetString (PyExc_TypeError,
++		       _("Cannot delete the frame filters attribute."));
++      return -1;
++    }
++
++  if (! PyDict_Check (filters))
++    {
++      PyErr_SetString (PyExc_TypeError,
++		       _("The frame_filters attribute must be a dictionary."));
++      return -1;
++    }
++
++  /* Take care in case the LHS and RHS are related somehow.  */
++  tmp = self->frame_filters;
++  Py_INCREF (filters);
++  self->frame_filters = filters;
++  Py_XDECREF (tmp);
++
++  return 0;
++}
++
+ /* Get the 'type_printers' attribute.  */
+ 
+ static PyObject *
+@@ -225,6 +276,13 @@ objfile_to_objfile_object (struct objfil
+ 	      return NULL;
+ 	    }
+ 
++	  object->frame_filters = PyDict_New ();
++	  if (!object->frame_filters)
++	    {
++	      Py_DECREF (object);
++	      return NULL;
++	    }
++
+ 	  object->type_printers = PyList_New (0);
+ 	  if (!object->type_printers)
+ 	    {
+@@ -270,6 +328,8 @@ static PyGetSetDef objfile_getset[] =
+     "The objfile's filename, or None.", NULL },
+   { "pretty_printers", objfpy_get_printers, objfpy_set_printers,
+     "Pretty printers.", NULL },
++  { "frame_filters", objfpy_get_frame_filters,
++    objfpy_set_frame_filters, "Frame Filters.", NULL },
+   { "type_printers", objfpy_get_type_printers, objfpy_set_type_printers,
+     "Type printers.", NULL },
+   { NULL }
+Index: gdb-7.6/gdb/python/py-progspace.c
+===================================================================
+--- gdb-7.6.orig/gdb/python/py-progspace.c	2013-05-20 22:23:36.748215146 +0200
++++ gdb-7.6/gdb/python/py-progspace.c	2013-05-20 22:25:52.112165767 +0200
+@@ -35,6 +35,8 @@ typedef struct
+   /* The pretty-printer list of functions.  */
+   PyObject *printers;
+ 
++  /* The frame filter list of functions.  */
++  PyObject *frame_filters;
+   /* The type-printer list.  */
+   PyObject *type_printers;
+ } pspace_object;
+@@ -69,6 +71,7 @@ pspy_dealloc (PyObject *self)
+   pspace_object *ps_self = (pspace_object *) self;
+ 
+   Py_XDECREF (ps_self->printers);
++  Py_XDECREF (ps_self->frame_filters);
+   Py_XDECREF (ps_self->type_printers);
+   Py_TYPE (self)->tp_free (self);
+ }
+@@ -89,6 +92,13 @@ pspy_new (PyTypeObject *type, PyObject *
+ 	  return NULL;
+ 	}
+ 
++      self->frame_filters = PyDict_New ();
++      if (!self->frame_filters)
++	{
++	  Py_DECREF (self);
++	  return NULL;
++	}
++
+       self->type_printers = PyList_New (0);
+       if (!self->type_printers)
+ 	{
+@@ -137,6 +147,47 @@ pspy_set_printers (PyObject *o, PyObject
+   return 0;
+ }
+ 
++/* Return the Python dictionary attribute containing frame filters for
++   this program space.  */
++PyObject *
++pspy_get_frame_filters (PyObject *o, void *ignore)
++{
++  pspace_object *self = (pspace_object *) o;
++
++  Py_INCREF (self->frame_filters);
++  return self->frame_filters;
++}
++
++/* Set this object file's frame filters dictionary to FILTERS.  */
++static int
++pspy_set_frame_filters (PyObject *o, PyObject *frame, void *ignore)
++{
++  PyObject *tmp;
++  pspace_object *self = (pspace_object *) o;
++
++  if (! frame)
++    {
++      PyErr_SetString (PyExc_TypeError,
++		       "cannot delete the frame filter attribute");
++      return -1;
++    }
++
++  if (! PyDict_Check (frame))
++    {
++      PyErr_SetString (PyExc_TypeError,
++		       "the frame filter attribute must be a dictionary");
++      return -1;
++    }
++
++  /* Take care in case the LHS and RHS are related somehow.  */
++  tmp = self->frame_filters;
++  Py_INCREF (frame);
++  self->frame_filters = frame;
++  Py_XDECREF (tmp);
++
++  return 0;
++}
++
+ /* Get the 'type_printers' attribute.  */
+ 
+ static PyObject *
+@@ -221,6 +272,13 @@ pspace_to_pspace_object (struct program_
+ 	      return NULL;
+ 	    }
+ 
++	  object->frame_filters = PyDict_New ();
++	  if (!object->frame_filters)
++	    {
++	      Py_DECREF (object);
++	      return NULL;
++	    }
++
+ 	  object->type_printers = PyList_New (0);
+ 	  if (!object->type_printers)
+ 	    {
+@@ -257,6 +315,8 @@ static PyGetSetDef pspace_getset[] =
+     "The progspace's main filename, or None.", NULL },
+   { "pretty_printers", pspy_get_printers, pspy_set_printers,
+     "Pretty printers.", NULL },
++  { "frame_filters", pspy_get_frame_filters, pspy_set_frame_filters,
++    "Frame filters.", NULL },
+   { "type_printers", pspy_get_type_printers, pspy_set_type_printers,
+     "Type printers.", NULL },
+   { NULL }
+Index: gdb-7.6/gdb/python/py-utils.c
+===================================================================
+--- gdb-7.6.orig/gdb/python/py-utils.c	2013-05-20 22:23:36.748215146 +0200
++++ gdb-7.6/gdb/python/py-utils.c	2013-05-20 22:25:52.113165766 +0200
+@@ -48,6 +48,28 @@ make_cleanup_py_decref (PyObject *py)
+   return make_cleanup (py_decref, (void *) py);
+ }
+ 
++/* This is a cleanup function which decrements the refcount on a
++   Python object.  This function accounts appropriately for NULL
++   references.  */
++
++static void
++py_xdecref (void *p)
++{
++  PyObject *py = p;
++
++  Py_XDECREF (py);
++}
++
++/* Return a new cleanup which will decrement the Python object's
++   refcount when run.  Account for and operate on NULL references
++   correctly.  */
++
++struct cleanup *
++make_cleanup_py_xdecref (PyObject *py)
++{
++  return make_cleanup (py_xdecref, py);
++}
++
+ /* Converts a Python 8-bit string to a unicode string object.  Assumes the
+    8-bit string is in the host charset.  If an error occurs during conversion,
+    returns NULL with a python exception set.
+Index: gdb-7.6/gdb/python/python-internal.h
+===================================================================
+--- gdb-7.6.orig/gdb/python/python-internal.h	2013-05-20 22:23:36.748215146 +0200
++++ gdb-7.6/gdb/python/python-internal.h	2013-05-20 22:25:52.113165766 +0200
+@@ -251,9 +251,11 @@ PyObject *frame_info_to_frame_object (st
+ 
+ PyObject *pspace_to_pspace_object (struct program_space *);
+ PyObject *pspy_get_printers (PyObject *, void *);
++PyObject *pspy_get_frame_filters (PyObject *, void *);
+ 
+ PyObject *objfile_to_objfile_object (struct objfile *);
+ PyObject *objfpy_get_printers (PyObject *, void *);
++PyObject *objfpy_get_frame_filters (PyObject *, void *);
+ 
+ PyObject *gdbarch_to_arch_object (struct gdbarch *gdbarch);
+ 
+@@ -304,6 +306,7 @@ void gdbpy_initialize_new_objfile_event
+ void gdbpy_initialize_arch (void);
+ 
+ struct cleanup *make_cleanup_py_decref (PyObject *py);
++struct cleanup *make_cleanup_py_xdecref (PyObject *py);
+ 
+ struct cleanup *ensure_python_env (struct gdbarch *gdbarch,
+ 				   const struct language_defn *language);
+Index: gdb-7.6/gdb/python/python.c
+===================================================================
+--- gdb-7.6.orig/gdb/python/python.c	2013-05-20 22:23:36.748215146 +0200
++++ gdb-7.6/gdb/python/python.c	2013-05-20 22:25:52.113165766 +0200
+@@ -1442,6 +1442,15 @@ free_type_printers (void *arg)
+ {
+ }
+ 
++enum py_bt_status
++apply_frame_filter (struct frame_info *frame, int flags,
++		    enum py_frame_args args_type,
++		    struct ui_out *out, int frame_low,
++		    int frame_high)
++{
++  return PY_BT_NO_FILTERS;
++}
++
+ #endif /* HAVE_PYTHON */
+ 
+ \f
+Index: gdb-7.6/gdb/python/python.h
+===================================================================
+--- gdb-7.6.orig/gdb/python/python.h	2013-05-20 22:23:36.748215146 +0200
++++ gdb-7.6/gdb/python/python.h	2013-05-20 22:25:52.113165766 +0200
+@@ -21,6 +21,7 @@
+ #define GDB_PYTHON_H
+ 
+ #include "value.h"
++#include "mi/mi-cmds.h"
+ 
+ struct breakpoint_object;
+ 
+@@ -28,6 +29,66 @@ struct breakpoint_object;
+    E.g. When the program loads libfoo.so, look for libfoo-gdb.py.  */
+ #define GDBPY_AUTO_FILE_NAME "-gdb.py"
+ 
++/* Python frame-filter status return values.  */
++enum py_bt_status
++  {
++    /* Return when an error has occurred in processing frame filters,
++       or when printing the stack.  */
++    PY_BT_ERROR = -1,
++
++    /* Return from internal routines to indicate that the function
++       succeeded.  */
++    PY_BT_OK = 1,
++
++    /* Return when the frame filter process is complete, and all
++       operations have succeeded.  */
++    PY_BT_COMPLETED = 2,
++
++    /* Return when the frame filter process is complete, but there
++       were no filter registered and enabled to process. */
++    PY_BT_NO_FILTERS = 3
++  };
++
++/* Flags to pass to apply_frame_filter.  */
++
++enum frame_filter_flags
++  {
++    /* Set this flag if frame level is to be printed.  */
++    PRINT_LEVEL = 1,
++
++    /* Set this flag if frame information is to be printed.  */
++    PRINT_FRAME_INFO = 2,
++
++    /* Set this flag if frame arguments are to be printed.  */
++    PRINT_ARGS = 4,
++
++    /* Set this flag if frame locals are to be printed.  */
++    PRINT_LOCALS = 8,
++  };
++
++/* A choice of the different frame argument printing strategies that
++   can occur in different cases of frame filter instantiation.  */
++typedef enum py_frame_args
++{
++  /* Print no values for arguments when invoked from the MI. */
++  NO_VALUES = PRINT_NO_VALUES,
++
++  MI_PRINT_ALL_VALUES = PRINT_ALL_VALUES,
++
++  /* Print only simple values (what MI defines as "simple") for
++     arguments when invoked from the MI. */
++  MI_PRINT_SIMPLE_VALUES = PRINT_SIMPLE_VALUES,
++
++
++  /* Print only scalar values for arguments when invoked from the
++     CLI. */
++  CLI_SCALAR_VALUES,
++
++  /* Print all values for arguments when invoked from the
++     CLI. */
++  CLI_ALL_VALUES
++} py_frame_args;
++
+ extern void finish_python_initialization (void);
+ 
+ void eval_python_from_control_command (struct command_line *);
+@@ -43,6 +104,11 @@ int apply_val_pretty_printer (struct typ
+ 			      const struct value_print_options *options,
+ 			      const struct language_defn *language);
+ 
++enum py_bt_status apply_frame_filter (struct frame_info *frame, int flags,
++				      enum py_frame_args args_type,
++				      struct ui_out *out, int frame_low,
++				      int frame_high);
++
+ void preserve_python_values (struct objfile *objfile, htab_t copied_types);
+ 
+ void gdbpy_load_auto_scripts_for_objfile (struct objfile *objfile);
+Index: gdb-7.6/gdb/python/lib/gdb/FrameDecorator.py
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ gdb-7.6/gdb/python/lib/gdb/FrameDecorator.py	2013-05-20 22:25:52.113165766 +0200
+@@ -0,0 +1,285 @@
++# Copyright (C) 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 <http://www.gnu.org/licenses/>.
++
++import gdb
++
++class FrameDecorator(object):
++    """Basic implementation of a Frame Decorator"""
++
++    """ This base frame decorator decorates a frame or another frame
++    decorator, and provides convenience methods.  If this object is
++    wrapping a frame decorator, defer to that wrapped object's method
++    if it has one.  This allows for frame decorators that have
++    sub-classed FrameDecorator object, but also wrap other frame
++    decorators on the same frame to correctly execute.
++
++    E.g
++
++    If the result of frame filters running means we have one gdb.Frame
++    wrapped by multiple frame decorators, all sub-classed from
++    FrameDecorator, the resulting hierarchy will be:
++
++    Decorator1
++      -- (wraps) Decorator2
++        -- (wraps) FrameDecorator
++          -- (wraps) gdb.Frame
++
++    In this case we have two frame decorators, both of which are
++    sub-classed from FrameDecorator.  If Decorator1 just overrides the
++    'function' method, then all of the other methods are carried out
++    by the super-class FrameDecorator.  But Decorator2 may have
++    overriden other methods, so FrameDecorator will look at the
++    'base' parameter and defer to that class's methods.  And so on,
++    down the chain."""
++
++    # 'base' can refer to a gdb.Frame or another frame decorator.  In
++    # the latter case, the child class will have called the super
++    # method and _base will be an object conforming to the Frame Filter
++    # class.
++    def __init__(self, base):
++        self._base = base
++
++    @staticmethod
++    def _is_limited_frame(frame):
++        """Internal utility to determine if the frame is special or
++        limited."""
++        sal = frame.find_sal()
++
++        if (not sal.symtab or not sal.symtab.filename
++            or frame.type() == gdb.DUMMY_FRAME
++            or frame.type() == gdb.SIGTRAMP_FRAME):
++
++            return True
++
++        return False
++
++    def elided(self):
++        """Return any elided frames that this class might be
++        wrapping, or None."""
++        if hasattr(self._base, "elided"):
++            return self._base.elided()
++
++        return None
++
++    def function(self):
++        """ Return the name of the frame's function or an address of
++        the function of the frame.  First determine if this is a
++        special frame.  If not, try to determine filename from GDB's
++        frame internal function API.  Finally, if a name cannot be
++        determined return the address.  If this function returns an
++        address, GDB will attempt to determine the function name from
++        its internal minimal symbols store (for example, for inferiors
++        without debug-info)."""
++
++        # Both gdb.Frame, and FrameDecorator have a method called
++        # "function", so determine which object this is.
++        if not isinstance(self._base, gdb.Frame):
++            if hasattr(self._base, "function"):
++                # If it is not a gdb.Frame, and there is already a
++                # "function" method, use that.
++                return self._base.function()
++
++        frame = self.inferior_frame()
++
++        if frame.type() == gdb.DUMMY_FRAME:
++            return "<function called from gdb>"
++        elif frame.type() == gdb.SIGTRAMP_FRAME:
++            return "<signal handler called>"
++
++        func = frame.function()
++
++        # If we cannot determine the function name, return the
++        # address.  If GDB detects an integer value from this function
++        # it will attempt to find the function name from minimal
++        # symbols via its own internal functions.
++        if func == None:
++            pc = frame.pc()
++            return pc
++
++        return str(func)
++
++    def address(self):
++        """ Return the address of the frame's pc"""
++
++        if hasattr(self._base, "address"):
++            return self._base.address()
++
++        frame = self.inferior_frame()
++        return frame.pc()
++
++    def filename(self):
++        """ Return the filename associated with this frame, detecting
++        and returning the appropriate library name is this is a shared
++        library."""
++
++        if hasattr(self._base, "filename"):
++            return self._base.filename()
++
++        frame = self.inferior_frame()
++        sal = frame.find_sal()
++        if not sal.symtab or not sal.symtab.filename:
++            pc = frame.pc()
++            return gdb.solib_name(pc)
++        else:
++            return sal.symtab.filename
++
++    def frame_args(self):
++        """ Return an iterable of frame arguments for this frame, if
++        any.  The iterable object contains objects conforming with the
++        Symbol/Value interface.  If there are no frame arguments, or
++        if this frame is deemed to be a special case, return None."""
++
++        if hasattr(self._base, "frame_args"):
++            return self._base.frame_args()
++
++        frame = self.inferior_frame()
++        if self._is_limited_frame(frame):
++            return None
++
++        args = FrameVars(frame)
++        return args.fetch_frame_args()
++
++    def frame_locals(self):
++        """ Return an iterable of local variables for this frame, if
++        any.  The iterable object contains objects conforming with the
++        Symbol/Value interface.  If there are no frame locals, or if
++        this frame is deemed to be a special case, return None."""
++
++        if hasattr(self._base, "frame_locals"):
++            return self._base.frame_locals()
++
++        frame = self.inferior_frame()
++        if self._is_limited_frame(frame):
++            return None
++
++        args = FrameVars(frame)
++        return args.fetch_frame_locals()
++
++    def line(self):
++        """ Return line number information associated with the frame's
++        pc.  If symbol table/line information does not exist, or if
++        this frame is deemed to be a special case, return None"""
++
++        if hasattr(self._base, "line"):
++            return self._base.line()
++
++        frame = self.inferior_frame()
++        if self._is_limited_frame(frame):
++            return None
++
++        sal = frame.find_sal()
++        if (sal):
++            return sal.line
++        else:
++            return None
++
++    def inferior_frame(self):
++        """ Return the gdb.Frame underpinning this frame decorator."""
++
++        # If 'base' is a frame decorator, we want to call its inferior
++        # frame method.  If '_base' is a gdb.Frame, just return that.
++        if hasattr(self._base, "inferior_frame"):
++            return self._base.inferior_frame()
++        return self._base
++
++class SymValueWrapper(object):
++    """A container class conforming to the Symbol/Value interface
++    which holds frame locals or frame arguments."""
++    def __init__(self, symbol, value):
++        self.sym = symbol
++        self.val = value
++
++    def value(self):
++        """ Return the value associated with this symbol, or None"""
++        return self.val
++
++    def symbol(self):
++        """ Return the symbol, or Python text, associated with this
++        symbol, or None"""
++        return self.sym
++
++class FrameVars(object):
++
++    """Utility class to fetch and store frame local variables, or
++    frame arguments."""
++
++    def __init__(self, frame):
++        self.frame = frame
++        self.symbol_class = {
++            gdb.SYMBOL_LOC_STATIC: True,
++            gdb.SYMBOL_LOC_REGISTER: True,
++            gdb.SYMBOL_LOC_ARG: True,
++            gdb.SYMBOL_LOC_REF_ARG: True,
++            gdb.SYMBOL_LOC_LOCAL: True,
++	    gdb.SYMBOL_LOC_REGPARM_ADDR: True,
++	    gdb.SYMBOL_LOC_COMPUTED: True
++            }
++
++    def fetch_b(self, sym):
++        """ Local utility method to determine if according to Symbol
++        type whether it should be included in the iterator.  Not all
++        symbols are fetched, and only symbols that return
++        True from this method should be fetched."""
++
++        # SYM may be a string instead of a symbol in the case of
++        # synthetic local arguments or locals.  If that is the case,
++        # always fetch.
++        if isinstance(sym, basestring):
++            return True
++
++        sym_type = sym.addr_class
++
++        return self.symbol_class.get(sym_type, False)
++
++    def fetch_frame_locals(self):
++        """Public utility method to fetch frame local variables for
++        the stored frame.  Frame arguments are not fetched.  If there
++        are no frame local variables, return an empty list."""
++        lvars = []
++
++        block = self.frame.block()
++
++        while block != None:
++            if block.is_global or block.is_static:
++                break
++            for sym in block:
++                if sym.is_argument:
++                    continue;
++                if self.fetch_b(sym):
++                    lvars.append(SymValueWrapper(sym, None))
++
++            block = block.superblock
++
++        return lvars
++
++    def fetch_frame_args(self):
++        """Public utility method to fetch frame arguments for the
++        stored frame.  Frame arguments are the only type fetched.  If
++        there are no frame argument variables, return an empty list."""
++
++        args = []
++        block = self.frame.block()
++        while block != None:
++            if block.function != None:
++                break
++            block = block.superblock
++
++        if block != None:
++            for sym in block:
++                if not sym.is_argument:
++                    continue;
++                args.append(SymValueWrapper(sym, None))
++
++        return args
+Index: gdb-7.6/gdb/python/lib/gdb/FrameIterator.py
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ gdb-7.6/gdb/python/lib/gdb/FrameIterator.py	2013-05-20 22:25:52.114165766 +0200
+@@ -0,0 +1,45 @@
++# Copyright (C) 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 <http://www.gnu.org/licenses/>.
++
++import gdb
++import itertools
++
++class FrameIterator(object):
++    """A gdb.Frame iterator.  Iterates over gdb.Frames or objects that
++    conform to that interface."""
++
++    def __init__(self, frame_obj):
++        """Initialize a FrameIterator.
++
++        Arguments:
++            frame_obj the starting frame."""
++
++        super(FrameIterator, self).__init__()
++        self.frame = frame_obj
++
++    def __iter__(self):
++        return self
++
++    def next(self):
++        """next implementation.
++
++        Returns:
++            The next oldest frame."""
++
++        result = self.frame
++        if result is None:
++            raise StopIteration
++        self.frame = result.older()
++        return result
+Index: gdb-7.6/gdb/python/lib/gdb/frames.py
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ gdb-7.6/gdb/python/lib/gdb/frames.py	2013-05-20 22:25:52.114165766 +0200
+@@ -0,0 +1,229 @@
++# Frame-filter commands.
++# Copyright (C) 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 <http://www.gnu.org/licenses/>.
++
++"""Internal functions for working with frame-filters."""
++
++import gdb
++from gdb.FrameIterator import FrameIterator
++from gdb.FrameDecorator import FrameDecorator
++import itertools
++import collections
++
++def get_priority(filter_item):
++    """ Internal worker function to return the frame-filter's priority
++    from a frame filter object.  This is a fail free function as it is
++    used in sorting and filtering.  If a badly implemented frame
++    filter does not implement the priority attribute, return zero
++    (otherwise sorting/filtering will fail and prevent other frame
++    filters from executing).
++
++    Arguments:
++        filter_item: An object conforming to the frame filter
++                     interface.
++
++    Returns:
++        The priority of the frame filter from the "priority"
++        attribute, or zero.
++    """
++    # Do not fail here, as the sort will fail.  If a filter has not
++    # (incorrectly) set a priority, set it to zero.
++    return getattr(filter_item, "priority", 0)
++
++def set_priority(filter_item, priority):
++    """ Internal worker function to set the frame-filter's priority.
++
++    Arguments:
++        filter_item: An object conforming to the frame filter
++                     interface.
++        priority: The priority to assign as an integer.
++    """
++
++    filter_item.priority = priority
++
++def get_enabled(filter_item):
++    """ Internal worker function to return a filter's enabled state
++    from a frame filter object.  This is a fail free function as it is
++    used in sorting and filtering.  If a badly implemented frame
++    filter does not implement the enabled attribute, return False
++    (otherwise sorting/filtering will fail and prevent other frame
++    filters from executing).
++
++    Arguments:
++        filter_item: An object conforming to the frame filter
++                     interface.
++
++    Returns:
++        The enabled state of the frame filter from the "enabled"
++        attribute, or False.
++    """
++
++    # If the filter class is badly implemented when called from the
++    # Python filter command, do not cease filter operations, just set
++    # enabled to False.
++    return getattr(filter_item, "enabled", False)
++
++def set_enabled(filter_item, state):
++    """ Internal Worker function to set the frame-filter's enabled
++    state.
++
++    Arguments:
++        filter_item: An object conforming to the frame filter
++                     interface.
++        state: True or False, depending on desired state.
++    """
++
++    filter_item.enabled = state
++
++def return_list(name):
++    """ Internal Worker function to return the frame filter
++    dictionary, depending on the name supplied as an argument.  If the
++    name is not "all", "global" or "progspace", it is assumed to name
++    an object-file.
++
++    Arguments:
++        name: The name of the list, as specified by GDB user commands.
++
++    Returns:
++        A dictionary object for a single specified dictionary, or a
++        list containing all the items for "all"
++
++    Raises:
++        gdb.GdbError:  A dictionary of that name cannot be found.
++    """
++
++    # If all dictionaries are wanted in the case of "all" we
++    # cannot return a combined dictionary as keys() may clash in
++    # between different dictionaries.  As we just want all the frame
++    # filters to enable/disable them all, just return the combined
++    # items() as a list.
++    if name == "all":
++        all_dicts = gdb.frame_filters.values()
++        all_dicts = all_dicts + gdb.current_progspace().frame_filters.values()
++        for objfile in gdb.objfiles():
++            all_dicts = all_dicts + objfile.frame_filters.values()
++            return all_dicts
++
++    if name == "global":
++        return gdb.frame_filters
++    else:
++        if name == "progspace":
++            cp = gdb.current_progspace()
++            return cp.frame_filters
++        else:
++            for objfile in gdb.objfiles():
++                if name == objfile.filename:
++                    return objfile.frame_filters
++
++    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 execute_frame_filters(frame, frame_low, frame_high):
++    """ Internal function called from GDB that will execute the chain
++    of frame filters.  Each filter is executed in priority order.
++    After the execution completes, slice the iterator to frame_low -
++    frame_high range.
++
++    Arguments:
++        frame: The initial frame.
++
++        frame_low: The low range of the slice.  If this is a negative
++        integer then it indicates a backward slice (ie bt -4) which
++        counts backward from the last frame in the backtrace.
++
++        frame_high: The high range of the slice.  If this is -1 then
++        it indicates all frames until the end of the stack from
++        frame_low.
++
++    Returns:
++        frame_iterator: The sliced 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 a basic frame decorator to all gdb.Frames.  This unifies the
++    # interface.
++    frame_iterator = itertools.imap(FrameDecorator, frame_iterator)
++
++    for ff in sorted_list:
++        frame_iterator = ff.filter(frame_iterator)
++
++    # Slicing
++
++    # Is this a slice from the end of the backtrace, ie bt -2?
++    if frame_low < 0:
++        count = 0
++        slice_length = abs(frame_low)
++        # We cannot use MAXLEN argument for deque as it is 2.6 onwards
++        # and some GDB versions might be < 2.6.
++        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 backtrace.  Set to
++    # None if that is the case, to indicate to itertools.islice to
++    # slice to the end of the iterator.
++    if frame_high == -1:
++        frame_high = None
++    else:
++        # As frames start from 0, add one to frame_high so islice
++        # correctly finds the end
++        frame_high = frame_high + 1;
++
++    sliced = itertools.islice(frame_iterator, frame_low, frame_high)
++
++    return sliced
+Index: gdb-7.6/gdb/python/lib/gdb/__init__.py
+===================================================================
+--- gdb-7.6.orig/gdb/python/lib/gdb/__init__.py	2013-05-20 22:23:36.748215146 +0200
++++ gdb-7.6/gdb/python/lib/gdb/__init__.py	2013-05-20 22:25:52.114165766 +0200
+@@ -67,6 +67,8 @@ pretty_printers = []
+ 
+ # Initial type printers.
+ type_printers = []
++# Initial frame filters.
++frame_filters = {}
+ 
+ # Convenience variable to GDB's python directory
+ PYTHONDIR = os.path.dirname(os.path.dirname(__file__))
+Index: gdb-7.6/gdb/python/lib/gdb/command/frame_filters.py
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ gdb-7.6/gdb/python/lib/gdb/command/frame_filters.py	2013-05-20 22:25:52.114165766 +0200
+@@ -0,0 +1,461 @@
++# Frame-filter commands.
++# Copyright (C) 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 <http://www.gnu.org/licenses/>.
++
++"""GDB commands for working with frame-filters."""
++
++import gdb
++import copy
++from gdb.FrameIterator import FrameIterator
++from gdb.FrameDecorator import FrameDecorator
++import gdb.frames
++import itertools
++
++# GDB Commands.
++class SetFilterPrefixCmd(gdb.Command):
++    """Prefix command for 'set' frame-filter related operations."""
++
++    def __init__(self):
++        super(SetFilterPrefixCmd, self).__init__("set frame-filter",
++                                                 gdb.COMMAND_OBSCURE,
++                                                 gdb.COMPLETE_NONE, True)
++
++class ShowFilterPrefixCmd(gdb.Command):
++    """Prefix command for 'show' frame-filter related operations."""
++    def __init__(self):
++        super(ShowFilterPrefixCmd, self).__init__("show frame-filter",
++                                                  gdb.COMMAND_OBSCURE,
++                                                  gdb.COMPLETE_NONE, True)
++class InfoFrameFilter(gdb.Command):
++    """List all registered Python frame-filters.
++
++    Usage: info frame-filters
++    """
++
++    def __init__(self):
++        super(InfoFrameFilter, self).__init__("info frame-filter",
++                                              gdb.COMMAND_DATA)
++    @staticmethod
++    def enabled_string(state):
++        """Return "Yes" if filter is enabled, otherwise "No"."""
++        if state:
++            return "Yes"
++        else:
++            return "No"
++
++    def list_frame_filters(self, frame_filters):
++        """ Internal worker function to list and print frame filters
++        in a dictionary.
++
++        Arguments:
++           frame_filters: The name of the dictionary, as
++           specified by GDB user commands.
++        """
++
++        sorted_frame_filters = sorted(frame_filters.items(),
++                                      key=lambda i: gdb.frames.get_priority(i[1]),
++                                      reverse=True)
++
++        if len(sorted_frame_filters) == 0:
++            print("  No frame filters registered.")
++        else:
++            print("  Priority  Enabled  Name")
++            for frame_filter in sorted_frame_filters:
++                name = frame_filter[0]
++                try:
++                    priority = '{:<8}'.format(
++                        str(gdb.frames.get_priority(frame_filter[1])))
++                    enabled = '{:<7}'.format(
++                        self.enabled_string(gdb.frames.get_enabled(frame_filter[1])))
++                except Exception as e:
++                    print("  Error printing filter '"+name+"': "+str(e))
++                else:
++                    print("  %s  %s  %s" % (priority, enabled, name))
++
++    def print_list(self, title, filter_list, blank_line):
++        print(title)
++        self.list_frame_filters(filter_list)
++        if blank_line:
++            print("")
++
++    def invoke(self, arg, from_tty):
++        self.print_list("global frame-filters:", gdb.frame_filters, True)
++
++        cp = gdb.current_progspace()
++        self.print_list("progspace %s frame-filters:" % cp.filename,
++                        cp.frame_filters, True)
++
++        for objfile in gdb.objfiles():
++            self.print_list("objfile %s frame-filters:" % objfile.filename,
++                            objfile.frame_filters, False)
++
++# Internal enable/disable functions.
++
++def _enable_parse_arg(cmd_name, arg):
++    """ Internal worker function to take an argument from
++    enable/disable and return a tuple of arguments.
++
++    Arguments:
++        cmd_name: Name of the command invoking this function.
++        args: The argument as a string.
++
++    Returns:
++        A tuple containing the dictionary, and the argument, or just
++        the dictionary in the case of "all".
++    """
++
++    argv = gdb.string_to_argv(arg);
++    argc = len(argv)
++    if argv[0] == "all" and argc > 1:
++        raise gdb.GdbError(cmd_name + ": with 'all' " \
++                          "you may not specify a filter.")
++    else:
++        if argv[0] != "all" and argc != 2:
++            raise gdb.GdbError(cmd_name + " takes exactly two arguments.")
++
++    return argv
++
++def _do_enable_frame_filter(command_tuple, flag):
++    """Worker for enabling/disabling frame_filters.
++
++    Arguments:
++        command_type: A tuple with the first element being the
++                      frame filter dictionary, and the second being
++                      the frame filter name.
++        flag: True for Enable, False for Disable.
++    """
++
++    list_op = command_tuple[0]
++    op_list = gdb.frames.return_list(list_op)
++
++    if list_op == "all":
++        for item in op_list:
++            gdb.frames.set_enabled(item, flag)
++    else:
++        frame_filter = command_tuple[1]
++        try:
++            ff = op_list[frame_filter]
++        except KeyError:
++            msg = "frame-filter '" + str(name) + "' not found."
++            raise gdb.GdbError(msg)
++
++        gdb.frames.set_enabled(ff, flag)
++
++def _complete_frame_filter_list(text, word, all_flag):
++    """Worker for frame filter dictionary name completion.
++
++    Arguments:
++        text: The full text of the command line.
++        word: The most recent word of the command line.
++        all_flag: Whether to include the word "all" in completion.
++
++    Returns:
++        A list of suggested frame filter dictionary name completions
++        from text/word analysis.  This list can be empty when there
++        are no suggestions for completion.
++        """
++    if all_flag == True:
++        filter_locations = ["all", "global", "progspace"]
++    else:
++        filter_locations = ["global", "progspace"]
++    for objfile in gdb.objfiles():
++        filter_locations.append(objfile.filename)
++
++    # If the user just asked for completions with no completion
++    # hints, just return all the frame filter dictionaries we know
++    # about.
++    if (text == ""):
++        return filter_locations
++
++    # Otherwise filter on what we know.
++    flist = filter(lambda x,y=text:x.startswith(y), filter_locations)
++
++    # If we only have one completion, complete it and return it.
++    if len(flist) == 1:
++        flist[0] = flist[0][len(text)-len(word):]
++
++    # Otherwise, return an empty list, or a list of frame filter
++    # dictionaries that the previous filter operation returned.
++    return flist
++
++def _complete_frame_filter_name(word, printer_dict):
++    """Worker for frame filter name completion.
++
++    Arguments:
++
++        word: The most recent word of the command line.
++
++        printer_dict: The frame filter dictionary to search for frame
++        filter name completions.
++
++        Returns: A list of suggested frame filter name completions
++        from word analysis of the frame filter dictionary.  This list
++        can be empty when there are no suggestions for completion.
++    """
++
++    printer_keys = printer_dict.keys()
++    if (word == ""):
++        return printer_keys
++
++    flist = filter(lambda x,y=word:x.startswith(y), printer_keys)
++    return flist
++
++class EnableFrameFilter(gdb.Command):
++    """GDB command to disable the specified frame-filter.
++
++    Usage: enable frame-filter enable DICTIONARY [NAME]
++
++    DICTIONARY is the name of the frame filter dictionary on which to
++    operate.  If dictionary is set to "all", perform operations on all
++    dictionaries.  Named dictionaries are: "global" for the global
++    frame filter dictionary, "progspace" for the program space's frame
++    filter dictionary.  If either all, or the two named dictionaries
++    are not specified, the dictionary name is assumed to be the name
++    of the object-file name.
++
++    NAME matches the name of the frame-filter to operate on.  If
++    DICTIONARY is "all", NAME is ignored.
++    """
++    def __init__(self):
++        super(EnableFrameFilter, self).__init__("enable frame-filter",
++                                                 gdb.COMMAND_DATA)
++    def complete(self, text, word):
++        """Completion function for both frame filter dictionary, and
++        frame filter name."""
++        if text.count(" ") == 0:
++            return _complete_frame_filter_list(text, word, True)
++        else:
++            printer_list = gdb.frames.return_list(text.split()[0].rstrip())
++            return _complete_frame_filter_name(word, printer_list)
++
++    def invoke(self, arg, from_tty):
++        command_tuple = _enable_parse_arg("enable frame-filter", arg)
++        _do_enable_frame_filter(command_tuple, True)
++
++
++class DisableFrameFilter(gdb.Command):
++    """GDB command to disable the specified frame-filter.
++
++    Usage: disable frame-filter disable DICTIONARY [NAME]
++
++    DICTIONARY is the name of the frame filter dictionary on which to
++    operate.  If dictionary is set to "all", perform operations on all
++    dictionaries.  Named dictionaries are: "global" for the global
++    frame filter dictionary, "progspace" for the program space's frame
++    filter dictionary.  If either all, or the two named dictionaries
++    are not specified, the dictionary name is assumed to be the name
++    of the object-file name.
++
++    NAME matches the name of the frame-filter to operate on.  If
++    DICTIONARY is "all", NAME is ignored.
++    """
++    def __init__(self):
++        super(DisableFrameFilter, self).__init__("disable frame-filter",
++                                                  gdb.COMMAND_DATA)
++
++    def complete(self, text, word):
++        """Completion function for both frame filter dictionary, and
++        frame filter name."""
++        if text.count(" ") == 0:
++            return _complete_frame_filter_list(text, word, True)
++        else:
++            printer_list = gdb.frames.return_list(text.split()[0].rstrip())
++            return _complete_frame_filter_name(word, printer_list)
++
++    def invoke(self, arg, from_tty):
++        command_tuple = _enable_parse_arg("disable frame-filter", arg)
++        _do_enable_frame_filter(command_tuple, False)
++
++class SetFrameFilterPriority(gdb.Command):
++    """GDB command to set the priority of the specified frame-filter.
++
++    Usage: set frame-filter priority DICTIONARY NAME PRIORITY
++
++    DICTIONARY is the name of the frame filter dictionary on which to
++    operate.  Named dictionaries are: "global" for the global frame
++    filter dictionary, "progspace" for the program space's framefilter
++    dictionary.  If either of these two are not specified, the
++    dictionary name is assumed to be the name of the object-file name.
++
++    NAME matches the name of the frame filter to operate on.
++
++    PRIORITY is the an integer to assign the new priority to the frame
++    filter.
++    """
++
++    def __init__(self):
++        super(SetFrameFilterPriority, self).__init__("set frame-filter " \
++                                                     "priority",
++                                                     gdb.COMMAND_DATA)
++
++    def _parse_pri_arg(self, arg):
++        """Internal worker to parse a priority from a tuple.
++
++        Arguments:
++            arg: Tuple which contains the arguments from the command.
++
++        Returns:
++            A tuple containing the dictionary, name and priority from
++            the arguments.
++
++        Raises:
++            gdb.GdbError: An error parsing the arguments.
++        """
++
++        argv = gdb.string_to_argv(arg);
++        argc = len(argv)
++        if argc != 3:
++            print("set frame-filter priority " \
++                  "takes exactly three arguments.")
++            return None
++
++        return argv
++
++    def _set_filter_priority(self, command_tuple):
++        """Internal worker for setting priority of frame-filters, by
++        parsing a tuple and calling _set_priority with the parsed
++        tuple.
++
++        Arguments:
++            command_tuple: Tuple which contains the arguments from the
++                           command.
++        """
++
++        list_op = command_tuple[0]
++        frame_filter = command_tuple[1]
++        priority = command_tuple[2]
++
++        op_list = gdb.frames.return_list(list_op)
++
++        try:
++            ff = op_list[frame_filter]
++        except KeyError:
++            msg = "frame-filter '" + str(name) + "' not found."
++            raise gdb.GdbError(msg)
++
++        gdb.frames.set_priority(ff, priority)
++
++    def complete(self, text, word):
++        """Completion function for both frame filter dictionary, and
++        frame filter name."""
++        if text.count(" ") == 0:
++            return _complete_frame_filter_list(text, word, False)
++        else:
++            printer_list = gdb.frames.return_list(text.split()[0].rstrip())
++            return _complete_frame_filter_name(word, printer_list)
++
++    def invoke(self, arg, from_tty):
++        command_tuple = self._parse_pri_arg(arg)
++        if command_tuple != None:
++            self._set_filter_priority(command_tuple)
++
++class ShowFrameFilterPriority(gdb.Command):
++    """GDB command to show the priority of the specified frame-filter.
++
++    Usage: show frame-filter priority DICTIONARY NAME
++
++    DICTIONARY is the name of the frame filter dictionary on which to
++    operate.  Named dictionaries are: "global" for the global frame
++    filter dictionary, "progspace" for the program space's framefilter
++    dictionary.  If either of these two are not specified, the
++    dictionary name is assumed to be the name of the object-file name.
++
++    NAME matches the name of the frame-filter to operate on.
++    """
++
++    def __init__(self):
++        super(ShowFrameFilterPriority, self).__init__("show frame-filter " \
++                                                      "priority",
++                                                      gdb.COMMAND_DATA)
++
++    def _parse_pri_arg(self, arg):
++        """Internal worker to parse a dictionary and name from a
++        tuple.
++
++        Arguments:
++            arg: Tuple which contains the arguments from the command.
++
++        Returns:
++            A tuple containing the dictionary,  and frame filter name.
++
++        Raises:
++            gdb.GdbError: An error parsing the arguments.
++        """
++
++        argv = gdb.string_to_argv(arg);
++        argc = len(argv)
++        if argc != 2:
++            print("show frame-filter priority " \
++                  "takes exactly two arguments.")
++            return None
++
++        return argv
++
++    def get_filter_priority(self, frame_filters, name):
++        """Worker for retrieving the priority of frame_filters.
++
++        Arguments:
++            frame_filters: Name of frame filter dictionary.
++            name: object to select printers.
++
++        Returns:
++            The priority of the frame filter.
++
++        Raises:
++            gdb.GdbError: A frame filter cannot be found.
++        """
++
++        op_list = gdb.frames.return_list(frame_filters)
++
++        try:
++            ff = op_list[name]
++        except KeyError:
++            msg = "frame-filter '" + str(name) + "' not found."
++            raise gdb.GdbError(msg)
++
++        return gdb.frames.get_priority(ff)
++
++    def complete(self, text, word):
++        """Completion function for both frame filter dictionary, and
++        frame filter name."""
++
++        if text.count(" ") == 0:
++            return _complete_frame_filter_list(text, word, False)
++        else:
++            printer_list = frame._return_list(text.split()[0].rstrip())
++            return _complete_frame_filter_name(word, printer_list)
++
++    def invoke(self, arg, from_tty):
++        command_tuple = self._parse_pri_arg(arg)
++        if command_tuple == None:
++            return
++        filter_name = command_tuple[1]
++        list_name = command_tuple[0]
++        try:
++            priority = self.get_filter_priority(list_name, filter_name);
++        except Exception as e:
++            print("Error printing filter priority for '"+name+"':"+str(e))
++        else:
++            print("Priority of filter '" + filter_name + "' in list '" \
++                + list_name + "' is: " + str(priority))
++
++# Register commands
++SetFilterPrefixCmd()
++ShowFilterPrefixCmd()
++InfoFrameFilter()
++EnableFrameFilter()
++DisableFrameFilter()
++SetFrameFilterPriority()
++ShowFrameFilterPriority()
+Index: gdb-7.6/gdb/testsuite/gdb.python/py-framefilter-gdb.py.in
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ gdb-7.6/gdb/testsuite/gdb.python/py-framefilter-gdb.py.in	2013-05-20 22:25:52.114165766 +0200
+@@ -0,0 +1,48 @@
++# Copyright (C) 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 <http://www.gnu.org/licenses/>.
++
++# This file is part of the GDB testsuite.  It tests Python-based
++# frame-filters.
++import gdb
++import itertools
++from gdb.FrameDecorator import FrameDecorator
++
++
++class FrameObjFile ():
++
++    def __init__ (self):
++        self.name = "Filter1"
++        self.priority = 1
++        self.enabled = False
++        gdb.current_progspace().frame_filters ["Progspace" + self.name] = self
++        gdb.current_objfile().frame_filters ["ObjectFile" + self.name] = self
++
++    def filter (self, frame_iter):
++        return frame_iter
++
++class FrameObjFile2 ():
++
++    def __init__ (self):
++        self.name = "Filter2"
++        self.priority = 100
++        self.enabled = True
++        gdb.current_progspace().frame_filters ["Progspace" + self.name] = self
++        gdb.current_objfile().frame_filters ["ObjectFile" + self.name] = self
++
++    def filter (self, frame_iter):
++        return frame_iter
++
++FrameObjFile()
++FrameObjFile2()
+Index: gdb-7.6/gdb/testsuite/gdb.python/py-framefilter-mi.c
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ gdb-7.6/gdb/testsuite/gdb.python/py-framefilter-mi.c	2013-05-20 22:25:52.114165766 +0200
+@@ -0,0 +1,138 @@
++/* This testcase is part of GDB, the GNU debugger.
++
++   Copyright 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 <http://www.gnu.org/licenses/>.  */
++
++#include <stdlib.h>
++
++void funca(void);
++int count = 0;
++
++typedef struct
++{
++  char *nothing;
++  int f;
++  short s;
++} foobar;
++
++void end_func (int foo, char *bar, foobar *fb, foobar bf)
++{
++  const char *str = "The End";
++  const char *st2 = "Is Near";
++  int b = 12;
++  short c = 5;
++  {
++    int d = 15;
++    int e = 14;
++    const char *foo = "Inside block";
++    {
++      int f = 42;
++      int g = 19;
++      const char *bar = "Inside block x2";
++      {
++	short h = 9;
++	h = h +1;  /* Inner test breakpoint  */
++      }
++    }
++  }
++
++  return; /* Backtrace end breakpoint */
++}
++
++void funcb(int j)
++{
++  struct foo
++  {
++    int a;
++    int b;
++  };
++
++  struct foo bar;
++
++  bar.a = 42;
++  bar.b = 84;
++
++  funca();
++  return;
++}
++
++void funca(void)
++{
++  foobar fb;
++  foobar *bf;
++
++  if (count < 10)
++    {
++      count++;
++      funcb(count);
++    }
++
++  fb.nothing = "Foo Bar";
++  fb.f = 42;
++  fb.s = 19;
++
++  bf = malloc (sizeof (foobar));
++  bf->nothing = malloc (128);
++  bf->nothing = "Bar Foo";
++  bf->f = 24;
++  bf->s = 91;
++
++  end_func(21, "Param", bf, fb);
++  free (bf->nothing);
++  free (bf);
++  return;
++}
++
++
++void func1(void)
++{
++  funca();
++  return;
++}
++
++int func2(void)
++{
++  func1();
++  return 1;
++}
++
++void func3(int i)
++{
++  func2();
++
++  return;
++}
++
++int func4(int j)
++{
++  func3(j);
++
++  return 2;
++}
++
++int func5(int f, int d)
++{
++  int i = 0;
++  char *random = "random";
++  i=i+f;
++
++  func4(i);
++  return i;
++}
++
++main()
++{
++  func5(3,5);
++}
+Index: gdb-7.6/gdb/testsuite/gdb.python/py-framefilter-mi.exp
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ gdb-7.6/gdb/testsuite/gdb.python/py-framefilter-mi.exp	2013-05-20 22:25:52.115165766 +0200
+@@ -0,0 +1,179 @@
++# Copyright (C) 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 <http://www.gnu.org/licenses/>.
++
++# This file is part of the GDB testsuite.  It tests Python-based
++# frame-filters.
++load_lib mi-support.exp
++load_lib gdb-python.exp
++
++set MIFLAGS "-i=mi2"
++
++gdb_exit
++if [mi_gdb_start] {
++    continue
++}
++
++standard_testfile py-framefilter-mi.c
++set pyfile py-framefilter.py
++
++if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-DMI}] != "" } {
++    untested ${testfile}.exp
++    return -1
++}
++
++mi_delete_breakpoints
++mi_gdb_reinitialize_dir $srcdir/$subdir
++mi_gdb_load ${binfile}
++
++if {[lsearch -exact [mi_get_features] python] < 0} {
++    unsupported "python support is disabled"
++    return -1
++}
++
++mi_runto main
++
++set remote_python_file [remote_download host ${srcdir}/${subdir}/${pyfile}]
++
++mi_gdb_test "python execfile ('${remote_python_file}')" ".*\\^done." \
++    "Load python file"
++
++# Multiple blocks test
++mi_continue_to_line [gdb_get_line_number {Inner test breakpoint} ${srcfile}] \
++  "step to breakpoint"
++
++mi_gdb_test "-stack-list-locals --all-values" \
++    "\\^done,locals=\\\[{name=\"h\",value=\"9\"},{name=\"f\",value=\"42\"},{name=\"g\",value=\"19\"},{name=\"bar\",value=\"$hex \\\\\"Inside block x2\\\\\"\"},{name=\"d\",value=\"15\"},{name=\"e\",value=\"14\"},{name=\"foo\",value=\"$hex \\\\\"Inside block\\\\\"\"},{name=\"str\",value=\"$hex \\\\\"The End\\\\\"\"},{name=\"st2\",value=\"$hex \\\\\"Is Near\\\\\"\"},{name=\"b\",value=\"12\"},{name=\"c\",value=\"5\"}\\\]" \
++    "stack-list-locals --all-values"
++
++mi_gdb_test "-enable-frame-filters" ".*\\^done." "enable frame filters"
++mi_gdb_test "-stack-list-locals --all-values" \
++    "\\^done,locals=\\\[{name=\"h\",value=\"9\"},{name=\"f\",value=\"42\"},{name=\"g\",value=\"19\"},{name=\"bar\",value=\"$hex \\\\\"Inside block x2\\\\\"\"},{name=\"d\",value=\"15\"},{name=\"e\",value=\"14\"},{name=\"foo\",value=\"$hex \\\\\"Inside block\\\\\"\"},{name=\"str\",value=\"$hex \\\\\"The End\\\\\"\"},{name=\"st2\",value=\"$hex \\\\\"Is Near\\\\\"\"},{name=\"b\",value=\"12\"},{name=\"c\",value=\"5\"}\\\]" \
++    "stack-list-locals --all-values frame filters enabled"
++
++mi_continue_to_line [gdb_get_line_number {Backtrace end breakpoint} ${srcfile}] \
++  "step to breakpoint"
++
++mi_gdb_test "-stack-list-frames" \
++    "\\^done,stack=\\\[frame={level=\"0\",addr=\"$hex\",func=\"cnuf_dne\".*},frame={level=\"1\",addr=\"$hex\",func=\"acnuf\".*},frame={level=\"2\",addr=\"$hex\",func=\"bcnuf\".*},frame={level=\"3\",addr=\"$hex\",func=\"acnuf\".*},frame={level=\"22\",addr=\"$hex\",func=\"1cnuf\".*,children=\\\[frame={level=\"23\",addr=\"$hex\",func=\"func2\".*}\\\]},frame={level=\"24\",addr=\"$hex\",func=\"3cnuf\".*},frame={level=\"27\",addr=\"$hex\",func=\"niam\".*}\\\].*" \
++    "filtered stack listing"
++mi_gdb_test "-stack-list-frames 0 3" \
++    "\\^done,stack=\\\[frame={level=\"0\",addr=\"$hex\",func=\"cnuf_dne\".*},frame={level=\"1\",addr=\"$hex\",func=\"acnuf\".*},frame={level=\"2\",addr=\"$hex\",func=\"bcnuf\".*},frame={level=\"3\",addr=\"$hex\",func=\"acnuf\".*}\\\]" \
++    "filtered stack list 0 3"
++mi_gdb_test "-stack-list-frames 22 24" \
++    "\\^done,stack=\\\[frame={level=\"22\",addr=\"$hex\",func=\"1cnuf\".*,children=\\\[frame={level=\"23\",addr=\"$hex\",func=\"func2\".*}\\\]},frame={level=\"24\",addr=\"$hex\",func=\"3cnuf\".*}\\\]" \
++    "filtered stack list 22 24"
++
++#stack list arguments
++
++
++mi_gdb_test "-stack-list-arguments 0" \
++    "\\^done,stack-args=\\\[frame={level=\"0\",args=\\\[name=\"foo\",name=\"bar\",name=\"fb\",name=\"bf\"\\\]},frame={level=\"1\",args=\\\[\\\]},frame={level=\"2\",args=\\\[name=\"j\"\\\]},.*frame={level=\"22\",args=\\\[\\\],children=\\\[frame={level=\"23\",args=\\\[\\\]}\\\]},.*frame={level=\"26\",args=\\\[name=\"f\",name=\"d\"\\\]},frame={level=\"27\",args=\\\[\\\]}\\\]" \
++    "stack-list-arguments 0"
++
++mi_gdb_test "-stack-list-arguments --no-frame-filters 0" \
++    "\\^done,stack-args=\\\[frame={level=\"0\",args=\\\[name=\"foo\",name=\"bar\",name=\"fb\",name=\"bf\"\\\]},frame={level=\"1\",args=\\\[\\\]},frame={level=\"2\",args=\\\[name=\"j\"\\\]},.*frame={level=\"22\",args=\\\[\\\]},frame={level=\"23\",args=\\\[\\\]},.*frame={level=\"26\",args=\\\[name=\"f\",name=\"d\"\\\]},frame={level=\"27\",args=\\\[\\\]}\\\]" \
++    "stack-list-arguments --no-frame-filters 0"
++
++mi_gdb_test "-stack-list-arguments 0 0 3" \
++    "\\^done,stack-args=\\\[frame={level=\"0\",args=\\\[name=\"foo\",name=\"bar\",name=\"fb\",name=\"bf\"\\\]},frame={level=\"1\",args=\\\[\\\]},frame={level=\"2\",args=\\\[name=\"j\"\\\]},frame={level=\"3\",args=\\\[\\\]}\\\]" \
++    "stack-list-arguments 0 0 3"
++
++mi_gdb_test "-stack-list-arguments 0 22 27" \
++    "\\^done,stack-args=\\\[frame={level=\"22\",args=\\\[\\\],children=\\\[frame={level=\"23\",args=\\\[\\\]}\\\]},.*frame={level=\"26\",args=\\\[name=\"f\",name=\"d\"\\\]},frame={level=\"27\",args=\\\[\\\]}\\\]" \
++    "stack-list-arguments 0 22 27"
++
++mi_gdb_test "-stack-list-arguments 1" \
++    "\\^done,stack-args=\\\[frame={level=\"0\",args=\\\[{name=\"foo\",value=\"21\"},{name=\"bar\",value=\"$hex \\\\\"Param\\\\\"\"},{name=\"fb\",value=\"$hex\"},{name=\"bf\",value=\"{nothing = $hex \\\\\"Foo Bar\\\\\", f = 42, s = 19}\"}\\\]},frame={level=\"1\",args=\\\[\\\]},frame={level=\"2\",args=\\\[{name=\"j\",value=\"10\"}\\\]},.*frame={level=\"22\",args=\\\[\\\],children=\\\[frame={level=\"23\",args=\\\[\\\]}\\\]},.*frame={level=\"26\",args=\\\[{name=\"f\",value=\"3\"},{name=\"d\",value=\"5\"}\\\]},frame={level=\"27\",args=\\\[\\\]}\\\]" \
++    "stack-list-arguments 1"
++
++mi_gdb_test "-stack-list-arguments --no-frame-filters 1" \
++    "\\^done,stack-args=\\\[frame={level=\"0\",args=\\\[{name=\"foo\",value=\"21\"},{name=\"bar\",value=\"$hex \\\\\"Param\\\\\"\"},{name=\"fb\",value=\"$hex\"},{name=\"bf\",value=\"{nothing = $hex \\\\\"Foo Bar\\\\\", f = 42, s = 19}\"}\\\]},frame={level=\"1\",args=\\\[\\\]},frame={level=\"2\",args=\\\[{name=\"j\",value=\"10\"}\\\]},.*frame={level=\"22\",args=\\\[\\\]},frame={level=\"23\",args=\\\[\\\]},.*frame={level=\"26\",args=\\\[{name=\"f\",value=\"3\"},{name=\"d\",value=\"5\"}\\\]},frame={level=\"27\",args=\\\[\\\]}\\\]" \
++    "stack-list-arguments --no-frame-filters 1"
++
++
++mi_gdb_test "-stack-list-arguments 1 0 3" \
++    "\\^done,stack-args=\\\[frame={level=\"0\",args=\\\[{name=\"foo\",value=\"21\"},{name=\"bar\",value=\"$hex \\\\\"Param\\\\\"\"},{name=\"fb\",value=\"$hex\"},{name=\"bf\",value=\"{nothing = $hex \\\\\"Foo Bar\\\\\", f = 42, s = 19}\"}\\\]},frame={level=\"1\",args=\\\[\\\]},frame={level=\"2\",args=\\\[{name=\"j\",value=\"10\"}\\\]},frame={level=\"3\",args=\\\[\\\]}\\\]" \
++    "stack-list-arguments 1 0 3"
++
++mi_gdb_test "-stack-list-arguments 1 22 27" \
++    "\\^done,stack-args=\\\[frame={level=\"22\",args=\\\[\\\],children=\\\[frame={level=\"23\",args=\\\[\\\]}\\\]},.*frame={level=\"26\",args=\\\[{name=\"f\",value=\"3\"},{name=\"d\",value=\"5\"}\\\]},frame={level=\"27\",args=\\\[\\\]}\\\]" \
++    "stack-list-arguments 1 22 27"
++
++mi_gdb_test "-stack-list-arguments 2" \
++    "\\^done,stack-args=\\\[frame={level=\"0\",args=\\\[{name=\"foo\",type=\"int\",value=\"21\"},{name=\"bar\",type=\"char \\\*\",value=\"$hex \\\\\"Param\\\\\"\"},{name=\"fb\",type=\"foobar \\\*\",value=\"$hex\"},{name=\"bf\",type=\"foobar\"\}\\\]},frame={level=\"1\",args=\\\[\\\]},frame={level=\"2\",args=\\\[{name=\"j\",type=\"int\",value=\"10\"}\\\]},.*frame={level=\"22\",args=\\\[\\\],children=\\\[frame={level=\"23\",args=\\\[\\\]}\\\]},.*frame={level=\"26\",args=\\\[{name=\"f\",type=\"int\",value=\"3\"},{name=\"d\",type=\"int\",value=\"5\"}\\\]},frame={level=\"27\",args=\\\[\\\]}\\\]" \
++    "stack-list-arguments 2"
++
++mi_gdb_test "-stack-list-arguments --no-frame-filters 2" \
++    "\\^done,stack-args=\\\[frame={level=\"0\",args=\\\[{name=\"foo\",type=\"int\",value=\"21\"},{name=\"bar\",type=\"char \\\*\",value=\"$hex \\\\\"Param\\\\\"\"},{name=\"fb\",type=\"foobar \\\*\",value=\"$hex\"},{name=\"bf\",type=\"foobar\"}\\\]},frame={level=\"1\",args=\\\[\\\]},frame={level=\"2\",args=\\\[{name=\"j\",type=\"int\",value=\"10\"}\\\]},.*frame={level=\"22\",args=\\\[\\\]},.*frame={level=\"26\",args=\\\[{name=\"f\",type=\"int\",value=\"3\"},{name=\"d\",type=\"int\",value=\"5\"}\\\]},frame={level=\"27\",args=\\\[\\\]}\\\]" \
++    "stack-list-arguments --no-frame-filters 2"
++
++
++mi_gdb_test "-stack-list-arguments 2 0 3" \
++    "\\^done,stack-args=\\\[frame={level=\"0\",args=\\\[{name=\"foo\",type=\"int\",value=\"21\"},{name=\"bar\",type=\"char \\\*\",value=\"$hex \\\\\"Param\\\\\"\"},{name=\"fb\",type=\"foobar \\\*\",value=\"$hex\"},{name=\"bf\",type=\"foobar\"}\\\]},frame={level=\"1\",args=\\\[\\\]},frame={level=\"2\",args=\\\[{name=\"j\",type=\"int\",value=\"10\"}\\\]},frame={level=\"3\",args=\\\[\\\]}\\\]" \
++    "stack-list-arguments 2 0 3"
++
++mi_gdb_test "-stack-list-arguments 2 22 27" \
++    "\\^done,stack-args=\\\[frame={level=\"22\",args=\\\[\\\],children=\\\[frame={level=\"23\",args=\\\[\\\]}\\\]},.*frame={level=\"26\",args=\\\[{name=\"f\",type=\"int\",value=\"3\"},{name=\"d\",type=\"int\",value=\"5\"}\\\]},frame={level=\"27\",args=\\\[\\\]}\\\]" \
++    "stack-list-arguments 2 22 27"
++
++mi_gdb_test "-stack-list-arguments --no-frame-filters 2 22 27" \
++    "\\^done,stack-args=\\\[frame={level=\"22\",args=\\\[\\\]},frame={level=\"23\",args=\\\[\\\]},.*frame={level=\"26\",args=\\\[{name=\"f\",type=\"int\",value=\"3\"},{name=\"d\",type=\"int\",value=\"5\"}\\\]},frame={level=\"27\",args=\\\[\\\]}\\\]" \
++    "stack-list-arguments --no-frame-filters 2 22 27"
++
++#stack-list-locals
++mi_gdb_test "-stack-list-locals --no-frame-filters 0" \
++    "\\^done,locals=\\\[name=\"str\",name=\"st2\",name=\"b\",name=\"c\"\\\]" \
++    "stack-list-locals --no-frame-filters 0"
++
++mi_gdb_test "-stack-list-locals --no-frame-filters 1" \
++    "\\^done,locals=\\\[{name=\"str\",value=\"$hex \\\\\"The End\\\\\"\"},{name=\"st2\",value=\"$hex \\\\\"Is Near\\\\\"\"},{name=\"b\",value=\"12\"},{name=\"c\",value=\"5\"}\\\]" \
++    "stack-list-locals --no-frame-filters 1"
++
++mi_gdb_test "-stack-list-locals --no-frame-filters 2" \
++    "\\^done,locals=\\\[{name=\"str\",type=\"const char \\\*\",value=\"$hex \\\\\"The End\\\\\"\"},{name=\"st2\",type=\"const char \\\*\",value=\"$hex \\\\\"Is Near\\\\\"\"},{name=\"b\",type=\"int\",value=\"12\"},{name=\"c\",type=\"short\",value=\"5\"}\\\]" \
++    "stack-list-locals --no-frame-filters 2"
++
++mi_gdb_test "-stack-list-locals --no-frame-filters --no-values" \
++    "\\^done,locals=\\\[name=\"str\",name=\"st2\",name=\"b\",name=\"c\"\\\]" \
++    "stack-list-locals --no-frame-filters --no-values"
++
++mi_gdb_test "-stack-list-locals --no-frame-filters --all-values" \
++    "\\^done,locals=\\\[{name=\"str\",value=\"$hex \\\\\"The End\\\\\"\"},{name=\"st2\",value=\"$hex \\\\\"Is Near\\\\\"\"},{name=\"b\",value=\"12\"},{name=\"c\",value=\"5\"}\\\]" \
++    "stack-list-locals --no-frame-filters --all-values"
++
++mi_gdb_test "-stack-list-locals --no-frame-filters --simple-values" \
++    "\\^done,locals=\\\[{name=\"str\",type=\"const char \\\*\",value=\"$hex \\\\\"The End\\\\\"\"},{name=\"st2\",type=\"const char \\\*\",value=\"$hex \\\\\"Is Near\\\\\"\"},{name=\"b\",type=\"int\",value=\"12\"},{name=\"c\",type=\"short\",value=\"5\"}\\\]" \
++    "stack-list-locals --no-frame-filters --simple-values"
++
++mi_gdb_test "-stack-list-locals 0" \
++    "\\^done,locals=\\\[name=\"str\",name=\"st2\",name=\"b\",name=\"c\"\\\]" \
++    "stack-list-locals 0"
++
++mi_gdb_test "-stack-list-locals 1" \
++    "\\^done,locals=\\\[{name=\"str\",value=\"$hex \\\\\"The End\\\\\"\"},{name=\"st2\",value=\"$hex \\\\\"Is Near\\\\\"\"},{name=\"b\",value=\"12\"},{name=\"c\",value=\"5\"}\\\]" \
++    "stack-list-locals 1"
++
++mi_gdb_test "-stack-list-locals 2" \
++    "\\^done,locals=\\\[{name=\"str\",type=\"const char \\\*\",value=\"$hex \\\\\"The End\\\\\"\"},{name=\"st2\",type=\"const char \\\*\",value=\"$hex \\\\\"Is Near\\\\\"\"},{name=\"b\",type=\"int\",value=\"12\"},{name=\"c\",type=\"short\",value=\"5\"}\\\]" \
++    "stack-list-locals 2"
++
++# stack-list-variables
++mi_gdb_test "-stack-list-variables --no-frame-filters 0" \
++    "\\^done,variables=\\\[{name=\"foo\",arg=\"1\"},{name=\"bar\",arg=\"1\"},{name=\"fb\",arg=\"1\"},{name=\"bf\",arg=\"1\"},{name=\"str\"},{name=\"st2\"},{name=\"b\"},{name=\"c\"}\\\]" \
++    "stack-list-variables --no-frame-filters 0"
++
++mi_gdb_test "-stack-list-variables 0" \
++    "\\^done,variables=\\\[{name=\"foo\",arg=\"1\"},{name=\"bar\",arg=\"1\"},{name=\"fb\",arg=\"1\"},{name=\"bf\",arg=\"1\"},{name=\"str\"},{name=\"st2\"},{name=\"b\"},{name=\"c\"}\\\]" \
++    "stack-list-variables 0"
+Index: gdb-7.6/gdb/testsuite/gdb.python/py-framefilter.c
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ gdb-7.6/gdb/testsuite/gdb.python/py-framefilter.c	2013-05-20 22:25:52.115165766 +0200
+@@ -0,0 +1,155 @@
++/* This testcase is part of GDB, the GNU debugger.
++
++   Copyright 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 <http://www.gnu.org/licenses/>.  */
++
++#include <stdlib.h>
++
++void funca(void);
++int count = 0;
++
++typedef struct
++{
++  char *nothing;
++  int f;
++  short s;
++} foobar;
++
++void end_func (int foo, char *bar, foobar *fb, foobar bf)
++{
++  const char *str = "The End";
++  const char *st2 = "Is Near";
++  int b = 12;
++  short c = 5;
++
++  {
++    int d = 15;
++    int e = 14;
++    const char *foo = "Inside block";
++    {
++      int f = 42;
++      int g = 19;
++      const char *bar = "Inside block x2";
++      {
++	short h = 9;
++	h = h +1;  /* Inner test breakpoint  */
++      }
++    }
++  }
++
++  return; /* Backtrace end breakpoint */
++}
++
++void funcb(int j)
++{
++  struct foo
++  {
++    int a;
++    int b;
++  };
++
++  struct foo bar;
++
++  bar.a = 42;
++  bar.b = 84;
++
++  funca();
++  return;
++}
++
++void funca(void)
++{
++  foobar fb;
++  foobar *bf = NULL;
++
++  if (count < 10)
++    {
++      count++;
++      funcb(count);
++    }
++
++  fb.nothing = "Foo Bar";
++  fb.f = 42;
++  fb.s = 19;
++
++  bf = alloca (sizeof (foobar));
++  bf->nothing = alloca (128);
++  bf->nothing = "Bar Foo";
++  bf->f = 24;
++  bf->s = 91;
++
++  end_func(21, "Param", bf, fb);
++  return;
++}
++
++
++void func1(void)
++{
++  funca();
++  return;
++}
++
++int func2(int f)
++{
++  int c;
++  const char *elided = "Elided frame";
++  foobar fb;
++  foobar *bf = NULL;
++
++  fb.nothing = "Elided Foo Bar";
++  fb.f = 84;
++  fb.s = 38;
++
++  bf = alloca (sizeof (foobar));
++  bf->nothing = alloca (128);
++  bf->nothing = "Elided Bar Foo";
++  bf->f = 48;
++  bf->s = 182;
++
++  func1();
++  return 1;
++}
++
++void func3(int i)
++{
++  func2(i);
++
++  return;
++}
++
++int func4(int j)
++{
++  func3(j);
++
++  return 2;
++}
++
++int func5(int f, int d)
++{
++  int i = 0;
++  char *random = "random";
++  i=i+f;
++
++  func4(i);
++  return i;
++}
++
++main()
++{
++  int z = 32;
++  int y = 44;
++  const char *foo1 = "Test";
++  func5(3,5);
++}
+Index: gdb-7.6/gdb/testsuite/gdb.python/py-framefilter.exp
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ gdb-7.6/gdb/testsuite/gdb.python/py-framefilter.exp	2013-05-20 22:25:52.115165766 +0200
+@@ -0,0 +1,239 @@
++# Copyright (C) 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 <http://www.gnu.org/licenses/>.
++
++# This file is part of the GDB testsuite.  It tests Python-based
++# frame-filters.
++
++load_lib gdb-python.exp
++
++standard_testfile
++
++# We cannot use prepare_for_testing as we have to set the safe-patch
++# to check objfile and progspace printers.
++if {[build_executable $testfile.exp $testfile $srcfile debug] == -1} {
++    return -1
++}
++
++# Start with a fresh gdb.
++gdb_exit
++gdb_start
++
++# Skip all tests if Python scripting is not enabled.
++if { [skip_python_tests] } { continue }
++
++# Make the -gdb.py script available to gdb, it is automagically loaded by gdb.
++# Care is taken to put it in the same directory as the binary so that
++# gdb will find it.
++set remote_obj_python_file \
++    [remote_download \
++	 host ${srcdir}/${subdir}/${testfile}-gdb.py.in \
++	 ${subdir}/${testfile}-gdb.py]
++
++gdb_reinitialize_dir $srcdir/$subdir
++gdb_test_no_output "set auto-load safe-path ${remote_obj_python_file}" \
++    "set auto-load safe-path"
++gdb_load ${binfile}
++# Verify gdb loaded the script.
++gdb_test "info auto-load python-scripts" "Yes.*/${testfile}-gdb.py.*" \
++    "Test auto-load had loaded python scripts"
++
++if ![runto_main] then {
++    perror "couldn't run to breakpoint"
++    return
++}
++gdb_test_no_output "set python print-stack full" \
++    "Set python print-stack to full"
++
++# Load global frame-filters
++set remote_python_file [remote_download host ${srcdir}/${subdir}/${testfile}.py]
++gdb_test_no_output "python execfile ('${remote_python_file}')" \
++    "Load python file"
++
++gdb_breakpoint [gdb_get_line_number "Backtrace end breakpoint"]
++gdb_breakpoint [gdb_get_line_number "Inner test breakpoint"]
++gdb_continue_to_breakpoint "Inner test breakpoint"
++
++# Test multiple local blocks.
++gdb_test "bt full no-filters" \
++    ".*#0.*end_func.*h = 9.*f = 42.*g = 19.*bar = $hex \"Inside block x2\".*d = 15.*e = 14.*foo = $hex \"Inside block\".*str = $hex \"The End\".*st2 = $hex \"Is Near\".*b = 12.*c = 5.*" \
++    "bt full no-filters"
++gdb_test "bt full" \
++    ".*#0.*cnuf_dne.*h = 9.*f = 42.*g = 19.*bar = $hex \"Inside block x2\".*d = 15.*e = 14.*foo = $hex \"Inside block\".*str = $hex \"The End\".*st2 = $hex \"Is Near\".*b = 12.*c = 5.*" \
++    "bt full with filters"
++
++gdb_continue_to_breakpoint "Backtrace end breakpoint"
++
++# Test set/show
++gdb_test "info frame-filter" \
++    ".*900.*Yes.*Elider.*100.*Yes.*Reverse.*10.*.*No.*Object.*1.*" \
++    "info frame filter before setting priority"
++gdb_test "show frame-filter priority global Elider" \
++    "Priority of filter 'Elider' in list 'global' is: 900" \
++    "show frame-filter priority global Elider before setting"
++gdb_test_no_output  "set frame-filter priority global Elider 1000" \
++    "set frame-filter priotiy global Elider 1000"
++gdb_test "show frame-filter priority global Elider" \
++        "Priority of filter 'Elider' in list 'global' is: 1000" \
++        "show frame-filter priority global Elider after setting"
++gdb_test "info frame-filter" \
++    ".*1000.*Yes.*Elider.*100.*Yes.*Reverse.*10.*.*No.*Object.*1.*" \
++    "info frame filter after setting priority"
++
++# Test enable/disable
++gdb_test "info frame-filter" \
++    ".*1000.*Yes.*Elider.*100.*Yes.*Reverse.*10.*.*No.*Object.*1.*" \
++    "info frame filter before disable frame filter"
++gdb_test_no_output  "disable frame-filter global Elider" \
++    "disable frame-filter global Elider"
++gdb_test "info frame-filter" \
++    ".*1000.*No.*Elider.*100.*Yes.*Reverse.*10.*.*No.*Object.*1.*" \
++    "info frame filter after disable frame filter"
++gdb_test_no_output  "enable frame-filter global Elider" \
++    "enable frame-filter global Elider"
++gdb_test "info frame-filter" \
++    ".*1000.*Yes.*Elider.*100.*Yes.*Reverse.*10.*.*No.*Object.*1.*" \
++    "info frame filter after reenabling frame filter"
++
++# Test no-filters
++gdb_test "bt no-filters" \
++    ".*#0.*end_func.*#22.*in func1.*#27.*in main \\(\\).*" \
++    "bt no-filters"
++
++# Test reverse
++gdb_test "bt" \
++    ".*#0.*cnuf_dne.*#22.*in 1cnuf.*#27.*in niam \\(\\).*" \
++    "bt with frame filters"
++
++# Disable Reverse
++gdb_test_no_output "disable frame-filter global Reverse" \
++    "disable frame-filter global Reverse"
++gdb_test "bt" \
++    ".*#0.*end_func.*#22.*in func1.*#27.*in main \\(\\).*" \
++    "bt with frame-filter Reverse disabled"
++gdb_test "bt -2" \
++    ".*#26.*func5.*#27.*in main \\(\\).*" \
++    "bt -2 with frame-filter Reverse disabled"
++gdb_test "bt 3" \
++    ".*#0.*end_func.*#1.*in funca \\(\\).*#2.*in funcb \\(j=10\\).*" \
++    "bt 3 with frame-filter Reverse disabled"
++gdb_test "bt no-filter full" \
++    ".*#0.*end_func.*str = $hex \"The End\".*st2 = $hex \"Is Near\".*b = 12.*c = 5.*#1.*in funca \\(\\).*#2.*in funcb \\(j=10\\).*bar = \{a = 42, b = 84\}.*" \
++    "bt no-filters full with Reverse disabled"
++gdb_test "bt full" \
++    ".*#0.*end_func.*str = $hex \"The End\".*st2 = $hex \"Is Near\".*b = 12.*c = 5.*#1.*in funca \\(\\).*#2.*in funcb \\(j=10\\).*bar = \{a = 42, b = 84\}.*#22.*in func1 \\(\\).*#23.*in func2 \\(f=3\\).*elided = $hex \"Elided frame\".*fb = \{nothing = $hex \"Elided Foo Bar\", f = 84, s = 38\}.*bf = $hex.*" \
++    "bt full with Reverse disabled"
++
++# Test set print frame-arguments
++# none
++gdb_test_no_output "set print frame-arguments none" \
++    "turn off frame arguments"
++gdb_test "bt no-filter 1" \
++    "#0.*end_func \\(foo=\.\.\., bar=\.\.\., fb=\.\.\., bf=\.\.\.\\) at .*py-framefilter.c.*" \
++    "bt no-filter 1 no args"
++gdb_test "bt 1" \
++    "#0.*end_func \\(foo=\.\.\., bar=\.\.\., fb=\.\.\., bf=\.\.\.\\) at .*py-framefilter.c.*" \
++    "bt 1 no args"
++
++# scalars
++gdb_test_no_output "set print frame-arguments scalars" \
++    "turn frame arguments to scalars only"
++gdb_test "bt no-filter 1" \
++    "#0.*end_func \\(foo=21, bar=$hex \"Param\", fb=$hex, bf=\.\.\.\\) at .*py-framefilter.c.*" \
++    "bt no-filter 1 scalars"
++gdb_test "bt 1" \
++    "#0.*end_func \\(foo=21, bar=$hex \"Param\", fb=$hex, bf=\.\.\.\\) at .*py-framefilter.c.*" \
++    "bt 1 scalars"
++
++# all
++gdb_test_no_output "set print frame-arguments all" \
++    "turn on frame arguments"
++gdb_test "bt no-filter 1" \
++    "#0.*end_func \\(foo=21, bar=$hex \"Param\", fb=$hex, bf=\{nothing = $hex \"Foo Bar\", f = 42, s = 19\}\\) at .*py-framefilter.c.*" \
++    "bt no-filter 1 all args"
++gdb_test "bt 1" \
++    "#0.*end_func \\(foo=21, bar=$hex \"Param\", fb=$hex, bf=\{nothing = $hex \"Foo Bar\", f = 42, s = 19\}\\) at .*py-framefilter.c.*" \
++    "bt 1 all args"
++
++# set print address off
++gdb_test_no_output "set print address off" \
++    "Turn off address printing"
++gdb_test "bt no-filter 1" \
++    "#0  end_func \\(foo=21, bar=\"Param\", fb=, bf=\{nothing = \"Foo Bar\", f = 42, s = 19\}\\) at .*py-framefilter.c.*" \
++    "bt no-filter 1 no address"
++gdb_test "bt 1" \
++    "#0  end_func \\(foo=21, bar=\"Param\", fb=, bf=\{nothing = \"Foo Bar\", f = 42, s = 19\}\\) at .*py-framefilter.c.*" \
++    "bt 1 no addresss"
++
++remote_file host delete ${remote_python_file}
++
++# Test with no debuginfo
++
++# We cannot use prepare_for_testing as we have to set the safe-patch
++# to check objfile and progspace printers.
++if {[build_executable $testfile.exp $testfile $srcfile {nodebug}] == -1} {
++    return -1
++}
++
++# Start with a fresh gdb.
++gdb_exit
++gdb_start
++
++# Skip all tests if Python scripting is not enabled.
++if { [skip_python_tests] } { continue }
++
++# Make the -gdb.py script available to gdb, it is automagically loaded by gdb.
++# Care is taken to put it in the same directory as the binary so that
++# gdb will find it.
++set remote_obj_python_file \
++    [remote_download \
++	 host ${srcdir}/${subdir}/${testfile}-gdb.py.in \
++	 ${subdir}/${testfile}-gdb.py]
++
++gdb_reinitialize_dir $srcdir/$subdir
++gdb_test_no_output "set auto-load safe-path ${remote_obj_python_file}" \
++    "set auto-load safe-path for no debug info"
++gdb_load ${binfile}
++
++# Verify gdb loaded the script.
++gdb_test "info auto-load python-scripts" "Yes.*/${testfile}-gdb.py.*" \
++    "Set autoload path for no debug info tests"
++if ![runto_main] then {
++    perror "couldn't run to breakpoint"
++    return
++}
++
++gdb_test_no_output "set python print-stack full" \
++    "set python print-stack full for no debuginfo tests"
++
++# Load global frame-filters
++set remote_python_file [remote_download host ${srcdir}/${subdir}/${testfile}.py]
++gdb_test_no_output "python execfile ('${remote_python_file}')" \
++    "Load python file for no debuginfo tests"
++
++# Disable Reverse
++gdb_test_no_output "disable frame-filter global Reverse" \
++    "disable frame-filter gloval Reverse for no debuginfo"
++gdb_test "bt" \
++    ".*#0..*in main \\(\\).*" \
++    "bt for no debuginfo"
++gdb_test "bt full" \
++    ".*#0..*in main \\(\\).*" \
++    "bt full for no debuginfo"
++gdb_test "bt no-filters" \
++    ".*#0..*in main \\(\\).*" \
++    "bt no filters for no debuginfo"
++gdb_test "bt no-filters full" \
++    ".*#0..*in main \\(\\).*" \
++    "bt no-filters full no debuginfo"
+Index: gdb-7.6/gdb/testsuite/gdb.python/py-framefilter.py
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ gdb-7.6/gdb/testsuite/gdb.python/py-framefilter.py	2013-05-20 22:25:52.115165766 +0200
+@@ -0,0 +1,117 @@
++# Copyright (C) 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 <http://www.gnu.org/licenses/>.
++
++# This file is part of the GDB testsuite.  It tests Python-based
++# frame-filters.
++import gdb
++import itertools
++from gdb.FrameDecorator import FrameDecorator
++import copy
++
++class Reverse_Function (FrameDecorator):
++
++    def __init__(self, fobj):
++        super(Reverse_Function, self).__init__(fobj)
++        self.fobj = fobj
++
++    def function (self):
++        fname = str (self.fobj.function())
++        if (fname == None or fname == ""):
++            return None
++        else:
++            fname = fname[::-1]
++        return fname
++
++class Dummy (FrameDecorator):
++
++    def __init__(self, fobj):
++        super(Dummy, self).__init__(fobj)
++        self.fobj = fobj
++
++    def function (self):
++        return "Dummy function"
++
++    def address (self):
++        return 0x123
++
++    def filename (self):
++        return "Dummy filename"
++
++    def frame_args (self):
++        return [("Foo",gdb.Value(12)),("Bar","Stuff"), ("FooBar",42)]
++
++    def frame_locals (self):
++        return []
++
++    def line (self):
++        return 0
++
++    def elided (self):
++        return None
++
++class FrameFilter ():
++
++    def __init__ (self):
++        self.name = "Reverse"
++        self.priority = 100
++        self.enabled = True
++        gdb.frame_filters [self.name] = self
++
++    def filter (self, frame_iter):
++        frame_iter = itertools.imap (Reverse_Function,
++                                     frame_iter)
++        return frame_iter
++
++class ElidingFrameDecorator(FrameDecorator):
++
++    def __init__(self, frame, elided_frames):
++        super(ElidingFrameDecorator, self).__init__(frame)
++        self.elided_frames = elided_frames
++
++    def elided(self):
++        return iter(self.elided_frames)
++
++class ElidingIterator:
++    def __init__(self, ii):
++        self.input_iterator = ii
++
++    def __iter__(self):
++        return self
++
++    def next(self):
++        frame = next(self.input_iterator)
++        if str(frame.function()) != 'func1':
++            return frame
++
++        # Suppose we want to return the 'func1' frame but elide the
++        # next frame.  E.g., if call in our interpreter language takes
++        # two C frames to implement, and the first one we see is the
++        # "sentinel".
++        elided = next(self.input_iterator)
++        return ElidingFrameDecorator(frame, [elided])
++
++class FrameElider ():
++
++    def __init__ (self):
++        self.name = "Elider"
++        self.priority = 900
++        self.enabled = True
++        gdb.frame_filters [self.name] = self
++
++    def filter (self, frame_iter):
++        return ElidingIterator (frame_iter)
++
++FrameFilter()
++FrameElider()

diff --git a/gdb-upstream-framefilters-2of2.patch b/gdb-upstream-framefilters-2of2.patch
new file mode 100644
index 0000000..0446ef6
--- /dev/null
+++ b/gdb-upstream-framefilters-2of2.patch
@@ -0,0 +1,175 @@
+http://sourceware.org/ml/gdb-cvs/2013-05/msg00141.html
+
+### src/gdb/ChangeLog	2013/05/17 06:58:33	1.15565
+### src/gdb/ChangeLog	2013/05/17 08:34:18	1.15566
+## -1,3 +1,18 @@
++2013-05-17  Phil Muldoon  <pmuldoon@redhat.com>
++
++	* frame.c (frame_stash): Convert to htab.
++	(frame_addr_hash): New function.
++	(frame_addr_hash_eq): New function.
++	(frame_stash_create): Convert function to create
++	a hash table.
++	(frame_stash_add): Convert function to add an entry to a hash
++	table.
++	(frame_stash_find): Convert function to search the hash table.
++	(frame_stash_invalidate): Convert function to empty the hash
++	table.
++	(get_frame_id): Only add to stash if a frame_id is created.
++	(_initialize_frame): Call frame_stash_create.
++
+ 2013-05-16  Yue Lu  <hacklu.newborn@gmail.com>  (tiny change)
+ 
+ 	* configure.ac: Ensure MIG is available when building for GNU Hurd
+--- src/gdb/frame.c	2013/04/10 15:11:11	1.317
++++ src/gdb/frame.c	2013/05/17 08:34:18	1.318
+@@ -43,6 +43,7 @@
+ #include "block.h"
+ #include "inline-frame.h"
+ #include "tracepoint.h"
++#include "hashtab.h"
+ 
+ static struct frame_info *get_prev_frame_1 (struct frame_info *this_frame);
+ static struct frame_info *get_prev_frame_raw (struct frame_info *this_frame);
+@@ -128,38 +129,107 @@
+   enum unwind_stop_reason stop_reason;
+ };
+ 
+-/* A frame stash used to speed up frame lookups.  */
++/* A frame stash used to speed up frame lookups.  Create a hash table
++   to stash frames previously accessed from the frame cache for
++   quicker subsequent retrieval.  The hash table is emptied whenever
++   the frame cache is invalidated.  */
++
++static htab_t frame_stash;
++
++/* Internal function to calculate a hash from the frame_id addresses,
++   using as many valid addresses as possible.  Frames below level 0
++   are not stored in the hash table.  */
++
++static hashval_t
++frame_addr_hash (const void *ap)
++{
++  const struct frame_info *frame = ap;
++  const struct frame_id f_id = frame->this_id.value;
++  hashval_t hash = 0;
++
++  gdb_assert (f_id.stack_addr_p || f_id.code_addr_p
++	      || f_id.special_addr_p);
++
++  if (f_id.stack_addr_p)
++    hash = iterative_hash (&f_id.stack_addr,
++			   sizeof (f_id.stack_addr), hash);
++  if (f_id.code_addr_p)
++    hash = iterative_hash (&f_id.code_addr,
++			   sizeof (f_id.code_addr), hash);
++  if (f_id.special_addr_p)
++    hash = iterative_hash (&f_id.special_addr,
++			   sizeof (f_id.special_addr), hash);
+ 
+-/* We currently only stash one frame at a time, as this seems to be
+-   sufficient for now.  */
+-static struct frame_info *frame_stash = NULL;
++  return hash;
++}
++
++/* Internal equality function for the hash table.  This function
++   defers equality operations to frame_id_eq.  */
++
++static int
++frame_addr_hash_eq (const void *a, const void *b)
++{
++  const struct frame_info *f_entry = a;
++  const struct frame_info *f_element = b;
+ 
+-/* Add the following FRAME to the frame stash.  */
++  return frame_id_eq (f_entry->this_id.value,
++		      f_element->this_id.value);
++}
++
++/* Internal function to create the frame_stash hash table.  100 seems
++   to be a good compromise to start the hash table at.  */
++
++static void
++frame_stash_create (void)
++{
++  frame_stash = htab_create (100,
++			     frame_addr_hash,
++			     frame_addr_hash_eq,
++			     NULL);
++}
++
++/* Internal function to add a frame to the frame_stash hash table.  Do
++   not store frames below 0 as they may not have any addresses to
++   calculate a hash.  */
+ 
+ static void
+ frame_stash_add (struct frame_info *frame)
+ {
+-  frame_stash = frame;
++  /* Do not stash frames below level 0.  */
++  if (frame->level >= 0)
++    {
++      struct frame_info **slot;
++
++      slot = (struct frame_info **) htab_find_slot (frame_stash,
++						    frame,
++						    INSERT);
++      *slot = frame;
++    }
+ }
+ 
+-/* Search the frame stash for an entry with the given frame ID.
+-   If found, return that frame.  Otherwise return NULL.  */
++/* Internal function to search the frame stash for an entry with the
++   given frame ID.  If found, return that frame.  Otherwise return
++   NULL.  */
+ 
+ static struct frame_info *
+ frame_stash_find (struct frame_id id)
+ {
+-  if (frame_stash && frame_id_eq (frame_stash->this_id.value, id))
+-    return frame_stash;
++  struct frame_info dummy;
++  struct frame_info *frame;
+ 
+-  return NULL;
++  dummy.this_id.value = id;
++  frame = htab_find (frame_stash, &dummy);
++  return frame;
+ }
+ 
+-/* Invalidate the frame stash by removing all entries in it.  */
++/* Internal function to invalidate the frame stash by removing all
++   entries in it.  This only occurs when the frame cache is
++   invalidated.  */
+ 
+ static void
+ frame_stash_invalidate (void)
+ {
+-  frame_stash = NULL;
++  htab_empty (frame_stash);
+ }
+ 
+ /* Flag to control debugging.  */
+@@ -345,10 +415,9 @@
+ 	  fprint_frame_id (gdb_stdlog, fi->this_id.value);
+ 	  fprintf_unfiltered (gdb_stdlog, " }\n");
+ 	}
++      frame_stash_add (fi);
+     }
+ 
+-  frame_stash_add (fi);
+-
+   return fi->this_id.value;
+ }
+ 
+@@ -2451,6 +2520,8 @@
+ {
+   obstack_init (&frame_cache_obstack);
+ 
++  frame_stash_create ();
++
+   observer_attach_target_changed (frame_observer_target_changed);
+ 
+   add_prefix_cmd ("backtrace", class_maintenance, set_backtrace_cmd, _("\

diff --git a/gdb-upstream.patch b/gdb-upstream.patch
index bcc5667..3240ab2 100644
--- a/gdb-upstream.patch
+++ b/gdb-upstream.patch
@@ -1199,3 +1199,97 @@ http://sourceware.org/ml/gdb-cvs/2013-04/msg00070.html
  	-($(POD2MAN5) gdbinit.pod | sed -e '/^.if n .na/d' > $@.T$$$$ && \
  		mv -f $@.T$$$$ $@) || (rm -f $@.T$$$$ && exit 1)
  	rm -f gdbinit.pod
+
+
+
+http://sourceware.org/bugzilla/show_bug.cgi?id=15413
+http://sourceware.org/ml/gdb-cvs/2013-05/msg00063.html
+
+### src/gdb/ChangeLog	2013/04/26 14:13:13	1.15260.2.50
+### src/gdb/ChangeLog	2013/05/07 17:04:56	1.15260.2.51
+## -1,3 +1,10 @@
++2013-05-07  Sergio Durigan Junior  <sergiodj@redhat.com>
++
++	PR breakpoints/15413:
++	* breakpoint.c (condition_completer): Simplify the code to
++	disconsider multiple locations of breakpoints when completing the
++	"condition" command.
++
+ 2013-04-26  Joel Brobecker  <brobecker@adacore.com>
+ 
+ 	* version.in: Set version to 7.6.0.20130426-cvs.
+--- src/gdb/breakpoint.c	2013/04/25 08:15:34	1.745.2.5
++++ src/gdb/breakpoint.c	2013/05/07 17:04:57	1.745.2.6
+@@ -1015,27 +1015,14 @@
+       len = strlen (text);
+ 
+       ALL_BREAKPOINTS (b)
+-      {
+-	int single = b->loc->next == NULL;
+-	struct bp_location *loc;
+-	int count = 1;
+-
+-	for (loc = b->loc; loc; loc = loc->next)
+-	  {
+-	    char location[50];
+-
+-	    if (single)
+-	      xsnprintf (location, sizeof (location), "%d", b->number);
+-	    else
+-	      xsnprintf (location, sizeof (location),  "%d.%d", b->number,
+-			 count);
++	{
++	  char number[50];
+ 
+-	    if (strncmp (location, text, len) == 0)
+-	      VEC_safe_push (char_ptr, result, xstrdup (location));
++	  xsnprintf (number, sizeof (number), "%d", b->number);
+ 
+-	    ++count;
+-	  }
+-      }
++	  if (strncmp (number, text, len) == 0)
++	    VEC_safe_push (char_ptr, result, xstrdup (number));
++	}
+ 
+       return result;
+     }
+### src/gdb/testsuite/ChangeLog	2013/05/03 16:26:32	1.3580.2.20
+### src/gdb/testsuite/ChangeLog	2013/05/07 17:04:57	1.3580.2.21
+## -1,3 +1,11 @@
++2013-05-07  Sergio Durigan Junior  <sergiodj@redhat.com>
++
++	PR breakpoints/15413:
++	* gdb.base/pending.exp: Add test for completion of the "condition"
++	command for pending breakpoints.
++	* gdb.linespec/linespec.ex: Add test for completion of the
++	"condition" command when dealing with multiple locations.
++
+ 2013-05-03  Hafiz Abid Qadeer  <abidh@codesourcery.com>
+ 
+ 	* status-stop.exp (test_tstart_tstart): Check for error
+--- src/gdb/testsuite/gdb.base/pending.exp	2013/01/01 06:33:26	1.27
++++ src/gdb/testsuite/gdb.base/pending.exp	2013/05/07 17:04:57	1.27.2.1
+@@ -55,6 +55,9 @@
+      }
+ }
+ 
++# Complete the condition (PR 15413).
++gdb_test "complete condition " "condition 1"
++
+ gdb_test "info break" \
+     "Num     Type\[ \]+Disp Enb Address\[ \]+What.*
+ \[0-9\]+\[\t \]+breakpoint     keep y.*PENDING.*pendfunc1.*" \
+--- src/gdb/testsuite/gdb.linespec/linespec.exp	2013/01/01 06:41:24	1.6
++++ src/gdb/testsuite/gdb.linespec/linespec.exp	2013/05/07 17:04:57	1.6.2.1
+@@ -63,6 +63,10 @@
+     "Breakpoint $decimal at $hex: dupname:label. \[(\]2 locations\[)\]" \
+     "multi-location break using duplicate function name and label"
+ 
++# Testing if the "condition" command completes only the breakpoints,
++# not the locations.
++gdb_test "complete condition " "condition $decimal\r\ncondition $decimal\r\ncondition $decimal"
++
+ gdb_test_no_output "set breakpoint pending off" \
+     "disable pending breakpoints for linespec tests"
+ 

diff --git a/gdb.spec b/gdb.spec
index 16bc3f0..8aada04 100644
--- a/gdb.spec
+++ b/gdb.spec
@@ -36,7 +36,7 @@ Version: 7.6
 
 # The release always contains a leading reserved number, start it at 1.
 # `upstream' is not a part of `name' to stay fully rpm dependencies compatible for the testing.
-Release: 29%{?dist}
+Release: 30%{?dist}
 
 License: GPLv3+ and GPLv3+ with exceptions and GPLv2+ and GPLv2+ with exceptions and GPL+ and LGPLv2+ and BSD and Public Domain
 Group: Development/Debuggers
@@ -266,6 +266,9 @@ Patch231: gdb-6.3-bz202689-exec-from-pthread-test.patch
 Patch232: gdb-upstream.patch
 Patch828: gdb-upstream-man-gcore-1of2.patch
 Patch829: gdb-upstream-man-gcore-2of2.patch
+# Backported Python frame filters (Phil Muldoon).
+Patch836: gdb-upstream-framefilters-1of2.patch
+Patch837: gdb-upstream-framefilters-2of2.patch
 
 # Testcase for PPC Power6/DFP instructions disassembly (BZ 230000).
 #=fedoratest+ppc
@@ -780,6 +783,8 @@ find -name "*.info*"|xargs rm -f
 %patch232 -p1
 %patch828 -p1
 %patch829 -p1
+%patch836 -p1
+%patch837 -p1
 %patch1 -p1
 %patch3 -p1
 
@@ -1397,8 +1402,12 @@ fi
 %endif # 0%{!?el5:1} || "%{_target_cpu}" == "noarch"
 
 %changelog
+* Tue May 21 2013 Jan Kratochvil <jan.kratochvil@redhat.com> - 7.6-30.fc19
+- Backported Python frame filters (Phil Muldoon).
+- Backported breakpoint conditions crash fix (Sergio Durigan Junior).
+
 * Sun May 19 2013 Jan Kratochvil <jan.kratochvil@redhat.com> - 7.6-29.fc19
-- Fix performance regression when inferior opens many libraries (Gary Benson).
+- Fix performance regression opening many libraries (Gary Benson, BZ 965106).
 
 * Thu May  9 2013 Jan Kratochvil <jan.kratochvil@redhat.com> - 7.6-28.fc19
 - Fix needless expansion of non-gdbindex symtabs (Doug Evans).

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

only message in thread, other threads:[~2026-06-27 23:56 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-06-27 23:56 [rpms/gdb] gdb-17.2-rebase-f44: Backported Python frame filters (Phil Muldoon) Jan Kratochvil

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox