public inbox for archer-commits@sourceware.org
help / color / mirror / Atom feed
* [SCM] archer-pmuldoon-python-backtrace: Rewrite and expand Writing Frame wrappers
@ 2012-11-23 16:39 pmuldoon
0 siblings, 0 replies; only message in thread
From: pmuldoon @ 2012-11-23 16:39 UTC (permalink / raw)
To: archer-commits
The branch, archer-pmuldoon-python-backtrace has been updated
via cf459d1c1c341a43afb77c0296975843ec81700a (commit)
from 8e8f7e135250a9d8332cc59be8a5ca68aba333f4 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email.
- Log -----------------------------------------------------------------
commit cf459d1c1c341a43afb77c0296975843ec81700a
Author: Phil Muldoon <pmuldoon@redhat.com>
Date: Fri Nov 23 16:38:29 2012 +0000
Rewrite and expand Writing Frame wrappers
-----------------------------------------------------------------------
Summary of changes:
gdb/doc/gdb.texinfo | 628 ++++++++++++++++++++++++++++-----------------------
1 files changed, 351 insertions(+), 277 deletions(-)
First 500 lines of diff:
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index f93bb40..bcbb94b 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -24115,21 +24115,19 @@ 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 in turn, the
-previous frame filter may have wrapped some @code{BaseFrameWrappers}
-in its own custom frame wrapper. As Frame Wrappers must also conform
-to a mandatory interface, these wrappers can be assumed to act in a
-uniform manner (@pxref{Writing a Frame Filter/Wrapper}).
+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 in turn, the previous
+frame filter may have wrapped some or all of the frame wrappers in
+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 returned by the iterator must be a an object
-conforming to the frame wrapper interface. As the initial iterator in
-the sequence is already wrapped in @code{BaseFrameWrapper} then if this
-iterator has no operations to perform it may just return the iterator
-without alteration.
+protocol. Each item in the iterator must be an object conforming to
+the frame wrapper interface. If the frame filter does not wish to do
+anything in this sequence, it should return the iterator untouched.
This method is not optional. If it does not exist, @value{GDBN} will
raise and print an error.
@@ -24144,226 +24142,47 @@ unique. This attribute is mandatory.
@end defvar
@defvar FrameFilter.enabled
-The @code{enabled} attribute must be Python boolean. This attributes
-controls whether the frame filter is enabled. 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.
+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 priority assigned to a
-frame filter, the sooner it will be executed in relation to other
-frame filters. Though @code{priority} can be negative, it is good
-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.
+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 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 name/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, 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} which also contain a
-@code{frame_filters} dictionary attribute.
-
-Each 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}).
-
-When a command is run from @value{GDBN} that is compatible with frame
-filters, @value{GDBN} combines all of the dictionaries from the
-@code{global}, @code{gdb.Progspace} and @code{gdb.ObjFiles}
-dictionaries. All of the @code{gdb.Objfiles} 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}, and finally, sorts these frame
-filters 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 the iterator wrapping this collection of
-@code{BaseFrameWrapper} frame wrapper objects. The output from
-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},
-and if so, implement a filtering strategy. A bare-bones frame filter
-follows the pattern:
-
-@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
-
-In the example above the frame filter implements the three steps that
-it must fulfill. 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
-related 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 third and final step of our small 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
-return an iterator. In this example, this frame filter is not very
-useful as it just returns the iterator untouched. However this is a
-valid operation for frame filters that have decided not to operate on
-any frames.
-
-In the next example, the frame filter operates on all frames, and
-uses a Frame Wrapper. @xref{Frame Wrapper API}, for the API
-relating to a @code{Frame Wrapper}.
-
-This example is a working demonstration. It works on inlined frames,
-by applying a frame wrapper to all frames with the Python
-@code{itertools imap} method. This example also introduces a new
-decision making topic: whether to perform operations at the filtering
-step, or at the printing step. For this example's approach it does
-not perform any filtering operations at the filtering step beyond
-mapping the frame wrapper to each frame. Instead we defer decision
-making to printing time. This is an important
-consideration. To search every frame to determine if it is inlined
-may be too expensive, as the frame filter does not know how many
-frames it has to deal with. In this case it can be deferred to the
-printing step as we can examine each frame when it is printed. This
-is an important consideration to note, as a backtrace from a large or
-complex program can constitue many thousands of frames. If there
-are many frame filters unwinding the stack during filtering, it can
-substantially delay the printing of the backtrace.
-
-@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 examples, except
-in the @code{filter} method we apply a frame wrapper with the object
-name @code{InlinedFrameWrapper} to each element in the iterator.
-Below is the frame wrapper:
-
-@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 actually defines the @code{function} method.
-It lets the supplied @code{BaseFrameWrapper} which is shipped with
-@value{GDBN} do most of the other work. The combination of these two
-objects create this output from a backtrace:
-
-@smallexample
-#0 0x004004e0 in bar () at inline.c:11
-#2 0x00400566 in max [inlined from main] (b=6, a=12) at inline.c:21
-#3 0x00400566 in main () at /home/pmuldoon/inline.c:31
-@end smallexample
-
-So in the case of this example, as each frame wrapper is applied to
-all frames, and the frame wrapper makes a decision on what to print in
-the @code{function} callback, the strategy can defer decisions on the
-frame content to printing time.
-
-
@node Frame Wrapper API
@subsubsection Wrapping and Decorating Frames.
@cindex Frame Wrapper API
-Frame wrappers are sister objects that decorate frames affected by
-frame filters. Frame wrappers can only be used in conjunction with
-Frame wrappers.
+Frame wrappers are sister objects to frame filters (@pxref{Frame
+Filters API}) that decorate frames worked on by frame filters. Frame
+wrappers can only be used in conjunction with frame filters.
Frame wrappers are applied by frame filters and customize the printed
-content of each frame via an API, defined here. A frame wrapper works
-on one frame, but a frame wrapper object can be applied to many
-multiple frames.
+content of each frame via 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 one frame wrapper called
+@code{BaseFrameWrapper}. This contains substantial amounts of
+boilerplate code to print frames, and it is advisable to inherit and
+extend this frame wrapper, 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 ()
@@ -24373,14 +24192,15 @@ 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, and contains the frames that are being
-elided, 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.
+Python iterator protocol, which contains the frames that are being
+elided wrapped in a suitable frame wrapper, 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.
-Note that it is the frame filter that instantiated this frame
-wrapper's task to filter out the elided frames from the source
-iterator. This will avoid the frame being printed twice.
+Note that 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.
If this function returns @code{None}, no frames will be elided.
@end defun
@@ -24439,12 +24259,13 @@ iterator protocol. 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, and
-@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 @code{None}, and the @code{argument} method
-returns a @code{gdb.Symbol}, @value{GDBN} will read and print the value
-of the @code{gdb.Symbol} automatically.
+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 @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:
@@ -24476,7 +24297,7 @@ Even if the @code{frame_args} method returns only a single object, it
must be wrapped in an iterator.
If this function returns a @code{None}, @value{GDBN} will not print
-locals for this frame.
+arguments for this frame.
@end defun
@defun FrameWrapper.frame_locals ()
@@ -24486,12 +24307,13 @@ iterator protocol. 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, and
-@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 @code{None}, and the @code{argument} method
-returns a @code{gdb.Symbol}, @value{GDBN} will read and print the value
-of the @code{gdb.Symbol} automatically.
+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 @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:
@@ -24524,7 +24346,6 @@ must be wrapped in an iterator.
If this function returns a @code{None}, @value{GDBN} will not print
locals for this frame.
-
@end defun
@defun FrameWrapper.frame ():
@@ -24535,50 +24356,304 @@ for internal frame information such as architecture so as 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 name/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}).
+
+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.ObjFiles} dictionaries
+currently loaded. All of the @code{gdb.Objfiles} 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} and finally, sorts these frame
+filters 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:
+
+@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
+
+In the example above the frame filter implements the three steps that
+it must fulfill. 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
+related 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 the further information on the
+interface.
+
+The following example works on inlined frames. It highlights frames
+which are inlined and the function in which they are inlined. 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 processed when @value{GDBN} prints the backtrace.
+
+This example also introduces a new decision making topic: whether to
+perform decision making operations at the filtering step, or at the
hooks/post-receive
--
Repository for Project Archer.
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2012-11-23 16:39 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-11-23 16:39 [SCM] archer-pmuldoon-python-backtrace: Rewrite and expand Writing Frame wrappers pmuldoon
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).