public inbox for archer-commits@sourceware.org
help / color / mirror / Atom feed
* [SCM]  archer-pmuldoon-python-backtrace: Clean up typos.  Fix testsuite due to type changes in GDB.  Document python code.
@ 2012-11-27 14:10 pmuldoon
  0 siblings, 0 replies; only message in thread
From: pmuldoon @ 2012-11-27 14:10 UTC (permalink / raw)
  To: archer-commits

The branch, archer-pmuldoon-python-backtrace has been updated
       via  f4ac160f931caacea57610f08d92f80221e5d893 (commit)
      from  6bc97e6b4fd186000825e9e20021e253580dd840 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email.

- Log -----------------------------------------------------------------
commit f4ac160f931caacea57610f08d92f80221e5d893
Author: Phil Muldoon <pmuldoon@redhat.com>
Date:   Tue Nov 27 14:09:23 2012 +0000

    Clean up typos.  Fix testsuite due to type changes in GDB.  Document
    python code.

-----------------------------------------------------------------------

Summary of changes:
 gdb/doc/gdb.texinfo                            |   51 ++++----
 gdb/python/lib/gdb/BaseFrameWrapper.py         |  151 ++++++++++++++++++------
 gdb/python/py-framefilter.c                    |   10 +-
 gdb/testsuite/gdb.python/py-framefilter-mi.exp |    8 +-
 gdb/testsuite/gdb.python/py-framefilter.py     |    3 +-
 5 files changed, 149 insertions(+), 74 deletions(-)

First 500 lines of diff:
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index d900402..837bf34 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -24050,19 +24050,19 @@ 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 
+@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}.  
+@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: 
+commands that work with frame filters are:
 
-@code{backtrace} (@pxref{backtrace-command,, The backtrace command}), 
+@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
@@ -24074,7 +24074,7 @@ commands that work with frame filters are:
 Frame filters work by applying actions to an iterator that is passed
 to the frame filter.  The frame filter works with tools such as
 Python's @code{itertools} module to modify the iterator, and returns
-this modified iterator. A frame filter must not alter the underlying
+this modified iterator.  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}.
@@ -24091,7 +24091,7 @@ 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. 
+reached the order in the priority list for that filter.
 
 For example, if there are four frame filters:
 
@@ -24164,7 +24164,7 @@ priority are executed in unsorted order in that priority slot.  This
 attribute is mandatory.
 @end defvar
 
-@node Frame Wrapper API 
+@node Frame Wrapper API
 @subsubsection Wrapping and Decorating Frames.
 @cindex Frame Wrapper API
 
@@ -24280,7 +24280,7 @@ class SymValueWrapper ():
         return self.val
 
     def symbol (self):
-      
+
         return self.sym
 
 class SomeFrameWrapper ()
@@ -24289,7 +24289,7 @@ class SomeFrameWrapper ()
     def frame_args (self):
         fvars = []
         fvars.append (SymValueWrapper (``foo'', 42))
-        
+
         return iter (fvars)
 @end smallexample
 
@@ -24328,7 +24328,7 @@ class SymValueWrapper ():
         return self.val
 
     def symbol (self):
-      
+
         return self.sym
 
 class SomeFrameWrapper ()
@@ -24337,10 +24337,10 @@ 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.
 
@@ -24400,7 +24400,7 @@ 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,
+@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:
 
@@ -24470,7 +24470,7 @@ this is a valid operation for frame filters that have the
 
 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
+frames.  @xref{Frame Wrapper API}, for the further information on the
 interface.
 
 The following example works on inlined frames.  It highlights frames
@@ -24488,13 +24488,13 @@ 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 may be too expensive at the filtering step. The frame filter
+inlined may be too expensive at the filtering step.  The frame filter
 cannot know how many frames it has to deal with, and it would have to
 iterate through them all.  This ends up duplicating effort as
-@value{GDBN} performs this unwinding when it prints the frames. In
+@value{GDBN} performs this unwinding when it prints the frames.  In
 this example it can be deferred to the printing step where it can
 examine each frame when it is printed.  From a performance viewpoint,
-this is an important note. A backtrace from large or complex programs
+this is an important note.  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
@@ -24517,7 +24517,7 @@ class InlineFilter ():
 
 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.  
+@code{InlinedFrameWrapper} to each element in the iterator.
 
 Below is the frame wrapper:
 
@@ -24529,7 +24529,7 @@ class InlinedFrameWrapper (BaseFrameWrapper):
         self.fobj = fobj
 
     def function (self):
-        frame = self.inferior_frame()        
+        frame = self.inferior_frame()
         name = str(frame.name())
         function = str(frame.function())
 
@@ -24585,7 +24585,7 @@ class InlineFrameFilter ():
 
 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: 
+it (@code{frame_iter}) with a custom iterator:
 @code{ElidingInlineIterator}.  This again defers actions to when
 @value{GDBN} prints the backtrace, as the iterator is not traversed
 until printing.
@@ -24618,10 +24618,10 @@ 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.  
+elided frame, and the eliding frame.
 
 @smallexample
-ElidingInlineWrapper(BaseFrameWrapper):
+class ElidingInlineWrapper(BaseFrameWrapper):
 
     def __init__(self, frame, elided_frames):
         super(ElidingInlineWrapper, self).__init__(frame)
@@ -24671,7 +24671,7 @@ 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.  
+@var{filter-name} is the name of the frame filter.
 
 Example:
 
@@ -24728,7 +24728,7 @@ objfile /build/test frame-filters:
 
 @end smallexample
 
-@kindex set python frame-filter priority 
+@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
@@ -30408,6 +30408,7 @@ For a stack with frame levels 0 through 11:
 @anchor{-stack-list-arguments}
 @subheading The @code{-stack-list-arguments} Command
 @findex -stack-list-arguments
+
 @subsubheading Synopsis
 
 @smallexample
@@ -30498,9 +30499,11 @@ 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
diff --git a/gdb/python/lib/gdb/BaseFrameWrapper.py b/gdb/python/lib/gdb/BaseFrameWrapper.py
index 0ddeb55..169930f 100644
--- a/gdb/python/lib/gdb/BaseFrameWrapper.py
+++ b/gdb/python/lib/gdb/BaseFrameWrapper.py
@@ -17,20 +17,43 @@ import gdb
 from gdb.FrameWrapper import FrameWrapper
 
 class BaseFrameWrapper (FrameWrapper):
-    "Base Frame Wrapper"
-
-    # 'base' here can refer to a gdb.Frame or another frame like
-    # object conforming to the interface of the FrameWrapper class.
-    # As we can have frame wrappers wrapping frame wrappers, we should
-    # defer to that object's method.
+    """Basic implementation of a Frame Wrapper"""
+
+    """ This base frame wrapper wraps a frame or another frame
+    wrapper, and provides convenience methods.  If this object is
+    wrapping a frame wrapper, defer to that wrapped object's method if
+    it has one.  This allows for frame wrappers that have sub-classed
+    BaseFrameWrapper, but also wrap other frame wrappers 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 wrappers, all sub-classed from
+    BaseFrameWrapper:
+
+    Wrapper1(Wrapper2(BaseFrameWrapper(gdb.Frame)))
+
+    In this case we have two frame wrappers, both of which are
+    sub-classed from BaseFrameWrapper.  If Wrapper1 just overrides the
+    'function' method, then all of the other methods are carried out
+    by the super-class BaseFrameWrapper.  But Wrapper2 may have
+    overriden other methods, so BaseFrameWrapper 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 filter.  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):
         super(BaseFrameWrapper, self).__init__(base)
         self.base = base
 
-        # Determine if this a library or limited frame
-        frame = self.inferior_frame()
-
-    def is_limited_frame (self, frame):
+    @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
@@ -42,116 +65,158 @@ class BaseFrameWrapper (FrameWrapper):
         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):
-        # As this is the base wrapper, "base" can either be a gdb.Frame,
-        # or a another frame wrapper object (another filter may extend
-        # this object, but not implement "function".  So in this case
-        # we must instance check what "base" is, as later there is
-        # some work to be done on solib names.
-        if isinstance(self.base, gdb.Frame):
-            name = self.base.name()
-        else:
+        """ Return the name of the frame's function, first determining
+        if it 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 not isinstance(self.base, gdb.Frame):
             if hasattr(self.base, "function"):
-                return str(self.base.function())
+                return self.base.function()
 
         frame = self.inferior_frame()
 
-        if frame == gdb.DUMMY_FRAME:
+        if frame.type() == gdb.DUMMY_FRAME:
             return "<function called from gdb>"
-        elif frame == gdb.SIGTRAMP_FRAME:
+        elif frame.type() == gdb.SIGTRAMP_FRAME:
             return "<signal handler called>"
 
-        sal = frame.find_sal ()
-        pc = frame.pc ()
+        func = frame.function()
+        sal = frame.find_sal()
+        pc = frame.pc()
 
-        if not name and not sal.symtab:
+        if func == None:
             unknown =  format (" 0x%08x in" % pc)
             return unknown
 
-        return name
+        return str(func)
 
     def address (self):
+        """ Return the address of the frame's pc"""
+
         if hasattr(self.base, "address"):
             return self.base.address()
 
-        return self.base.pc()
+        frame = self.inferior_frame()
+        return frame.pc()
 
     def filename (self):
+        """ Return the filename associated with this frame, detecting
+        and returns the appropriate library name is this is a shared
+        library."""
+
         if hasattr(self.base, "filename"):
             return self.base.filename()
 
-        sal = self.base.find_sal()
+        frame = self.inferior_frame()
+        sal = frame.find_sal()
         if (not sal.symtab or not sal.symtab.filename):
-            pc = self.inferior_frame().pc()
+            pc = frame.pc()
             return gdb.solib_name (pc)
         else:
             return sal.symtab.filename
 
     def frame_args (self):
+        """ Return an iterator of frame arguments for this frame, if
+        any.  The iterator 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()
 
-        if self.is_limited_frame (self.base):
+        frame = self.inferior_frame()
+        if self.is_limited_frame (frame):
             return None
 
-        args = FrameVars (self.base)
+        args = FrameVars (frame)
         return args.fetch_frame_args()
 
     def frame_locals (self):
+        """ Return an iterator of local variables for this frame, if
+        any.  The iterator 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()
 
-        if self.is_limited_frame (self.base):
+        frame = self.inferior_frame()
+        if self.is_limited_frame (frame):
             return None
 
-        args = FrameVars (self.base)
+        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()
 
-        if self.is_limited_frame (self.base):
+        frame = self.inferior_frame()
+        if self.is_limited_frame (frame):
             return None
 
-        sal = self.base.find_sal()
+        sal = frame.find_sal()
         if (sal):
             return sal.line
         else:
             return None
 
     def inferior_frame (self):
+        """ Return the gdb.Frame underpinning this frame wrapper."""
+
+        # If 'base' is a frame wrapper, 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 BaseSymValueWrapper ():
-
+    """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 ():
 
+    """Utility class to fetch and store frame local variables, or
+    frame arguments."""
+
     def __init__(self,frame):
         self.frame = frame
 
-    def fetch_b (self, sym):
+    @staticmethod
+    def fetch_b (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."""
 
-        # We may have a string as a symbol, in the case of synthetic
-        # locals/args
+        # 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
 
@@ -168,6 +233,9 @@ class FrameVars ():
           }.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 not frame local variables, return None."""
         lvars = []
         try:
             block = self.frame.block()
@@ -186,6 +254,10 @@ class FrameVars ():
         return iter (lvars)
 
     def fetch_frame_args (self):
+        """Public utility method to fetch frame argument for the
+        stored frame.  Frame arguments are the only type fetched.  If
+        there are no frame arguments variables, return None."""
+
         args = []
         try:
             block = self.frame.block()
@@ -203,6 +275,7 @@ class FrameVars ():
         return iter (args)
 
     def get_value (self, sym, block):
+        """Public utility method to fetch a value from a symbol."""
         if len (sym.linkage_name):
             nsym, is_field_of_this = gdb.lookup_symbol (sym.linkage_name, block)
             if nsym != None:
diff --git a/gdb/python/py-framefilter.c b/gdb/python/py-framefilter.c
index a508a4b..d48ed28 100644
--- a/gdb/python/py-framefilter.c
+++ b/gdb/python/py-framefilter.c
@@ -44,7 +44,7 @@
    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
+   denoting the language attributed to the Symbol.  In the case of
    **SYM being NULL, this will be set to the current language.
    Returns 0 on error with the appropriate Python exception set, and 1
    on success.  */
@@ -342,7 +342,7 @@ get_py_iter_from_func (PyObject *filter, char *func)
     frame argument structure.  If FA is populated, both SYM_NAME and
     FV are ignored.  OPTS contains the value printing options,
     MI_PRINT_TYPE is an enumerator to the value types that will be


hooks/post-receive
--
Repository for Project Archer.


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

only message in thread, other threads:[~2012-11-27 14:10 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-11-27 14:10 [SCM] archer-pmuldoon-python-backtrace: Clean up typos. Fix testsuite due to type changes in GDB. Document python code 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).