public inbox for archer-commits@sourceware.org
help / color / mirror / Atom feed
* [SCM]  archer-pmuldoon-python-breakpoints: Initial version of visible/invisible breakpoints from Python.  Only CLI. Revert vector to linked list changes.
@ 2010-09-28  9:27 pmuldoon
  0 siblings, 0 replies; only message in thread
From: pmuldoon @ 2010-09-28  9:27 UTC (permalink / raw)
  To: archer-commits

The branch, archer-pmuldoon-python-breakpoints has been updated
       via  1accd8f5f0c491b18bcb9e222a189e664dc00c9d (commit)
      from  a95e04ca2ca8fdeae594811689a97427f9297c7e (commit)

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

- Log -----------------------------------------------------------------
commit 1accd8f5f0c491b18bcb9e222a189e664dc00c9d
Author: Phil Muldoon <pmuldoon@redhat.com>
Date:   Tue Sep 28 10:25:56 2010 +0100

    Initial version of visible/invisible breakpoints from Python.  Only CLI.
    Revert vector to linked list changes.

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

Summary of changes:
 gdb/breakpoint.c                           |   21 +++--
 gdb/breakpoint.h                           |   14 ++--
 gdb/doc/gdb.texinfo                        |   15 +++-
 gdb/python/py-breakpoint.c                 |  141 +++++++++++++++-------------
 gdb/testsuite/gdb.python/py-breakpoint.exp |   24 +++++
 5 files changed, 134 insertions(+), 81 deletions(-)

First 500 lines of diff:
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index c980d93..26cab2c 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -4947,7 +4947,8 @@ breakpoint_1 (int bnum, int allflag, int (*filter) (const struct breakpoint *))
 	if (filter && !filter (b))
 	  continue;
 	
-	if (allflag || (user_settable_breakpoint (b)  && breakpoint_visible (b)))
+	if (allflag || (user_settable_breakpoint (b)
+			&& breakpoint_visible (b)))
 	  {
 	    int addr_bit, type_len;
 
@@ -5466,6 +5467,7 @@ set_raw_breakpoint_without_location (struct gdbarch *gdbarch,
   b->ops = NULL;
   b->condition_not_parsed = 0;
   b->visible = 1;
+
   /* Add this breakpoint to the end of the chain
      so that a list of breakpoints will come out in order
      of increasing numbers.  */
@@ -6923,7 +6925,7 @@ create_breakpoint_sal (struct gdbarch *gdbarch,
 		       char *cond_string,
 		       enum bptype type, enum bpdisp disposition,
 		       int thread, int task, int ignore_count,
-		       struct breakpoint_ops *ops, int from_tty, 
+		       struct breakpoint_ops *ops, int from_tty,
 		       int enabled, int visible)
 {
   struct breakpoint *b = NULL;
@@ -6972,6 +6974,7 @@ create_breakpoint_sal (struct gdbarch *gdbarch,
 	  b->disposition = disposition;
 	  b->pspace = sals.sals[0].pspace;
 	  b->visible = visible;
+
 	  if (type == bp_static_tracepoint)
 	    {
 	      struct static_tracepoint_marker marker;
@@ -7046,6 +7049,10 @@ Couldn't determine the static tracepoint marker to probe"));
   b->ops = ops;
   if (visible)
     mention (b);
+  else
+    /* Just notify observers without printing.  */
+    observer_notify_breakpoint_created (b->number);
+
 }
 
 /* Remove element at INDEX_TO_REMOVE from SAL, shifting other
@@ -7510,9 +7517,7 @@ create_new_breakpoint (struct gdbarch *gdbarch,
   int pending = 0;
   int not_found = 0;
   int task = 0;
-  int prev_bkpt_count = 0;
-  
-  prev_bkpt_count = breakpoint_count;
+  int prev_bkpt_count = breakpoint_count;
 
   sals.sals = NULL;
   sals.nelts = 0;
@@ -7705,7 +7710,6 @@ create_new_breakpoint (struct gdbarch *gdbarch,
       b = set_raw_breakpoint_without_location (gdbarch, type_wanted);
       set_breakpoint_count (breakpoint_count + 1);
       b->number = breakpoint_count;
-
       b->thread = -1;
       b->addr_string = addr_string[0];
       b->cond_string = NULL;
@@ -7724,6 +7728,9 @@ create_new_breakpoint (struct gdbarch *gdbarch,
 
       if (visible)
 	mention (b);
+      else
+	/* Just notify observers without printing.  */
+	observer_notify_breakpoint_created (b->number);
     }
   
   if (sals.nelts > 1)
@@ -7769,7 +7776,7 @@ create_breakpoint (struct gdbarch *gdbarch,
   return create_new_breakpoint (gdbarch, arg, cond_string, thread,
 				parse_condition_and_thread, tempflag,
 				type_wanted, ignore_count,
-				pending_break_support,			       
+				pending_break_support,
 				ops, from_tty, enabled, 1);
 }
 
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index 8315e76..3c3b5d0 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -878,13 +878,13 @@ extern int create_breakpoint (struct gdbarch *gdbarch, char *arg,
 			      int enabled);
 
 extern int create_new_breakpoint (struct gdbarch *gdbarch, char *arg,
-				  char *cond_string, int thread, 
-				  int parse_condition_and_thread, 
-				  int tempflag, 
-				  enum bptype type_wanted, 
-				  int ignore_count, 
-				  enum auto_boolean pending_break_support, 
-				  struct breakpoint_ops *ops,  
+				  char *cond_string, int thread,
+				  int parse_condition_and_thread,
+				  int tempflag,
+				  enum bptype type_wanted,
+				  int ignore_count,
+				  enum auto_boolean pending_break_support,
+				  struct breakpoint_ops *ops,
 				  int from_tty,
 				  int enabled,
 				  int visible);
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 07f9ad6..7791d0c 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -22520,7 +22520,7 @@ Return the symbol table's source absolute file name.
 Python code can manipulate breakpoints via the @code{gdb.Breakpoint}
 class.
 
-@defmethod Breakpoint __init__ spec @r{[}type@r{]} @r{[}wp_class@r{]}
+@defmethod Breakpoint __init__ spec @r{[}type@r{]} @r{[}wp_class@r{]} @r{[}visible@r{]}
 Create a new breakpoint.  @var{spec} is a string naming the
 location of the breakpoint, or an expression that defines a
 watchpoint.  The contents can be any location recognized by the
@@ -22528,7 +22528,12 @@ watchpoint.  The contents can be any location recognized by the
 command.  The optional @var{type} denotes the breakpoint to create
 from the types defined later in this chapter.  This argument can be
 either: @code{BP_BREAKPOINT} or @code{BP_WATCHPOINT}.  @var{type}
-defaults to @code{BP_BREAKPOINT}.  The optional @var{wp_class}
+defaults to @code{BP_BREAKPOINT}.  The optional @var{visible} argument
+allow the breakpoint to become invisible to the user.  The breakpoint
+will neither be reported when created, or will it be enumerated in the
+output from @samp{info breakpoints} (but will be enumerated with the
+@samp{maint info breakpoints} command).  The @var{visible} argument
+has no effect with watchpoints.  The optional @var{wp_class}
 argument defines the class of watchpoint to create, if @var{type} is
 defined as @code{BP_WATCHPOINT}.  If a watchpoint class is not
 provided, it is assumed to be a @var{WP_WRITE} class.
@@ -22606,6 +22611,12 @@ determine the actual breakpoint type or use-case.  This attribute is not
 writable.
 @end defivar
 
+@defivar Breakpoint visible
+This attribute holds the breakpoint's visibility flag --- the identifier used to
+determine whether the breakpoint is visible to the user when set, or
+when the @samp{info breakpoints} command is run.  This attribute is writable.
+@end defivar
+
 The available types are represented by constants defined in the @code{gdb}
 module:
 
diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c
index 2cbd751..e847092 100644
--- a/gdb/python/py-breakpoint.c
+++ b/gdb/python/py-breakpoint.c
@@ -34,6 +34,17 @@ typedef struct breakpoint_object breakpoint_object;
 
 static PyTypeObject breakpoint_object_type;
 
+/* A dynamically allocated vector of breakpoint objects.  Each
+   breakpoint has a number.  A breakpoint is valid if its slot in this
+   vector is non-null.  When a breakpoint is deleted, we drop our
+   reference to it and zero its slot; this is how we let the Python
+   object have a lifetime which is independent from that of the gdb
+   breakpoint.  */
+static breakpoint_object **bppy_breakpoints;
+
+/* Number of slots in bppy_breakpoints.  */
+static int bppy_slots;
+
 /* Number of live breakpoints.  */
 static int bppy_live;
 
@@ -51,12 +62,8 @@ struct breakpoint_object
   /* The gdb breakpoint object, or NULL if the breakpoint has been
      deleted.  */
   struct breakpoint *bp;
-  struct breakpoint_object *next;
 };
 
-struct breakpoint_object *top;
-struct breakpoint_object *bottom;
-
 /* Require that BREAKPOINT be a valid breakpoint ID; throw a Python
    exception if it is invalid.  */
 #define BPPY_REQUIRE_VALID(Breakpoint)					\
@@ -78,8 +85,6 @@ struct breakpoint_object *bottom;
 	}								\
     } while (0)
 
-#define ALL_PY_BREAKPOINTS(B)  for (B = top; B; B = B->next)
-
 /* This is used to initialize various gdb.bp_* constants.  */
 struct pybp_code
 {
@@ -114,10 +119,9 @@ static struct pybp_code pybp_watch_types[] =
 static int 
 bpnum_is_valid (int num)
 {
-  struct breakpoint *bp = NULL;
-
-  bp = get_breakpoint (num);
-  if (bp)
+  if (num >=0 
+      && num < bppy_slots 
+      && bppy_breakpoints[num] != NULL)
     return 1;
   
   return 0;
@@ -507,6 +511,29 @@ bppy_get_visibility (PyObject *self, void *closure)
   return PyInt_FromLong (self_bp->bp->visible);
 }
 
+/* Python function to set the 'silent' state of a breakpoint.  */
+static int
+bppy_set_visibility (PyObject *self, PyObject *newvalue, void *closure)
+{
+  breakpoint_object *self_bp = (breakpoint_object *) self;
+
+  BPPY_SET_REQUIRE_VALID (self_bp);
+
+  if (newvalue == NULL || ! PyBool_Check (newvalue))
+    {
+      PyErr_SetString (PyExc_TypeError,
+		       _("Value must be True or False."));
+      return -1;
+    }
+
+  if (newvalue == Py_True)
+    self_bp->bp->visible = 1;
+  else
+    self_bp->bp->visible = 0;
+
+  return 0;
+}
+
 /* Python function to get the breakpoint's number.  */
 static PyObject *
 bppy_get_number (PyObject *self, void *closure)
@@ -590,9 +617,7 @@ bppy_new (PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
   bppy_pending_object = (breakpoint_object *) result;
   bppy_pending_object->number = -1;
   bppy_pending_object->bp = NULL;
-  /* We don't add the breakpoint to the linked-list yet as the GDB
-     breakpoint has not yet been created.  */
-  bppy_pending_object->next = NULL;
+  
   TRY_CATCH (except, RETURN_MASK_ALL)
     {
       switch (type)
@@ -644,7 +669,6 @@ PyObject *
 gdbpy_breakpoints (PyObject *self, PyObject *args)
 {
   PyObject *result;
-  breakpoint_object *b;
 
   if (bppy_live == 0)
     Py_RETURN_NONE;
@@ -652,13 +676,16 @@ gdbpy_breakpoints (PyObject *self, PyObject *args)
   result = PyTuple_New (bppy_live);
   if (result)
     {
-      int out = 0;
-      ALL_PY_BREAKPOINTS (b)
-      {
-	Py_INCREF (b);
-	PyTuple_SetItem (result, out, (PyObject *) b);
-	++out;
-      }
+      int i, out = 0;
+
+      for (i = 0; out < bppy_live; ++i)
+	{
+	  if (! bppy_breakpoints[i])
+	    continue;
+	  Py_INCREF (bppy_breakpoints[i]);
+	  PyTuple_SetItem (result, out, (PyObject *) bppy_breakpoints[i]);
+	  ++out;
+	}
     }
   return result;
 }
@@ -676,6 +703,9 @@ gdbpy_breakpoint_created (int num)
   struct breakpoint *bp = NULL;
   PyGILState_STATE state;
 
+  if (num < 0)
+    return;
+
   bp = get_breakpoint (num);
   if (! bp)
     return;
@@ -687,6 +717,21 @@ gdbpy_breakpoint_created (int num)
       && bp->type != bp_access_watchpoint)
     return;
 
+  if (num >= bppy_slots)
+    {
+      int old = bppy_slots;
+
+      bppy_slots = bppy_slots * 2 + 10;
+      bppy_breakpoints
+	= (breakpoint_object **) xrealloc (bppy_breakpoints,
+					   (bppy_slots
+					    * sizeof (breakpoint_object *)));
+      memset (&bppy_breakpoints[old], 0,
+	      (bppy_slots - old) * sizeof (PyObject *));
+    }
+
+  ++bppy_live;
+
   state = PyGILState_Ensure ();
 
   if (bppy_pending_object)
@@ -700,29 +745,10 @@ gdbpy_breakpoint_created (int num)
     {
       newbp->number = num;
       newbp->bp = bp;
-      newbp->next = NULL;
+      bppy_breakpoints[num] = newbp;
       Py_INCREF (newbp);
     }
-  else
-    {
-      PyErr_SetString (PyExc_RuntimeError, 
-		       _("Error while creating breakpoint from GDB."));
-      return;
-    }
-
-  ++bppy_live;
-
-  /* If this is the first breakpoint created, set the top and bottom
-     of the linked list. */
-  if (top == NULL)
-    top = newbp;
-
-  if (bottom)
-      bottom->next = newbp;
 
-  bottom = newbp;
-  
-  
   /* Just ignore errors here.  */
   PyErr_Clear ();
 
@@ -735,28 +761,15 @@ static void
 gdbpy_breakpoint_deleted (int num)
 {
   PyGILState_STATE state;
-  breakpoint_object *b = NULL;
-  breakpoint_object *prev = NULL;
 
   state = PyGILState_Ensure ();
-  ALL_PY_BREAKPOINTS (b)
-  {
-    if (b->number == num)
-      {
-	if (b == top)
-	  top = b->next;
-	else
-	  prev->next = b->next;
-	if (b == bottom)
-	  bottom = prev;
-	
-	b->bp = NULL;
-	Py_DECREF (b);
-	--bppy_live;
-	break;
-      }
-    prev = b;
-  }
+  if (bpnum_is_valid (num))
+    {
+      bppy_breakpoints[num]->bp = NULL;
+      Py_DECREF (bppy_breakpoints[num]);
+      bppy_breakpoints[num] = NULL;
+      --bppy_live;
+    }
   PyGILState_Release (state);
 }
 
@@ -776,9 +789,6 @@ gdbpy_initialize_breakpoints (void)
   PyModule_AddObject (gdb_module, "Breakpoint",
 		      (PyObject *) &breakpoint_object_type);
 
-  top = NULL;
-  bottom = NULL;
-
   observer_attach_breakpoint_created (gdbpy_breakpoint_created);
   observer_attach_breakpoint_deleted (gdbpy_breakpoint_deleted);
 
@@ -801,6 +811,7 @@ gdbpy_initialize_breakpoints (void)
 				   pybp_watch_types[i].code) < 0)
 	return;
     }
+
 }
 
 \f
@@ -840,7 +851,7 @@ or None if no condition set."},
     "Commands of the breakpoint, as specified by the user."},
   { "type", bppy_get_type, NULL,
     "Type of breakpoint."},
-  { "visible", bppy_get_visibility, NULL,
+  { "visible", bppy_get_visibility, bppy_set_visibility,
     "Whether the breakpoint is visible to the user."},
 
   { NULL }  /* Sentinel.  */
diff --git a/gdb/testsuite/gdb.python/py-breakpoint.exp b/gdb/testsuite/gdb.python/py-breakpoint.exp
index 07a7362..dc78a92 100644
--- a/gdb/testsuite/gdb.python/py-breakpoint.exp
+++ b/gdb/testsuite/gdb.python/py-breakpoint.exp
@@ -126,6 +126,30 @@ gdb_test "end"
 gdb_py_test_silent_cmd "python blist = gdb.breakpoints()" "Get Breakpoint List" 0
 gdb_test "python print blist\[len(blist)-1\].commands" "print \"Command for breakpoint has been executed.\".*print result"
 
+# Start with a fresh gdb.
+clean_restart ${testfile}
+
+if ![runto_main] then {
+    fail "Cannot run to main."
+    return 0
+}
+
+# Test invisible breakpooints.
+delete_breakpoints
+set ibp_location [gdb_get_line_number "Break at multiply."]
+gdb_py_test_silent_cmd  "python ibp = gdb.Breakpoint(\"$ibp_location\", visible=False)" "Set invisible breakpoint" 0
+gdb_py_test_silent_cmd "python ilist = gdb.breakpoints()" "Get Breakpoint List" 0
+gdb_test "python print ilist\[0\]" "<gdb.Breakpoint object at $hex>" "Check invisible bp obj exists"
+gdb_test "python print ilist\[0\].location" "py-breakpoint\.c:$ibp_location*" "Check breakpoint location"
+gdb_test "python print ilist\[0\].visible" "0" "Check breakpoint visibility"
+gdb_test "python print ilist\[0\].number == gdb.parse_and_eval(\"\$bpnum\")" "True" "Check that bpnum has been updated"
+gdb_test "info breakpoints" "No breakpoints or watchpoints.*" "Check info breakpoints does not show invisible breakpoints"
+gdb_test "maint info breakpoints" "py-breakpoint\.c:$ibp_location.*" "Check maint info breakpoints shows invisible breakpoints"
+gdb_py_test_silent_cmd "python ilist\[0\].visible = True" "Set visibility to True" 0
+gdb_test "info breakpoints" "py-breakpoint\.c:$ibp_location.*" "Check info breakpoints shows visible breakpoints"
+gdb_py_test_silent_cmd "python ilist\[0\].visible = False" "Set visibility to True" 0
+gdb_test "info breakpoints" "No breakpoints or watchpoints.*" "Check info breakpoints does not show invisible breakpoints"
+
 # Watchpoints
 # Start with a fresh gdb.
 clean_restart ${testfile}


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


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

only message in thread, other threads:[~2010-09-28  9:27 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-09-28  9:27 [SCM] archer-pmuldoon-python-breakpoints: Initial version of visible/invisible breakpoints from Python. Only CLI. Revert vector to linked list changes 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).