public inbox for archer-commits@sourceware.org
help / color / mirror / Atom feed
* [SCM]  archer-pmuldoon-python-backtrace: Elide now returns an iterator.  Default values for fields are not populated, but left blank.  Elided frames are called recursivley from the eliding frame.  Rewrite tests.  Do not allow dummy synthetic frames without a backing (borrowed) architecture.  Add BaseFrameWrapper, and split up FrameWrapper into BaseWrapper. FrameWrapper is not a documented reference interface.
@ 2012-07-11 14:18 pmuldoon
  0 siblings, 0 replies; only message in thread
From: pmuldoon @ 2012-07-11 14:18 UTC (permalink / raw)
  To: archer-commits

The branch, archer-pmuldoon-python-backtrace has been updated
       via  54612dd2bc40b8cf406b5f5c338239836a0c68b6 (commit)
      from  0f867d14147dc0ace45c24f247551f48a9138739 (commit)

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

- Log -----------------------------------------------------------------
commit 54612dd2bc40b8cf406b5f5c338239836a0c68b6
Author: Phil Muldoon <pmuldoon@redhat.com>
Date:   Wed Jul 11 15:16:36 2012 +0100

    Elide now returns an iterator.  Default values for fields are not
    populated, but left blank.  Elided frames are called recursivley from
    the eliding frame.  Rewrite tests.  Do not allow dummy synthetic
    frames without a backing (borrowed) architecture.  Add
    BaseFrameWrapper, and split up FrameWrapper into BaseWrapper.
    FrameWrapper is not a documented reference interface.

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

Summary of changes:
 gdb/data-directory/Makefile.in              |    7 +-
 gdb/python/lib/gdb/BaseFrameWrapper.py      |  102 ++++++++
 gdb/python/lib/gdb/FrameWrapper.py          |  161 +++++++-----
 gdb/python/lib/gdb/command/frame_filters.py |   41 +--
 gdb/python/py-framefilter.c                 |  363 ++++++++++++++-------------
 gdb/testsuite/gdb.python/py-framefilter.exp |   14 +-
 gdb/testsuite/gdb.python/py-framefilter.py  |  103 ++++++--
 7 files changed, 488 insertions(+), 303 deletions(-)
 create mode 100644 gdb/python/lib/gdb/BaseFrameWrapper.py

First 500 lines of diff:
diff --git a/gdb/data-directory/Makefile.in b/gdb/data-directory/Makefile.in
index ea2c682..1679d09 100644
--- a/gdb/data-directory/Makefile.in
+++ b/gdb/data-directory/Makefile.in
@@ -53,12 +53,13 @@ PYTHON_DIR = python
 PYTHON_INSTALL_DIR = $(DESTDIR)$(GDB_DATADIR)/$(PYTHON_DIR)
 PYTHON_FILES = \
 	gdb/__init__.py \
-	gdb/types.py \
-	gdb/printing.py \
-	gdb/prompt.py \
+	gdb/BaseFrameWrapper.py \
 	gdb/FrameFilter.py \
 	gdb/FrameIterator.py \
 	gdb/FrameWrapper.py \
+	gdb/types.py \
+	gdb/printing.py \
+	gdb/prompt.py \
 	gdb/command/__init__.py \
 	gdb/command/frame_filters.py \
 	gdb/command/pretty_printers.py \
diff --git a/gdb/python/lib/gdb/BaseFrameWrapper.py b/gdb/python/lib/gdb/BaseFrameWrapper.py
new file mode 100644
index 0000000..c24463e
--- /dev/null
+++ b/gdb/python/lib/gdb/BaseFrameWrapper.py
@@ -0,0 +1,102 @@
+# Copyright (C) 2012 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
+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.
+    def __init__(self, base):
+        super(BaseFrameWrapper, self).__init__(base)
+        self.base = base
+
+    def elide (self):
+        if hasattr(self.base, "elide"):
+            return self.base.elide()
+
+        return None
+
+    def function (self):
+        if hasattr(self.base, "function"):
+            return str(self.base.function())
+
+        fname = str (self.base.function())
+        if (fname == ""):
+            return None
+        else:
+            return fname
+
+    def address (self):
+        if hasattr(self.base, "address"):
+            return self.base.address()
+
+        return self.base.pc()
+
+    def filename (self):
+        if hasattr(self.base, "filename"):
+            return self.base.filename()
+
+        sal = self.base.find_sal()
+        if (sal):
+            return sal.symtab.filename
+        else:
+            return None
+
+    def frame_args (self):
+        if hasattr(self.base, "frame_args"):
+            return self.base.frame_args()
+
+        args = self.base.arguments()
+        args_list = []
+        if args != None:
+            for arg in args:
+                value = arg.value(self.base)
+                args_list.append((arg, value))
+
+        return args_list
+
+    def frame_locals (self):
+        if hasattr(self.base, "frame_locals"):
+            return self.base.frame_locals()
+
+        frame_locals = self.base.locals()
+        frame_locals_list = []
+        if frame_locals != None:
+            for frame_local in frame_locals:
+                value = frame_local.value(self.base)
+                frame_locals_list.append((frame_local, value))
+
+        return frame_locals_list
+
+    def line (self):
+        if hasattr(self.base, "line"):
+            return self.base.line()
+
+        sal = self.base.find_sal()
+        if (sal):
+            return sal.line        
+        else:
+            return None
+
+    def inferior_frame (self):
+        if hasattr(self.base, "inferior_frame"):
+            return self.base.inferior_frame()
+
+        return self.base
diff --git a/gdb/python/lib/gdb/FrameWrapper.py b/gdb/python/lib/gdb/FrameWrapper.py
index 91ae620..b565b89 100644
--- a/gdb/python/lib/gdb/FrameWrapper.py
+++ b/gdb/python/lib/gdb/FrameWrapper.py
@@ -16,95 +16,130 @@
 import gdb
 
 class FrameWrapper (object):
-    "Base Frame Wrapper"
+    """Interface for a Frame Wrapper"""
 
-    # frame her can refer to a gdb.Frame or another frame like object
-    # conforming to the interface in this class.  As we can have frame
-    # wrappers wrapping frame wrappers, we should defer to that
-    # object's method.
+    """ A frame wrapper wraps a frame and provides additional and
+    convenience methods. """
     def __init__(self, frame):
         super(FrameWrapper, self).__init__()
         self.frame = frame
 
-    def omit (self):
-        return False
-
-    def elide (self):
-        return False
+    def elided (self):
+        """ The 'elided' function 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.
+
+        Arguments: None 
+        
+        Returns: The 'elide' function must return an iterator that
+        contains the frames that are being elided.  Elided frames are
+        indented from normal frames in a backtrace, to show affinity
+        with the frame that elided them.  Note that it is the Frame
+        Filter's task to filter out the elided frames from the
+        iterator the source frames were acquired, and also to provide
+        the iterator of elided frames in this function.
+
+        If this function returns a Python None, no frames will be
+        elided.
+        """
+       
+        pass
 
     def function (self):
-        if hasattr(self.frame, "function"):
-            return str(self.frame.function())
+        """ The name of the function in the frame.
 
-        fname = str (self.frame.function())
-        if (fname == ""):
-            return "<unknown function>"
-        else:
-            return fname
+        Arguments: None.
 
-    def level (self, level):
-        if hasattr(self.frame, "level"):
-            return self.frame.level()
+        Returns: A string describing the function.
 
-        return level
+        If this function returns a Python None, no data will be
+        displayed for this field at printing.
+        """
+        pass
 
     def address (self):
-        if hasattr(self.frame, "address"):
-            return self.frame.address()
+        """ The address of the frame.
+
+        Arguments: None.
+
+        Returns: A numeric integer type of sufficient size to describe
+        the address of the frame.
+
+        If this function returns a Python None, no data will be
+        displayed for this field at printing.
+        """
 
-        return self.frame.pc()
+        pass
 
     def filename (self):
-        if hasattr(self.frame, "filename"):
-            return self.frame.filename()
+        """ The filename associated with the function and line number
+        addressed by this frame.
+
+        Arguments: None.
+
+        Returns: A string containing the filename, and optionally, the
+        path to the filename of the frame.
+
+        If this function returns a Python None, the field output from
+        the function will be left blank.""
+        """
+
+        pass
 
-        sal = self.frame.find_sal()
-        if (sal):
-            return sal.symtab.filename
-        else:
-            return "<unknown filename>"
+    def line (self):
+        """ The line number associated with the current position
+        within the function addressed by this frame.
+
+        Arguments: None.
+
+        Returns: A number integer type line number
+
+        If this function returns a Python None, the field output from
+        the function will be left blank.""
+        """
+
+        pass
 
     def frame_args (self):
-        if hasattr(self.frame, "frame_args"):
-            return self.frame.frame_args()
+        """ The arguments of the function in this frame.
+
+        Arguments: None.
 
-        args = self.frame.arguments()
-        args_list = []
-        if args != None:
-            for arg in args:
-                value = arg.value(self.frame)
-                args_list.append((arg, value))
+        Returns: An iterator that returns a tuple pairing of
+        "argument", and "value".  The "argument" element can be either
+        a gdb.Symbol or a string.  The "value" argument must be a
+        gdb.Value or a Python value that can be translated into a
+        gdb.Value.
 
-        return args_list
+
+        If this function returns a Python None, frame arguments will
+        not be printed.
+        """
+        pass
 
     def frame_locals (self):
-        if hasattr(self.frame, "frame_locals"):
-            return self.frame.frame_locals()
+        """ The local variables of the function in this frame.
 
-        frame_locals = self.frame.locals()
-        frame_locals_list = []
-        if frame_locals != None:
-            for frame_local in frame_locals:
-                value = frame_local.value(self.frame)
-                frame_locals_list.append((frame_local, value))
+        Arguments: None.
 
-        return frame_locals_list
+        Returns: An iterator that returns a tuple pairing of
+        "argument", and "value".  The "argument" element can be either
+        a gdb.Symbol or a string.  The "value" argument must be a
+        gdb.Value or a Python value that can be translated into a
+        gdb.Value.
 
-    def line (self):
-        if hasattr(self.frame, "line"):
-            return self.frame.line()
 
-        sal = self.frame.find_sal()
-        if (sal):
-            return sal.line        
-        else:
-            return "<unknown line>"
+        If this function returns a Python None, local variables will
+        not be printed.
+        """
+        pass
 
-    def inferior_frame (self):
-        if hasattr(self.frame, "inferior_frame"):
-            return self.frame.inferior_frame()
+    def frame (self):
+        """ The gdb.Frame that this wrapper is wrapping.
 
-        return self.frame
+        Arguments: None.
 
-    def older(self):
-        return self.frame.older()
+        Returns: The gdb.Frame that this wrapper is wrapping.
+        """
+        pass
diff --git a/gdb/python/lib/gdb/command/frame_filters.py b/gdb/python/lib/gdb/command/frame_filters.py
index cec5d1c..59ec9b2 100644
--- a/gdb/python/lib/gdb/command/frame_filters.py
+++ b/gdb/python/lib/gdb/command/frame_filters.py
@@ -20,23 +20,8 @@ import gdb
 import copy
 import gdb.FrameFilter
 from gdb.FrameIterator import FrameIterator
-from gdb.FrameWrapper import FrameWrapper
-
-class PrimordialFilter:
-
-    def filter_unwrapped (self, frame):
-        foo =  gdb.Frame
-        if isinstance (frame, foo):
-            return True
-        else:
-            return False
-
-    def filter (self, iterator):
-        for it in iterator:
-            if self.filter_unwrapped (it):
-                yield FrameWrapper(it)
-            else:
-                yield it
+from gdb.BaseFrameWrapper import BaseFrameWrapper
+import itertools
 
 def _parse_arg (cmd_name, arg):
     """ Internal Worker function to take an argument and return a
@@ -79,10 +64,10 @@ def _set_priority(filter_item, priority):
         priority: The priority to assign as an integer.
     """
 
-    if priority < 0 and priority > 10000:
-        raise SyntaxError("Priority must be between 0 - 10000")
     if hasattr(filter_item, "priority"):
         filter_item.priority = priority
+    else:
+        raise gdb.GdbError("Cannot find class attribute 'priority'")
 
 def _get_enabled(filter_item):
     """ Internal Worker function to return the frame-filter's enabled
@@ -96,7 +81,7 @@ def _get_enabled(filter_item):
     if hasattr(filter_item[1], "enabled"):
         return filter_item[1].enabled
     else:
-        return True
+        raise gdb.GdbError("Cannot find class attribute 'enabled'")
 
 def _set_enabled(filter_item, state):
     """ Internal Worker function to set the frame-filter's enabled
@@ -107,9 +92,10 @@ def _set_enabled(filter_item, state):
         and the second being the frame-filter object.
         state: True or False, depending on desired state.
     """
-
     if hasattr(filter_item, "enabled"):
         filter_item.enabled = state
+    else:        
+        raise gdb.GdbError("Cannot find class attribute 'enabled'")
 
 def _get_name (frame_filter):
     """ Internal Worker function to return the name of the
@@ -121,10 +107,7 @@ def _get_name (frame_filter):
     """
     if hasattr(frame_filter, "name"):
         return frame_filter.name
-    if hasattr(frame_filter, "__name__"):
-        return frame_filter.__name__
-    # Deal with anonymous objects/functions
-    return "Unknown"
+    raise gdb.GdbError("Cannot find class attribute 'name'")
 
 def _return_list (name):
     """ Internal Worker function to return the frame-filter name,
@@ -178,11 +161,15 @@ def invoke (frame):
     """
     sorted_list = _sort_list()
     frame_iterator = FrameIterator (frame)
+
+    # Apply base filter to all gdb.Frames.  This unifies the in
+    # interface
+
+    frame_iterator = itertools.imap (BaseFrameWrapper, frame_iterator) 
+
     for ff in sorted_list:
         frame_iterator = ff[1].filter (frame_iterator)
 
-    pri = PrimordialFilter ()
-    frame_iterator = pri.filter (frame_iterator)
     return frame_iterator
 
 class InfoFrameFilter(gdb.Command):
diff --git a/gdb/python/py-framefilter.c b/gdb/python/py-framefilter.c
index 42664f9..304e243 100644
--- a/gdb/python/py-framefilter.c
+++ b/gdb/python/py-framefilter.c
@@ -28,6 +28,7 @@
 #include "ui-out.h"
 #include "valprint.h"
 #include "annotate.h"
+#include "hashtab.h"
 
 #ifdef HAVE_PYTHON
 #include "python-internal.h"
@@ -297,204 +298,163 @@ py_print_args (PyObject *filter,
   return 0;
 }
 
-static CORE_ADDR
-get_address (PyObject *filter, int *error)
+/* Hash function for the printed frame hash.  */
+
+static hashval_t
+hash_printed_frame_entry (const void *data)
 {
-  PyObject *result = NULL;
-  CORE_ADDR address = 0;
-  
-  *error = 0;
-  if (PyObject_HasAttrString (filter, "address"))
-      result = PyObject_CallMethod (filter, "address", NULL);
-  else
-    {
-      if (PyObject_HasAttrString (filter, "pc"))
-	  result = PyObject_CallMethod (filter, "pc", NULL);
-      else
-	return 0;
-    }
-      
-  if (result)
-    {
-      address = PyLong_AsLong (result);
-      Py_DECREF (result);
-    }
-  else
-    *error = 1;
+  const struct frame_info *frame = data;
+
+  return htab_hash_pointer (frame);
+}
+
+/* Equality function for the printed hash.  */
+
+static int
+eq_printed_frame_entry (const void *a, const void *b)
+{
+  const struct frame_info *ea = a;
+  const struct frame_info *eb = b;
   
-  return address;
+  return ea == eb;
 }
 
+
 static int
 py_print_frame (PyObject *filter,
 		int print_level,
 		enum print_what print_what,
 		int print_args,
 		const char *print_args_type,
+		int print_locals,
 		struct ui_out *out,
-		struct value_print_options opts)
+		struct value_print_options opts,
+		int indent,
+		htab_t levels_printed)
 {
-  int level = 0;
+  int has_addr = 0;
   CORE_ADDR address = 0;
   struct gdbarch *gdbarch = NULL;


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


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

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

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-07-11 14:18 [SCM] archer-pmuldoon-python-backtrace: Elide now returns an iterator. Default values for fields are not populated, but left blank. Elided frames are called recursivley from the eliding frame. Rewrite tests. Do not allow dummy synthetic frames without a backing (borrowed) architecture. Add BaseFrameWrapper, and split up FrameWrapper into BaseWrapper. FrameWrapper is not a documented reference interface 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).