[patch][python] 5 of 5 - Frame filter documentation changes

Phil Muldoon pmuldoon@redhat.com
Fri Nov 30 14:32:00 GMT 2012


This patch/email address documentation changes for Python Frame
Filters.

2012-11-30  Phil Muldoon  <pmuldoon@redhat.com>

	* gdb.texinfo (Backtrace): Add "raw" argument.
	(Python API): Add Frame	Filters API, Frame Wrapper API,
	Writing a Frame Filter/Wrapper,	Managing Management of Frame
	Filters chapter entries.
	(Frame Filters API): New Node.
	(Frame Wrapper API): New Node.
	(Writing a Frame Filter/Wrapper): New Node.
	(Managing Frame Filters): New Node.
	(Progspaces In Python): Add note about frame_filters attribute.
	(Objfiles in Python): Ditto.
	(GDB/MI Stack Manipulation): Add -enable-frame-filters command,
	@anchors and --no-frame-filters option to -stack-list-variables,
	-stack-list-frames, -stack-list-locals and -stack-list-arguments
	commands.


--

diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index afe3845..5a0215d 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -6360,6 +6360,7 @@ line per frame, for many frames, starting with the currently executing
 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})}
@@ -6385,6 +6386,17 @@ Similar, but print only the outermost @var{n} frames.
 @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 raw
+@itemx bt raw
+@itemx bt raw @var{n}
+@itemx bt raw -@var{n}
+@itemx bt raw full
+@itemx bt raw full @var{n}
+@itemx bt raw full -@var{n}
+Do not run Python frame filters on this backtrace.  @xref{Frame
+Filters API}, for more information.  This is only relevant when
+@value{GDBN} has been configured with @code{Python} support.
 @end table
 
 @kindex where
@@ -22738,6 +22750,10 @@ situation, a Python @code{KeyboardInterrupt} exception is thrown.
 * Selecting Pretty-Printers::   How GDB chooses a pretty-printer.
 * Writing a Pretty-Printer::    Writing a Pretty-Printer.
 * Type Printing API::		Pretty-printing types.
+* Frame Filters API::           Filtering and Wrapping Frames.
+* Frame Wrapper API::           Wrapping and Decorating Frames.
+* Writing a Frame Filter/Wrapper::  Writing a Frame Filter and Wrapper.
+* Managing Frame Filters::      Management of Frame Filters.
 * 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.
@@ -24095,6 +24111,759 @@ done then type printers would have to make use of the event system in
 order to avoid holding information that could become stale as the
 inferior changed.
 
+@node Frame Filters API
+@subsubsection Filtering and Wrapping Frames.
+@cindex Frame Filter/Wrappers 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 applying actions to an iterator that is passed
+to that frame filter as a parameter.  Typically, frame filters utilize
+tools such as the Python's @code{itertools} module to modify the
+iterator.  If the frame filter modifies the iterator, it returns that
+modified iterator, otherwise it returns the original iterator
+unmodified.  A frame filter must not alter the underlying @value{GDBN}
+frame or frames, or attempt to alter the call-stack within
+@value{GDBN}.  Frame filters may only work on the wrapping iterator.
+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.  Each frame filter object
+takes a Python iterator, and returns a Python iterator.  For further
+information on frame filters see, @ref{Writing a Frame
+Filter/Wrapper}.
+
+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 (a Python iterator) 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 wrappers that wrap each @code{gdb.Frame},
+or another frame wrapper that wraps a frame wrapper.  The first filter
+that is executed in the sequence of frame filters will receive an
+iterator entirely comprised of @code{BaseFrameWrapper} objects.
+However, after each frame filter is executed, the previous frame
+filter may have wrapped some or all of the frame wrappers with their
+own frame wrapper.  As Frame Wrappers must also conform to a mandatory
+interface, these wrappers can be assumed to act in a uniform manner
+(@pxref{Frame Wrapper 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 wrapper 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{Managing Frame
+Filters}).  This attribute may contain any combination of letters,
+numbers and spaces.  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 is 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 Wrapper API
+@subsubsection Wrapping and Decorating Frames.
+@cindex Frame Wrapper API
+
+Frame wrappers are sister objects to frame filters (@pxref{Frame
+Filters API}).  Frame wrappers are applied by a frame filter and can
+only be used in conjunction with frame filters.
+
+The purpose of a frame wrapper is to customize the printed content of
+each frame.  Frame wrappers have a mandatory interface, defined below.
+A frame wrapper object works on a single frame, but a frame wrapper
+object can be applied to multiple frames.
+
+@value{GDBN} already contains a frame wrapper called
+@code{BaseFrameWrapper}.  This contains substantial amounts of
+boilerplate code to print the content of frames.  It is recommended
+that other frame wrappers inherit and extend this object, and only to
+override the methods needed.  The Python code for
+@code{BaseFrameWrapper} can be found in
+@file{@var{data-directory}/python/gdb}
+
+@defun FrameWrapper.elided ()
+
+The @code{elided} method groups frames together in a hierarchical
+system.  An example would be an interpreter call that occurs over many
+frames but might be better represented as a group of frames distinct
+from the other frames.
+
+The @code{elide} function must return an iterator that conforms to the
+Python iterator protocol.  This iterator must contains the frames that
+are being elided wrapped in a suitable frame wrapper.  If there are no
+frames being elided in this frame wrapper, this method must return a
+Python @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 task to also filter out the elided frames from
+the source iterator.  This will avoid the frame being printed twice.
+@end defun
+
+@defun FrameWrapper.function ()
+
+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 a
+Python @code{None}.
+
+If this function returns a Python @code{None}, @value{GDBN} will not
+print any data for this field.
+@end defun
+
+@defun FrameWrapper.address ()
+
+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 a Python @code{None}.
+
+If this function returns a Python @code{None}, @value{GDBN} will not
+print any data for this field.
+@end defun
+
+@defun FrameWrapper.filename ()
+
+This method returns the filename associated with this frame.
+
+This method must return a Python string containing the filename, and
+optionally, the path to the filename of the frame, or a Python
+@code{None}.
+
+If this function returns a Python @code{None}, @value{GDBN} will not
+print any data for this field.
+@end defun
+
+
+@defun FrameWrapper.line ():
+
+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 a Python
+@code{None}.
+
+If this function returns a Python @code{None}, @value{GDBN} will not
+print any data for this field.
+@end defun
+
+@defun FrameWrapper.frame_args ()
+
+This method must return an  iterator that conforms to the Python
+iterator protocol, or a Python @code{None}.  This iterator must
+contain objects that implement two methods, described here.
+
+The object must implement an @code{argument} method which takes no
+parameters and must return a @code{gdb.Symbol} or a Python string.  It
+must also implement a @code{value} method which takes no parameters
+and which must return a @code{gdb.Value}, a Python value, or
+@code{None}.  If the @code{value} method returns a Python @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 SomeFrameWrapper ()
+...
+...
+    def frame_args (self):
+        fvars = []
+        fvars.append (SymValueWrapper (``foo'', 42))
+
+        return iter (fvars)
+@end smallexample
+
+Even if the @code{frame_args} method returns only a single object, it
+must be wrapped in an iterator.
+
+If this function returns a Python @code{None}, @value{GDBN} will not
+print arguments for this frame.
+@end defun
+
+@defun FrameWrapper.frame_locals ()
+
+This method must return an iterator that conforms to the Python
+iterator protocol, or a Python @code{None}.  This iterator must
+contain objects that implement two methods, described here.
+
+The object must implement an @code{argument} method which takes no
+parameters and must return a @code{gdb.Symbol} or a Python string.  It
+must also implement a @code{value} method which takes no parameters
+and which must return a @code{gdb.Value}, a Python value, or
+@code{None}.  If the @code{value} method returns a Python @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 SomeFrameWrapper ()
+...
+...
+    def frame_locals (self):
+        fvars = []
+        fvars.append (SymValueWrapper (``foo'', 42))
+
+        return iter (fvars)
+@end smallexample
+
+Even if the @code{frame_locals} method returns only a single object, it
+must be wrapped in an iterator.
+
+If this function returns a Python @code{None}, @value{GDBN} will not
+print locals for this frame.
+@end defun
+
+@defun FrameWrapper.frame ():
+
+This method must return the underlying @code{gdb.Frame} that this
+frame wrapper is wrapping.  @value{GDBN} requires the underlying frame
+for internal frame information to determine how to print certain
+values in frame printing
+@end defun
+
+@node Writing a Frame Filter/Wrapper
+@subsubsection Writing a Frame Filter and Wrapper
+@cindex Writing a Frame Filter/Wrapper
+
+The Python dictionary @code{gdb.frame_filters} contains key/object
+pairings that compromise a frame filter.  These frame filters must
+register with the dictionary directly.  Frame filters in this
+dictionary are called @code{global} frame filters, and they are
+available when debugging all inferiors.  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 contain a @code{frame_filters} dictionary attribute.
+
+Each frame filter object in these dictionaries is passed a single
+Python iterator argument and should return a Python iterator.  Each
+frame filter object must conform to the frame filter interface
+definition (@pxref{Frame Filters API}).  The iterator returned by the
+frame filter must contain only a collection of frame wrappers
+(@pxref{Frame Wrapper API}), conforming to the frame wrapper interface
+definition.
+
+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 object files might be in use.
+@value{GDBN} then prunes any frame filter where the @code{enabled}
+attribute is set to @code{False}.  This pruned list is then sorted
+according to the @code{priority} attribute in each filter.  Once the
+dictionaries are combined, sorted and pruned, @value{GDBN} then wraps
+all frames in the call-stack with a @code{BaseFrameWrapper} object,
+and calls each filter in priority order.  The input to the first frame
+filter will be an initial iterator wrapping a collection of
+@code{BaseFrameWrapper} objects.  The output from the previous filter
+will always be the input to the next filter, and so on.
+
+@subsubheading Implementing a frame filter
+
+There are three basic elements that a frame filter must implement: it
+must correctly implement the documented interface (@pxref{Frame
+Filters 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):
+        self.name = "Foo"
+        self.priority = 100
+        self.enabled = True
+        gdb.frame_filters [self.name] = self
+
+    def filter (self, frame_iter):
+        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:
+
+@smallexample
+        self.name = "Foo"
+        self.priority = 100
+        self.enabled = True
+@end smallexample
+
+The second step is registering the frame filter with the dictionary or
+dictionaries that the frame filter has interest in:
+
+@smallexample
+        gdb.frame_filters [self.name] = self
+@end smallexample
+
+As noted earlier, @code{gdb.frame_filters} is a dictionary that is
+initialized in the @code{gdb} module when @value{GDBN} starts.  In
+this example, the frame filter only wishes to register with the
+@code{global} dictionary.
+
+@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{Managing Frame
+Filters}), 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:
+
+@smallexample
+    def filter (self, frame_iter):
+        return frame_iter
+@end smallexample
+
+Note that the @code{filter} 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 wrapper to perform some work on the frames.
+@xref{Frame Wrapper API}, for further information on the frame wrapper
+interface.
+
+This example works on inlined frames.  It highlights frames which are
+inlined by adding the function in which they are inlined into.  By
+applying a frame wrapper to all frames with the Python @code{itertools
+imap} method, the example defers actions to the frame wrapper.  Frame
+wrappers 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 wrapper 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.  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 wrapper can examine each frame in
+turn when @value{GDBN} iterates.  From a performance viewpoint, this
+is the most appropriate decision to make.  A backtrace from large or
+complex programs can constitute many thousands of frames.  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 = "Inlined Frame Class"
+        self.priority = 100
+        self.enabled = True
+        gdb.frame_filters [self.name] = self
+
+    def filter (self, frame_iter):
+        frame_iter = itertools.imap (InlinedFrameWrapper,
+                                     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 wrapper object called
+@code{InlinedFrameWrapper} 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 wrapper for this example.
+
+@smallexample
+class InlinedFrameWrapper (BaseFrameWrapper):
+
+    def __init__(self, fobj):
+        super(InlinedFrameWrapper, self).__init__(fobj)
+        self.fobj = fobj
+
+    def function (self):
+        frame = self.inferior_frame()
+        name = str(frame.name())
+        function = str(frame.function())
+
+        if frame.type() == gdb.INLINE_FRAME:
+            name = name + " [inlined from "+ function +"]"
+
+        return name
+@end smallexample
+
+This frame wrapper only defines and overrides the @code{function}
+method.  It lets the supplied @code{BaseFrameWrapper}, 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 from main] (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 wrapper 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 wrapper 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
+wrapper 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 = "Inlined Frame Class"
+        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
+
+        eliding_frame = next(self.input_iterator)
+        return ElidingFrameWrapper(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 wrapper, @code{frame}, is wrapping
+an inlined frame.  If it is not, it returns the existing frame wrapper
+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 wrapper, @code{ElidingFrameWrapper}, which contains both the
+elided frame, and the eliding frame.
+
+@smallexample
+class ElidingInlineWrapper(BaseFrameWrapper):
+
+    def __init__(self, frame, elided_frames):
+        super(ElidingInlineWrapper, self).__init__(frame)
+        self.frame = frame
+        self.elided_frames = elided_frames
+
+    def elided(self):
+        return iter(self.elided_frames)
+@end smallexample
+
+This frame wrapper overrides one function and returns the inlined
+frame in the @code{elided} method.  As before it lets
+@code{BaseFrameWrapper} 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 Managing Frame Filters
+@subsubsection Management of Frame Filters.
+@cindex Managing Frame Filters
+
+There are several commands available within @value{GDBN} to manage
+frame filters, 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
+@item disable frame-filter @var{filter-dictionary} @var{filter-name}
+Disable a frame filter in the dictionary matching
+@var{filter-dictionary} and @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{filter-name} is the name of the frame filter.  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} and @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{filter-name} is the name of the frame filter.
+
+Example:
+
+@smallexample
+(gdb) info frame-filter
+
+global frame-filters:
+  Priority  Enabled  Name
+  ========  =======  ====
+  1000      No       Capital Primary Function Filter
+  100       Yes      Reverse
+progspace /build/test frame-filters:
+  Priority  Enabled  Name
+  ========  =======  ====
+  100       Yes      Progspace Filter 1
+objfile /build/test frame-filters:
+  Priority  Enabled  Name
+  ========  =======  ====
+  999       Yes      Build Test Program Filter
+
+(gdb) disable frame-filter ``/build/test'' ``Build Test Program Filter''
+(gdb) info frame-filter
+
+global frame-filters:
+  Priority  Enabled  Name
+  ========  =======  ====
+  1000      No       Capital Primary Function Filter
+  100       Yes      Reverse
+progspace /build/test frame-filters:
+  Priority  Enabled  Name
+  ========  =======  ====
+  100       Yes      Progspace Filter 1
+objfile /build/test frame-filters:
+  Priority  Enabled  Name
+  ========  =======  ====
+  999       No       Build Test Program Filter
+
+(gdb) enable frame-filter global ``Capital Primary Function Filter''
+(gdb) info frame-filter
+
+global frame-filters:
+  Priority  Enabled  Name
+  ========  =======  ====
+  1000      Yes      Capital Primary Function Filter
+  100       Yes      Reverse
+progspace /build/test frame-filters:
+  Priority  Enabled  Name
+  ========  =======  ====
+  100       Yes      Progspace Filter 1
+objfile /build/test frame-filters:
+  Priority  Enabled  Name
+  ========  =======  ====
+  999       No       Build Test Program Filter
+
+@end smallexample
+
+@kindex set python frame-filter priority
+@item set python 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 python frame-filter priority
+@item show python 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      No       Capital Primary Function Filter
+  100       Yes      Reverse
+progspace /build/test frame-filters:
+  Priority  Enabled  Name
+  ========  =======  ====
+  100       Yes      Progspace Filter 1
+objfile /build/test frame-filters:
+  Priority  Enabled  Name
+  ========  =======  ====
+  999       Yes      Build Test Program Filter
+
+(gdb) set python  frame-filter priority global ``Reverse'' 50
+(gdb) info frame-filter
+
+global frame-filters:
+  Priority  Enabled  Name
+  ========  =======  ====
+  1000      No       Capital Primary Function Filter
+  50       Yes      Reverse
+progspace /build/test frame-filters:
+  Priority  Enabled  Name
+  ========  =======  ====
+  100       Yes      Progspace Filter 1
+objfile /build/test frame-filters:
+  Priority  Enabled  Name
+  ========  =======  ====
+  999       No       Build Test Program Filter
+@end smallexample
+@end table
+
 @node Inferiors In Python
 @subsubsection Inferiors In Python
 @cindex inferiors in Python
@@ -24944,6 +25713,11 @@ The @code{type_printers} attribute is a list of type printer objects.
 @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 Filters API}, for more information.
+@end defvar
+
 @node Objfiles In Python
 @subsubsection Objfiles In Python
 
@@ -24994,6 +25768,11 @@ The @code{type_printers} attribute is a list of type printer objects.
 @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 Filters API}, for more information.
+@end defvar
+
 A @code{gdb.Objfile} object has the following methods:
 
 @defun Objfile.is_valid ()
@@ -25975,7 +26754,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
@@ -29659,6 +30438,25 @@ 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).
+
+This feature is currently (as of @value{GDBN} 7.6) experimental, and
+may work differently in future versions of @value{GDBN}.
 
 @subheading The @code{-stack-info-frame} Command
 @findex -stack-info-frame
@@ -29726,13 +30524,14 @@ For a stack with frame levels 0 through 11:
 (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
 
@@ -29749,7 +30548,9 @@ If @var{print-values} is 0 or @code{--no-values}, print only the names of
 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.
@@ -29820,13 +30621,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
@@ -29856,7 +30658,9 @@ levels are between the two arguments (inclusive).  If the two arguments
 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
 
@@ -29926,11 +30730,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
@@ -29941,7 +30746,8 @@ type and value for simple data types, and the name and type for arrays,
 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.
@@ -29966,13 +30772,14 @@ This command is deprecated in favor of the
 (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
@@ -29980,7 +30787,8 @@ Display the names of local variables and function arguments for the selected fra
 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
 



More information about the Gdb-patches mailing list