public inbox for archer-commits@sourceware.org
help / color / mirror / Atom feed
* [SCM]  archer-pmuldoon-python-backtrace: Implement omit and (bogus, non duck typed) elide function.
@ 2012-03-19 15:06 pmuldoon
  0 siblings, 0 replies; only message in thread
From: pmuldoon @ 2012-03-19 15:06 UTC (permalink / raw)
  To: archer-commits

The branch, archer-pmuldoon-python-backtrace has been updated
       via  d34a750b8b79c1260f21e8c25f61b7197448d78f (commit)
      from  0e5e6d2d84fbf0a975c4f83017c845805b7d1ae2 (commit)

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

- Log -----------------------------------------------------------------
commit d34a750b8b79c1260f21e8c25f61b7197448d78f
Author: Phil Muldoon <pmuldoon@redhat.com>
Date:   Mon Mar 19 15:05:11 2012 +0000

    Implement omit and (bogus, non duck typed) elide function.

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

Summary of changes:
 gdb/frame.c                                 |   23 ++++
 gdb/frame.h                                 |    6 +
 gdb/python/py-framefilter.c                 |  145 +++++++++++++++++++++++----
 gdb/python/python.h                         |    6 +-
 gdb/stack.c                                 |   18 +++-
 gdb/testsuite/gdb.python/py-framefilter.c   |    3 +-
 gdb/testsuite/gdb.python/py-framefilter.exp |    4 +-
 gdb/testsuite/gdb.python/py-framefilter.py  |   34 +++++--
 8 files changed, 197 insertions(+), 42 deletions(-)

First 500 lines of diff:
diff --git a/gdb/frame.c b/gdb/frame.c
index e012f2d..3e0cb40 100644
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -127,6 +127,11 @@ struct frame_info
   /* The reason why we could not set PREV, or UNWIND_NO_REASON if we
      could.  Only valid when PREV_P is set.  */
   enum unwind_stop_reason stop_reason;
+
+  /* In Python frame-filtering, we can "elide" frames.  Store state
+     (during printing and processing) if this frame has been elided by
+     another.  */
+  int elide;
 };
 
 /* A frame stash used to speed up frame lookups.  */
@@ -2217,6 +2222,24 @@ frame_relative_level (struct frame_info *fi)
     return fi->level;
 }
 
+int
+frame_print_elide (struct frame_info *fi)
+{
+  if (fi == NULL)
+    return -1;
+  else
+    return fi->elide;
+}
+
+void
+set_frame_print_elide (struct frame_info *fi)
+{
+  if (fi == NULL)
+    return;
+  else
+    fi->elide = 1;
+}
+
 enum frame_type
 get_frame_type (struct frame_info *frame)
 {
diff --git a/gdb/frame.h b/gdb/frame.h
index 7b42b56..c027c81 100644
--- a/gdb/frame.h
+++ b/gdb/frame.h
@@ -428,6 +428,12 @@ extern CORE_ADDR get_frame_args_address (struct frame_info *);
    for an invalid frame).  */
 extern int frame_relative_level (struct frame_info *fi);
 
+/* Whether this frame has been marked as elided for printing
+   purposes.  */
+extern int frame_print_elide (struct frame_info *fi);
+
+extern void set_frame_print_elide (struct frame_info *fi);
+
 /* Return the frame's type.  */
 
 extern enum frame_type get_frame_type (struct frame_info *);
diff --git a/gdb/python/py-framefilter.c b/gdb/python/py-framefilter.c
index d156d7f..ea4edfc 100644
--- a/gdb/python/py-framefilter.c
+++ b/gdb/python/py-framefilter.c
@@ -18,7 +18,6 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
-#include "exceptions.h"
 #include "objfiles.h"
 #include "symtab.h"
 #include "language.h"
@@ -247,8 +246,10 @@ find_frame_filter (PyObject *frame, int print_level,
 }
 
 static int
-print_frame (PyObject *filter, int print_level,
-	     enum print_what print_what, int print_args,
+print_frame (PyObject *filter,
+	     int print_level,
+	     enum print_what print_what,
+	     int print_args,
 	     struct ui_out *out,
 	     struct value_print_options opts,
 	     struct frame_info *frame)
@@ -260,18 +261,53 @@ print_frame (PyObject *filter, int print_level,
   char *func = NULL;
   char *filename = NULL;
   int line = 0;
+  volatile struct gdb_exception except;
+
+  /* First check to see if this frame is to be omitted.  */
+  if (PyObject_HasAttrString (filter, "omit"))
+    {
+      PyObject *result = PyObject_CallMethod (filter, "omit", NULL);
+
+      if (result)
+	{
+	  int omit = 0;
+
+	  if (! PyBool_Check (result))
+	    {
+	      Py_DECREF (result);
+	      PyErr_SetString (PyExc_RuntimeError,
+			       _("'omit' must return type boolean."));
+	      goto error;
+	    }
+
+	  omit = PyObject_IsTrue (result);
+
+	  Py_DECREF (result);
+
+	  if (omit == -1)
+	    goto error;
+	  else if (omit)
+	    return 1;
+	}
+      else
+	goto error;
+    }
 
   if (print_level)
     {
       if (PyObject_HasAttrString (filter, "level"))
 	{
-	  PyObject *result = PyObject_CallMethod (filter, "level", NULL);
+	  PyObject *result = PyObject_CallMethod (filter, "level", "i",
+						  frame_relative_level (frame),
+						  NULL);
 
 	  if (result)
 	    {
 	      level = PyLong_AsLong (result);
 	      Py_DECREF (result);
 	    }
+	  else
+	    goto error;
 	}
       else
 	level = frame_relative_level (frame);
@@ -286,6 +322,8 @@ print_frame (PyObject *filter, int print_level,
 	  address = PyLong_AsLong (result);
 	  Py_DECREF (result);
 	}
+      else
+	goto error;
     }
   else
     address = 0;
@@ -311,15 +349,21 @@ print_frame (PyObject *filter, int print_level,
       if (result)
 	{
 	  char *dup = PyString_AsString (result);
-	  if (dup)
-	    func  = xstrdup (dup);
-	  else
-	    return 0;
+	  if (! dup)
+	    {
+	      Py_DECREF (result);
+	      goto error;
+	    }
+
+	  func = xstrdup (dup);
+
 	  Py_DECREF (result);
 	}
+      else
+	goto error;
     }
   else
-    func = xstrdup("<unknown>");
+    func = xstrdup ("<unknown>");
 
   annotate_frame_function_name ();
   ui_out_field_string (out, "func", func);
@@ -331,12 +375,19 @@ print_frame (PyObject *filter, int print_level,
       if (result)
 	{
 	  char *dup = PyString_AsString (result);
-	  if (dup)
-	    filename  = xstrdup (dup);
-	  else
-	    return 0;
+
+	  if (! dup)
+	    {
+	      Py_DECREF (result);
+	      goto error;
+	    }
+
+	  filename  = xstrdup (dup);
+
 	  Py_DECREF (result);
 	}
+      else
+	goto error;
     }
   else
     func = xstrdup("<unknown function>");
@@ -357,6 +408,8 @@ print_frame (PyObject *filter, int print_level,
 	  line  = PyLong_AsLong (result);
 	  Py_DECREF (result);
 	}
+      else
+	goto error;
     }
   else
     line = 0;
@@ -369,10 +422,55 @@ print_frame (PyObject *filter, int print_level,
   ui_out_text (out, "\n");
   annotate_frame_end ();
 
+  if (PyObject_HasAttrString (filter, "elide"))
+    {
+      PyObject *result = PyObject_CallMethod (filter, "elide", NULL);
+
+      if (result)
+	{
+	  struct frame_info *restart = NULL;
+	  struct frame_info *current = NULL;
+	  /* Fix result here.  */
+	  TRY_CATCH (except, RETURN_MASK_ALL)
+	    {
+	      restart = frame_object_to_frame_info (result);
+	    }
+	  if (except.reason > 0)
+	    {
+	      Py_DECREF (result);
+	      PyErr_SetString (PyExc_RuntimeError,
+			       except.message);
+	      goto error;
+	    }
+	  if (! restart)
+	    {
+	      Py_DECREF (result);
+	      PyErr_SetString (PyExc_RuntimeError,
+			       _("Cannot locate frame to continue backtrace."));
+	      goto error;
+	    }
+	  if (restart != frame)
+	    {
+	      current=get_prev_frame (frame);
+	      while (current!=restart)
+		{
+		  set_frame_print_elide (current);
+		  current = get_prev_frame (current);
+		}
+	    }
+	}
+      else
+	goto error;
+    }
+
   xfree (func);
   xfree (filename);
-
   return 1;
+
+ error:
+  xfree (func);
+  xfree (filename);
+  return 0;
 }
 
 int
@@ -386,6 +484,7 @@ apply_frame_filter (struct frame_info *frame, int print_level,
   int result = 0;
   int print_result = 0;
   struct value_print_options opts;
+  int success = 0;
 
   cleanups = ensure_python_env (gdbarch, current_language);
 
@@ -396,32 +495,34 @@ apply_frame_filter (struct frame_info *frame, int print_level,
   /* Find the constructor.  */
   filter = find_frame_filter (frame_obj, print_level, print_what, print_args);
   Py_DECREF (frame_obj);
+
   make_cleanup_py_decref (filter);
   if (! filter || filter == Py_None)
     goto done;
 
   get_user_print_options (&opts);
-  print_result = print_frame (filter, print_level, print_what,
-			      print_args, out, opts, frame);
+  success =  print_frame (filter, print_level, print_what,
+			  print_args, out, opts, frame);
   
-  if (print_result)
-    result = 1;
-  else
+  /* 'print_frame' can return a frame to "resume" from, in the case
+     that frames have been elided.  If the return value is NULL, also
+     check to see if this was because a Python error occurred.  */
+  if (success == 0 && PyErr_Occurred())
     gdbpy_print_stack ();
 
  done:
   do_cleanups (cleanups);
-  return result;
+  return success;
 }
 
 #else /* HAVE_PYTHON */
 
-int
+struct frame_info *
 apply_frame_filter (struct frame_info *frame, int print_level,
 		    enum print_what print_what, int print_args,
 		    struct ui_out *out)
 {
-  return 0;
+  return NULL;
 }
 
 #endif /* HAVE_PYTHON */
diff --git a/gdb/python/python.h b/gdb/python/python.h
index 0344aa9..32a5653 100644
--- a/gdb/python/python.h
+++ b/gdb/python/python.h
@@ -39,8 +39,10 @@ int apply_val_pretty_printer (struct type *type, const gdb_byte *valaddr,
 			      const struct value_print_options *options,
 			      const struct language_defn *language);
 
-int apply_frame_filter (struct frame_info *frame, int print_level,
-			enum print_what print_what, int print_args,
+int apply_frame_filter (struct frame_info *frame,
+			int print_level,
+			enum print_what print_what,
+			int print_args,
 			struct ui_out *out);
 
 void preserve_python_values (struct objfile *objfile, htab_t copied_types);
diff --git a/gdb/stack.c b/gdb/stack.c
index bdd63f4..9ae4290 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -762,12 +762,17 @@ print_frame_info (struct frame_info *frame, int print_level,
   struct symtab_and_line sal;
   int source_print;
   int location_print;
-  int result;
   struct ui_out *uiout = current_uiout;
 
-  result = apply_frame_filter (frame, 1, LOCATION, 1, current_uiout);
-  if (result)
-    return;
+  /* If a previous frame elided this one, do not run the frame
+     filters.  */
+  if (! frame_print_elide (frame))
+    {
+      int result = apply_frame_filter (frame, 1, LOCATION, 1,
+				       current_uiout);
+      if (result)
+	return;
+    }
 
   if (get_frame_type (frame) == DUMMY_FRAME
       || get_frame_type (frame) == SIGTRAMP_FRAME
@@ -783,7 +788,7 @@ print_frame_info (struct frame_info *frame, int print_level,
          to list for this frame.  */
       if (print_level)
         {
-          ui_out_text (uiout, "#");
+	  ui_out_text (uiout, "#");
           ui_out_field_fmt_int (uiout, 2, ui_left, "level",
 				frame_relative_level (frame));
         }
@@ -1128,6 +1133,9 @@ print_frame (struct frame_info *frame, int print_level,
 
   list_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "frame");
 
+  if (frame_print_elide (frame))
+    ui_out_spaces (uiout, 4);
+
   if (print_level)
     {
       ui_out_text (uiout, "#");
diff --git a/gdb/testsuite/gdb.python/py-framefilter.c b/gdb/testsuite/gdb.python/py-framefilter.c
index 26f561f..6113716 100644
--- a/gdb/testsuite/gdb.python/py-framefilter.c
+++ b/gdb/testsuite/gdb.python/py-framefilter.c
@@ -37,7 +37,7 @@ void funca(void)
       count++;
       funcb(count);
     }
-  
+
   end_func();
   return;
 }
@@ -83,4 +83,3 @@ main()
 {
   func5(3);
 }
-
diff --git a/gdb/testsuite/gdb.python/py-framefilter.exp b/gdb/testsuite/gdb.python/py-framefilter.exp
index 73c1ba5..a3b1126 100644
--- a/gdb/testsuite/gdb.python/py-framefilter.exp
+++ b/gdb/testsuite/gdb.python/py-framefilter.exp
@@ -40,6 +40,6 @@ set remote_python_file [remote_download host ${srcdir}/${subdir}/${testfile}.py]
 gdb_test_no_output "python execfile ('${remote_python_file}')"
 gdb_test_no_output "python gdb.frame_filters.append(register_frame_filters)"
 gdb_breakpoint [gdb_get_line_number "Backtrace end breakpoint"]
-gdb_continue_to_breakpoint "Bactrace end breakpoint"
-gdb_test "bt" "#1.*in end_func.*#23.*in func1.*#27.*in main ().*"
+gdb_continue_to_breakpoint "Backtrace end breakpoint"
+gdb_test "bt" "#0.*in end_func.*#22.*in func1.*Composite frame func3.*#27.*in main ().*"
 remote_file host delete ${remote_python_file}
diff --git a/gdb/testsuite/gdb.python/py-framefilter.py b/gdb/testsuite/gdb.python/py-framefilter.py
index b7ee5c5..a3afe1a 100644
--- a/gdb/testsuite/gdb.python/py-framefilter.py
+++ b/gdb/testsuite/gdb.python/py-framefilter.py
@@ -16,8 +16,6 @@
 # This file is part of the GDB testsuite.  It tests Python-based
 # frame-filters.
 
-flevel = 0
-
 class Main_filter:
     "Example main () filter"
 
@@ -26,16 +24,34 @@ class Main_filter:
         self.what = what
         self.lvl = level
         self.args = args
-        
+
+    def omit (self):
+        fname = str (self.frame.function())
+        if fname == "func2":
+            return True
+        else:
+            return False
+
+    def elide (self):
+        fname = str (self.frame.function())
+        frame = self.frame
+
+        if fname == "func3":
+            frame = frame.older()
+            frame = frame.older()
+            frame = frame.older()
+
+        return frame
 
     def function (self):
-        return str (self.frame.function())
+        fname = str (self.frame.function())
+        if fname == "func3":
+            return "Composite frame " + str(self.frame.function())
+        else:
+            return str (self.frame.function())
 
-    def level (self):
-        global flevel
-        rlevel = flevel
-        flevel = flevel + 1
-        return rlevel
+    def level (self, level):
+        return level
 
     def address (self):
         return self.frame.pc()


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


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

only message in thread, other threads:[~2012-03-19 15:06 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-03-19 15:06 [SCM] archer-pmuldoon-python-backtrace: Implement omit and (bogus, non duck typed) elide function 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).