2010-11-11 Phil Muldoon <pmuldoon@redhat.com>
authorPhil Muldoon <pmuldoon@redhat.com>
Thu, 11 Nov 2010 14:11:56 +0000 (14:11 +0000)
committerPhil Muldoon <pmuldoon@redhat.com>
Thu, 11 Nov 2010 14:11:56 +0000 (14:11 +0000)
* python/py-breakpoint.c (BPPY_REQUIRE_VALID): Check if bp is
NULL.
(BPPY_SET_REQUIRE_VALID): Ditto.
(bpnum_is_valid): Delete function.
(bppy_get_visibility): New function.
(bppy_new): Parse for, and validate internal keyword.  Pass
internal keyword to breakpoint or watchpoint functions.
(build_bp_list): New function.
(gdbpy_breakpoints): Rewrite.  Use build_bp_list and
iterate_over_breakpoints.
(gdbpy_breakpoint_created): Rewrite.  Do not store breakpoints in a
look-aside vector.
(gdbpy_breakpoint_deleted): Rewrite, defer breakpoint management
to internal breakpoint chain.

* breakpoint.c (set_breakpoint_number): New function.
(breakpoint_1): Check if breakpoint number is more than zero.
(set_raw_breakpoint_without_location): Set py_bp_object to NULL.
(create_breakpoint_sal): Take a new parameter called internal.
Call set_breakpoint_number with internal parameter.  Do not
mention internal breakpoints.  All callers updated.
(create_breakpoint): Ditto.
(create_breakpoints_sal): Ditto.
(watch_command_1): Ditto.
(watch_command_wrapper): Take a new parameter called internal.
All callers updated.
(rwatch_command_wrapper): Ditto.
(awatch_command_wrapper): Ditto.
(save_breakpoints): Update breakpoint save condition check.
(iterate_over_breakpoints): New function.
* breakpoint.h: Add conditional python includes.  Add py_bp_object
and comment to struct breakpoint.  Update all callers.
* defs.h: Add PyObject definition for GDB builds without Python.

2010-11-11  Phil Muldoon  <pmuldoon@redhat.com>

* gdb.texinfo (Breakpoints In Python): Document "internal"
parameter, and visible attribute.

2010-11-11  Phil Muldoon  <pmuldoon@redhat.com>

* gdb.python/py-breakpoint.exp: Add internal watchpoint and
breakpoint tests.

12 files changed:
gdb/ChangeLog
gdb/breakpoint.c
gdb/breakpoint.h
gdb/defs.h
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/mi/mi-cmd-break.c
gdb/python/py-breakpoint.c
gdb/spu-tdep.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.python/py-breakpoint.exp
gdb/varobj.c

index 8c8a5bd..2c413a3 100644 (file)
@@ -1,3 +1,39 @@
+2010-11-11  Phil Muldoon  <pmuldoon@redhat.com>
+
+       * python/py-breakpoint.c (BPPY_REQUIRE_VALID): Check if bp is
+       NULL.
+       (BPPY_SET_REQUIRE_VALID): Ditto.
+       (bpnum_is_valid): Delete function.
+       (bppy_get_visibility): New function.
+       (bppy_new): Parse for, and validate internal keyword.  Pass
+       internal keyword to breakpoint or watchpoint functions.
+       (build_bp_list): New function.
+       (gdbpy_breakpoints): Rewrite.  Use build_bp_list and
+       iterate_over_breakpoints.
+       (gdbpy_breakpoint_created): Rewrite.  Do not store breakpoints in a
+       look-aside vector.
+       (gdbpy_breakpoint_deleted): Rewrite, defer breakpoint management
+       to internal breakpoint chain.
+
+       * breakpoint.c (set_breakpoint_number): New function.
+       (breakpoint_1): Check if breakpoint number is more than zero.
+       (set_raw_breakpoint_without_location): Set py_bp_object to NULL.
+       (create_breakpoint_sal): Take a new parameter called internal.
+       Call set_breakpoint_number with internal parameter.  Do not
+       mention internal breakpoints.  All callers updated.
+       (create_breakpoint): Ditto.
+       (create_breakpoints_sal): Ditto.
+       (watch_command_1): Ditto.
+       (watch_command_wrapper): Take a new parameter called internal.
+       All callers updated.
+       (rwatch_command_wrapper): Ditto.
+       (awatch_command_wrapper): Ditto.
+       (save_breakpoints): Update breakpoint save condition check.
+       (iterate_over_breakpoints): New function.
+       * breakpoint.h: Add conditional python includes.  Add py_bp_object
+       and comment to struct breakpoint.  Update all callers.
+       * defs.h: Add PyObject definition for GDB builds without Python.
+
 2010-11-10  Doug Evans  <dje@google.com>
 
        * python/lib/gdb/command/pretty_printers.py
index ffa8c52..6b55313 100644 (file)
@@ -2068,6 +2068,24 @@ reattach_breakpoints (int pid)
 
 static int internal_breakpoint_number = -1;
 
+/* Set the breakpoint number of B, depending on the value of INTERNAL.
+   If INTERNAL is non-zero, the breakpoint number will be populated
+   from internal_breakpoint_number and that variable decremented.
+   Otherwis the breakpoint number will be populated from
+   breakpoint_count and that value incremented.  Internal breakpoints
+   do not set the internal var bpnum.  */
+static void
+set_breakpoint_number (int internal, struct breakpoint *b)
+{
+  if (internal)
+    b->number = internal_breakpoint_number--;
+  else
+    {
+      set_breakpoint_count (breakpoint_count + 1);
+      b->number = breakpoint_count;
+    }
+}
+
 static struct breakpoint *
 create_internal_breakpoint (struct gdbarch *gdbarch,
                            CORE_ADDR address, enum bptype type)
@@ -4939,7 +4957,8 @@ breakpoint_1 (int bnum, int allflag, int (*filter) (const struct breakpoint *))
        if (filter && !filter (b))
          continue;
        
-       if (allflag || user_settable_breakpoint (b))
+       if (allflag || (user_settable_breakpoint (b)
+                       && b->number > 0))
          {
            int addr_bit, type_len;
 
@@ -5007,7 +5026,8 @@ breakpoint_1 (int bnum, int allflag, int (*filter) (const struct breakpoint *))
        
        /* We only print out user settable breakpoints unless the
           allflag is set. */
-       if (allflag || user_settable_breakpoint (b))
+       if (allflag || (user_settable_breakpoint (b)
+                       && b->number > 0))
          print_one_breakpoint (b, &last_loc, print_address_bits, allflag);
       }
   }
@@ -5456,6 +5476,7 @@ set_raw_breakpoint_without_location (struct gdbarch *gdbarch,
   b->syscalls_to_be_caught = NULL;
   b->ops = NULL;
   b->condition_not_parsed = 0;
+  b->py_bp_object = NULL;
 
   /* Add this breakpoint to the end of the chain
      so that a list of breakpoints will come out in order
@@ -6914,7 +6935,8 @@ 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, int enabled)
+                      struct breakpoint_ops *ops, int from_tty,
+                      int enabled, int internal)
 {
   struct breakpoint *b = NULL;
   int i;
@@ -6951,8 +6973,7 @@ create_breakpoint_sal (struct gdbarch *gdbarch,
       if (i == 0)
        {
          b = set_raw_breakpoint (gdbarch, sal, type);
-         set_breakpoint_count (breakpoint_count + 1);
-         b->number = breakpoint_count;
+         set_breakpoint_number (internal, b);
          b->thread = thread;
          b->task = task;
   
@@ -7034,7 +7055,12 @@ Couldn't determine the static tracepoint marker to probe"));
       = xstrprintf ("*%s", paddress (b->loc->gdbarch, b->loc->address));
 
   b->ops = ops;
-  mention (b);
+  if (internal)
+    /* Do not mention breakpoints with a negative number, but do
+       notify observers.  */
+    observer_notify_breakpoint_created (b->number);
+  else
+    mention (b);
 }
 
 /* Remove element at INDEX_TO_REMOVE from SAL, shifting other
@@ -7190,7 +7216,7 @@ create_breakpoints_sal (struct gdbarch *gdbarch,
                        enum bptype type, enum bpdisp disposition,
                        int thread, int task, int ignore_count,
                        struct breakpoint_ops *ops, int from_tty,
-                       int enabled)
+                       int enabled, int internal)
 {
   int i;
 
@@ -7201,7 +7227,8 @@ create_breakpoints_sal (struct gdbarch *gdbarch,
 
       create_breakpoint_sal (gdbarch, expanded, addr_string[i],
                             cond_string, type, disposition,
-                            thread, task, ignore_count, ops, from_tty, enabled);
+                            thread, task, ignore_count, ops,
+                            from_tty, enabled, internal);
     }
 }
 
@@ -7470,8 +7497,10 @@ decode_static_tracepoint_spec (char **arg_p)
    parameter.  If non-zero, the function will parse arg, extracting
    breakpoint location, address and thread. Otherwise, ARG is just the
    location of breakpoint, with condition and thread specified by the
-   COND_STRING and THREAD parameters.  Returns true if any breakpoint
-   was created; false otherwise.  */
+   COND_STRING and THREAD parameters.  If INTERNAL is non-zero, the
+   breakpoint number will be allocated from the internal breakpoint
+   count.  Returns true if any breakpoint was created; false
+   otherwise.  */
 
 int
 create_breakpoint (struct gdbarch *gdbarch,
@@ -7481,8 +7510,7 @@ create_breakpoint (struct gdbarch *gdbarch,
                   int ignore_count,
                   enum auto_boolean pending_break_support,
                   struct breakpoint_ops *ops,
-                  int from_tty,
-                  int enabled)
+                  int from_tty, int enabled, int internal)
 {
   struct gdb_exception e;
   struct symtabs_and_lines sals;
@@ -7658,12 +7686,15 @@ create_breakpoint (struct gdbarch *gdbarch,
                                     cond_string, type_wanted,
                                     tempflag ? disp_del : disp_donttouch,
                                     thread, task, ignore_count, ops,
-                                    from_tty, enabled);
+                                    from_tty, enabled, internal);
 
              do_cleanups (old_chain);
 
              /* Get the tracepoint we just created.  */
-             tp = get_breakpoint (breakpoint_count);
+             if (internal)
+               tp = get_breakpoint (internal_breakpoint_number);
+             else
+               tp = get_breakpoint (breakpoint_count);
              gdb_assert (tp != NULL);
 
              /* Given that its possible to have multiple markers with
@@ -7679,7 +7710,7 @@ create_breakpoint (struct gdbarch *gdbarch,
        create_breakpoints_sal (gdbarch, sals, addr_string, cond_string,
                                type_wanted, tempflag ? disp_del : disp_donttouch,
                                thread, task, ignore_count, ops, from_tty,
-                               enabled);
+                               enabled, internal);
     }
   else
     {
@@ -7688,8 +7719,7 @@ create_breakpoint (struct gdbarch *gdbarch,
       make_cleanup (xfree, copy_arg);
 
       b = set_raw_breakpoint_without_location (gdbarch, type_wanted);
-      set_breakpoint_count (breakpoint_count + 1);
-      b->number = breakpoint_count;
+      set_breakpoint_number (internal, b);
       b->thread = -1;
       b->addr_string = addr_string[0];
       b->cond_string = NULL;
@@ -7699,13 +7729,19 @@ create_breakpoint (struct gdbarch *gdbarch,
       b->ops = ops;
       b->enable_state = enabled ? bp_enabled : bp_disabled;
       b->pspace = current_program_space;
+      b->py_bp_object = NULL;
 
       if (enabled && b->pspace->executing_startup
          && (b->type == bp_breakpoint
              || b->type == bp_hardware_breakpoint))
        b->enable_state = bp_startup_disabled;
 
-      mention (b);
+      if (internal)
+        /* Do not mention breakpoints with a negative number, 
+          but do notify observers.  */
+        observer_notify_breakpoint_created (b->number);
+      else
+        mention (b);
     }
   
   if (sals.nelts > 1)
@@ -7750,7 +7786,8 @@ break_command_1 (char *arg, int flag, int from_tty)
                     pending_break_support,
                     NULL /* breakpoint_ops */,
                     from_tty,
-                    1 /* enabled */);
+                    1 /* enabled */,
+                    0 /* internal */);
 }
 
 
@@ -8017,7 +8054,8 @@ watchpoint_exp_is_const (const struct expression *exp)
                 hw_read:   watch read, 
                hw_access: watch access (read or write) */
 static void
-watch_command_1 (char *arg, int accessflag, int from_tty, int just_location)
+watch_command_1 (char *arg, int accessflag, int from_tty,
+                int just_location, int internal)
 {
   struct breakpoint *b, *scope_breakpoint = NULL;
   struct expression *exp;
@@ -8225,8 +8263,7 @@ watch_command_1 (char *arg, int accessflag, int from_tty, int just_location)
 
   /* Now set up the breakpoint.  */
   b = set_raw_breakpoint_without_location (NULL, bp_type);
-  set_breakpoint_count (breakpoint_count + 1);
-  b->number = breakpoint_count;
+  set_breakpoint_number (internal, b);
   b->thread = thread;
   b->disposition = disp_donttouch;
   b->exp = exp;
@@ -8285,8 +8322,12 @@ watch_command_1 (char *arg, int accessflag, int from_tty, int just_location)
   /* Finally update the new watchpoint.  This creates the locations
      that should be inserted.  */
   update_watchpoint (b, 1);
-
-  mention (b);
+  if (internal)
+    /* Do not mention breakpoints with a negative number, but do
+       notify observers.  */
+    observer_notify_breakpoint_created (b->number);
+  else
+    mention (b);
   update_global_location_list (1);
 }
 
@@ -8370,9 +8411,9 @@ can_use_hardware_watchpoint (struct value *v)
 }
 
 void
-watch_command_wrapper (char *arg, int from_tty)
+watch_command_wrapper (char *arg, int from_tty, int internal)
 {
-  watch_command_1 (arg, hw_write, from_tty, 0);
+  watch_command_1 (arg, hw_write, from_tty, 0, internal);
 }
 
 /* A helper function that looks for an argument at the start of a
@@ -8408,7 +8449,7 @@ watch_maybe_just_location (char *arg, int accessflag, int from_tty)
       just_location = 1;
     }
 
-  watch_command_1 (arg, accessflag, from_tty, just_location);
+  watch_command_1 (arg, accessflag, from_tty, just_location, 0);
 }
 
 static void
@@ -8418,9 +8459,9 @@ watch_command (char *arg, int from_tty)
 }
 
 void
-rwatch_command_wrapper (char *arg, int from_tty)
+rwatch_command_wrapper (char *arg, int from_tty, int internal)
 {
-  watch_command_1 (arg, hw_read, from_tty, 0);
+  watch_command_1 (arg, hw_read, from_tty, 0, internal);
 }
 
 static void
@@ -8430,9 +8471,9 @@ rwatch_command (char *arg, int from_tty)
 }
 
 void
-awatch_command_wrapper (char *arg, int from_tty)
+awatch_command_wrapper (char *arg, int from_tty, int internal)
 {
-  watch_command_1 (arg, hw_access, from_tty, 0);
+  watch_command_1 (arg, hw_access, from_tty, 0, internal);
 }
 
 static void
@@ -8790,7 +8831,8 @@ handle_gnu_v3_exceptions (int tempflag, char *cond_string,
                     0,
                     AUTO_BOOLEAN_TRUE /* pending */,
                     &gnu_v3_exception_catchpoint_ops, from_tty,
-                    1 /* enabled */);
+                    1 /* enabled */,
+                    0 /* internal */);
 
   return 1;
 }
@@ -11010,7 +11052,8 @@ trace_command (char *arg, int from_tty)
                         pending_break_support,
                         NULL,
                         from_tty,
-                        1 /* enabled */))
+                        1 /* enabled */,
+                        0 /* internal */))
     set_tracepoint_count (breakpoint_count);
 }
 
@@ -11026,7 +11069,8 @@ ftrace_command (char *arg, int from_tty)
                         pending_break_support,
                         NULL,
                         from_tty,
-                        1 /* enabled */))
+                        1 /* enabled */,
+                        0 /* internal */))
     set_tracepoint_count (breakpoint_count);
 }
 
@@ -11044,7 +11088,8 @@ strace_command (char *arg, int from_tty)
                         pending_break_support,
                         NULL,
                         from_tty,
-                        1 /* enabled */))
+                        1 /* enabled */,
+                        0 /* internal */))
     set_tracepoint_count (breakpoint_count);
 }
 
@@ -11106,7 +11151,8 @@ create_tracepoint_from_upload (struct uploaded_tp *utp)
                          pending_break_support,
                          NULL,
                          0 /* from_tty */,
-                         utp->enabled /* enabled */))
+                         utp->enabled /* enabled */,
+                         0 /* internal */))
     return NULL;
 
   set_tracepoint_count (breakpoint_count);
@@ -11372,7 +11418,7 @@ save_breakpoints (char *filename, int from_tty,
   ALL_BREAKPOINTS (tp)
   {
     /* Skip internal and momentary breakpoints.  */
-    if (!user_settable_breakpoint (tp))
+    if (!user_settable_breakpoint (tp) || tp->number < 0)
       continue;
 
     /* If we have a filter, only save the breakpoints it accepts.  */
@@ -11410,7 +11456,7 @@ save_breakpoints (char *filename, int from_tty,
   ALL_BREAKPOINTS (tp)
   {
     /* Skip internal and momentary breakpoints.  */
-    if (!user_settable_breakpoint (tp))
+    if (!user_settable_breakpoint (tp) || tp->number < 0)
       continue;
 
     /* If we have a filter, only save the breakpoints it accepts.  */
@@ -11627,6 +11673,21 @@ save_command (char *arg, int from_tty)
   help_list (save_cmdlist, "save ", -1, gdb_stdout);
 }
 
+struct breakpoint *
+iterate_over_breakpoints (int (*callback) (struct breakpoint *, void *),
+                         void *data)
+{
+  struct breakpoint *b, *temp;
+
+  ALL_BREAKPOINTS_SAFE (b, temp)
+    {
+      if ((*callback) (b, data))
+       return b;
+    }
+
+  return NULL;
+}
+
 void
 _initialize_breakpoint (void)
 {
index 9f7600a..e34c2d3 100644 (file)
 #include "value.h"
 #include "vec.h"
 
+#if HAVE_PYTHON
+#include "python/python.h"
+#include "python/python-internal.h"
+#endif
+
 struct value;
 struct block;
 
@@ -557,7 +562,14 @@ struct breakpoint
        breakpoints, we will use this index to try to find the same
        marker again.  */
     int static_trace_marker_id_idx;
-  };
+
+    /* With a Python scripting enabled GDB, store a reference to the
+       Python object that has been associated with this breakpoint.
+       This is always NULL for a GDB that is not script enabled.  It
+       can sometimes be NULL for enabled GDBs as not all breakpoint
+       types are tracked by the Python scripting API.  */
+    PyObject *py_bp_object;
+};
 
 typedef struct breakpoint *breakpoint_p;
 DEF_VEC_P(breakpoint_p);
@@ -855,9 +867,9 @@ extern void break_command (char *, int);
 extern void hbreak_command_wrapper (char *, int);
 extern void thbreak_command_wrapper (char *, int);
 extern void rbreak_command_wrapper (char *, int);
-extern void watch_command_wrapper (char *, int);
-extern void awatch_command_wrapper (char *, int);
-extern void rwatch_command_wrapper (char *, int);
+extern void watch_command_wrapper (char *, int, int);
+extern void awatch_command_wrapper (char *, int, int);
+extern void rwatch_command_wrapper (char *, int, int);
 extern void tbreak_command (char *, int);
 
 extern int create_breakpoint (struct gdbarch *gdbarch, char *arg,
@@ -868,7 +880,8 @@ extern int create_breakpoint (struct gdbarch *gdbarch, char *arg,
                              enum auto_boolean pending_break_support,
                              struct breakpoint_ops *ops,
                              int from_tty,
-                             int enabled);
+                             int enabled,
+                             int internal);
 
 extern void insert_breakpoints (void);
 
@@ -1101,4 +1114,15 @@ extern void check_tracepoint_command (char *line, void *closure);
 extern void start_rbreak_breakpoints (void);
 extern void end_rbreak_breakpoints (void);
 
+/* Breakpoint iterator function.
+
+   Calls a callback function once for each breakpoint, so long as the
+   callback function returns false.  If the callback function returns
+   true, the iteration will end and the current breakpoint will be
+   returned.  This can be useful for implementing a search for a
+   breakpoint with arbitrary attributes, or for applying an operation
+   to every breakpoint.  */
+extern struct breakpoint *iterate_over_breakpoints (int (*) (struct breakpoint *,
+                                                            void *), void *);
+
 #endif /* !defined (BREAKPOINT_H) */
index 489de74..d36f7c1 100644 (file)
@@ -1240,4 +1240,8 @@ void dummy_obstack_deallocate (void *object, void *data);
 extern void initialize_progspace (void);
 extern void initialize_inferiors (void);
 
+#ifndef HAVE_PYTHON
+typedef int PyObject;
+#endif
+
 #endif /* #ifndef DEFS_H */
index 7e006ce..d999772 100644 (file)
@@ -1,3 +1,8 @@
+2010-11-11  Phil Muldoon  <pmuldoon@redhat.com>
+
+       * gdb.texinfo (Breakpoints In Python): Document "internal"
+       parameter, and visible attribute.
+
 2010-11-05  Doug Evans  <dje@google.com>
 
        * gdb.texinfo (Source Path): Document "set directories".
index 257ff19..cf70ce4 100644 (file)
@@ -22823,7 +22823,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{[}internal@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
@@ -22831,10 +22831,14 @@ 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{internal} argument
+allows the breakpoint to become invisible to the user.  The breakpoint
+will neither be reported when created, nor will it be listed in the
+output from @code{info breakpoints} (but will be listed with the
+@code{maint info breakpoints} command).  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.
+@code{BP_WATCHPOINT}.  If a watchpoint class is not provided, it is
+assumed to be a @var{WP_WRITE} class.
 @end defmethod
 
 The available watchpoint types represented by constants are defined in the
@@ -22909,6 +22913,12 @@ determine the actual breakpoint type or use-case.  This attribute is not
 writable.
 @end defivar
 
+@defivar Breakpoint visible
+This attribute tells whether the breakpoint is visible to the user
+when set, or when the @samp{info breakpoints} command is run.  This
+attribute is not writable.
+@end defivar
+
 The available types are represented by constants defined in the @code{gdb}
 module:
 
index 3408244..2aad420 100644 (file)
@@ -169,7 +169,7 @@ mi_cmd_break_insert (char *command, char **argv, int argc)
                     temp_p, type_wanted,
                     ignore_count,
                     pending ? AUTO_BOOLEAN_TRUE : AUTO_BOOLEAN_FALSE,
-                    NULL, 0, enabled);
+                    NULL, 0, enabled, 0);
   do_cleanups (back_to);
 
 }
@@ -259,13 +259,13 @@ mi_cmd_break_watch (char *command, char **argv, int argc)
   switch (type)
     {
     case REG_WP:
-      watch_command_wrapper (expr, FROM_TTY);
+      watch_command_wrapper (expr, FROM_TTY, 0);
       break;
     case READ_WP:
-      rwatch_command_wrapper (expr, FROM_TTY);
+      rwatch_command_wrapper (expr, FROM_TTY, 0);
       break;
     case ACCESS_WP:
-      awatch_command_wrapper (expr, FROM_TTY);
+      awatch_command_wrapper (expr, FROM_TTY, 0);
       break;
     default:
       error (_("mi_cmd_break_watch: Unknown watchpoint type."));
index b18f7f3..8afa414 100644 (file)
@@ -34,17 +34,6 @@ 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;
 
@@ -68,7 +57,7 @@ struct breakpoint_object
    exception if it is invalid.  */
 #define BPPY_REQUIRE_VALID(Breakpoint)                                 \
     do {                                                               \
-      if (! bpnum_is_valid ((Breakpoint)->number))                     \
+      if ((Breakpoint)->bp == NULL)                                    \
        return PyErr_Format (PyExc_RuntimeError, _("Breakpoint %d is invalid."), \
                             (Breakpoint)->number);                     \
     } while (0)
@@ -77,7 +66,7 @@ struct breakpoint_object
    exception if it is invalid.  This macro is for use in setter functions.  */
 #define BPPY_SET_REQUIRE_VALID(Breakpoint)                             \
     do {                                                               \
-      if (! bpnum_is_valid ((Breakpoint)->number))                     \
+      if ((Breakpoint)->bp == NULL)                                            \
         {                                                              \
          PyErr_Format (PyExc_RuntimeError, _("Breakpoint %d is invalid."), \
                        (Breakpoint)->number);                          \
@@ -115,18 +104,6 @@ static struct pybp_code pybp_watch_types[] =
   {NULL} /* Sentinel.  */
 };
 
-/* Evaluate to true if the breakpoint NUM is valid, false otherwise.  */
-static int 
-bpnum_is_valid (int num)
-{
-  if (num >=0 
-      && num < bppy_slots 
-      && bppy_breakpoints[num] != NULL)
-    return 1;
-  
-  return 0;
-}
-
 /* Python function which checks the validity of a breakpoint object.  */
 static PyObject *
 bppy_is_valid (PyObject *self, PyObject *args)
@@ -503,6 +480,21 @@ bppy_get_type (PyObject *self, void *closure)
   return PyInt_FromLong (self_bp->bp->type);
 }
 
+/* Python function to get the visibility of the breakpoint.  */
+
+static PyObject *
+bppy_get_visibility (PyObject *self, void *closure)
+{
+  breakpoint_object *self_bp = (breakpoint_object *) self;
+
+  BPPY_REQUIRE_VALID (self_bp);
+
+  if (self_bp->bp->number < 0)
+    Py_RETURN_FALSE;
+
+  Py_RETURN_TRUE;
+}
+
 /* Python function to get the breakpoint's number.  */
 static PyObject *
 bppy_get_number (PyObject *self, void *closure)
@@ -569,16 +561,25 @@ static PyObject *
 bppy_new (PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
 {
   PyObject *result;
-  static char *keywords[] = { "spec", "type", "wp_class", NULL };
+  static char *keywords[] = { "spec", "type", "wp_class", "internal", NULL };
   char *spec;
   int type = bp_breakpoint;
   int access_type = hw_write;
+  PyObject *internal = NULL;
+  int internal_bp = 0;
   volatile struct gdb_exception except;
 
-  if (! PyArg_ParseTupleAndKeywords (args, kwargs, "s|ii", keywords,
-                                    &spec, &type, &access_type))
+  if (! PyArg_ParseTupleAndKeywords (args, kwargs, "s|iiO", keywords,
+                                    &spec, &type, &access_type, &internal))
     return NULL;
 
+  if (internal)
+    {
+      internal_bp = PyObject_IsTrue (internal);
+      if (internal_bp == -1)
+       return NULL;
+    }
+
   result = subtype->tp_alloc (subtype, 0);
   if (! result)
     return NULL;
@@ -598,17 +599,17 @@ bppy_new (PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
                               0, bp_breakpoint,
                               0,
                               AUTO_BOOLEAN_TRUE,
-                              NULL, 0, 1);
+                              NULL, 0, 1, internal_bp);
            break;
          }
         case bp_watchpoint:
          {
            if (access_type == hw_write)
-             watch_command_wrapper (spec, 0);
+             watch_command_wrapper (spec, 0, internal_bp);
            else if (access_type == hw_access)
-             awatch_command_wrapper (spec, 0);
+             awatch_command_wrapper (spec, 0, internal_bp);
            else if (access_type == hw_read)
-             rwatch_command_wrapper (spec, 0);
+             rwatch_command_wrapper (spec, 0, internal_bp);
            else
              error(_("Cannot understand watchpoint access type."));
            break;
@@ -631,31 +632,50 @@ bppy_new (PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
 
 \f
 
+static int
+build_bp_list (struct breakpoint *b, void *arg)
+{
+  PyObject *list = arg;
+  PyObject *bp = b->py_bp_object;
+  int iserr = 0;
+
+  /* Not all breakpoints will have a companion Python object.
+     Only breakpoints that were created via bppy_new, or
+     breakpoints that were created externally and are tracked by
+     the Python Scripting API.  */
+  if (bp)
+    iserr = PyList_Append (list, bp);
+
+  if (iserr == -1)
+    return 1;
+
+  return 0;
+}
+
 /* Static function to return a tuple holding all breakpoints.  */
 
 PyObject *
 gdbpy_breakpoints (PyObject *self, PyObject *args)
 {
-  PyObject *result;
+  PyObject *list;
 
   if (bppy_live == 0)
     Py_RETURN_NONE;
 
-  result = PyTuple_New (bppy_live);
-  if (result)
-    {
-      int i, out = 0;
+  list = PyList_New (0);
+  if (!list)
+    return NULL;
 
-      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;
-       }
+  /* If iteratre_over_breakpoints returns non NULL it signals an error
+     condition.  In that case abandon building the list and return
+     NULL.  */
+  if (iterate_over_breakpoints (build_bp_list, list) != NULL)
+    {
+      Py_DECREF (list);
+      return NULL;
     }
-  return result;
+
+  return PyList_AsTuple (list);
 }
 
 \f
@@ -671,13 +691,13 @@ gdbpy_breakpoint_created (int num)
   struct breakpoint *bp = NULL;
   PyGILState_STATE state;
 
-  if (num < 0)
-    return;
-
   bp = get_breakpoint (num);
   if (! bp)
     return;
 
+  if (num < 0 && bppy_pending_object == NULL)
+    return;
+
   if (bp->type != bp_breakpoint 
       && bp->type != bp_watchpoint
       && bp->type != bp_hardware_watchpoint  
@@ -685,21 +705,6 @@ 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)
@@ -713,12 +718,16 @@ gdbpy_breakpoint_created (int num)
     {
       newbp->number = num;
       newbp->bp = bp;
-      bppy_breakpoints[num] = newbp;
+      newbp->bp->py_bp_object = (PyObject *) newbp;
       Py_INCREF (newbp);
+      ++bppy_live;
+    }
+  else
+    {
+      PyErr_SetString (PyExc_RuntimeError,
+                      _("Error while creating breakpoint from GDB."));
+      gdbpy_print_stack ();
     }
-
-  /* Just ignore errors here.  */
-  PyErr_Clear ();
 
   PyGILState_Release (state);
 }
@@ -729,14 +738,20 @@ static void
 gdbpy_breakpoint_deleted (int num)
 {
   PyGILState_STATE state;
+  struct breakpoint *bp = NULL;
+  breakpoint_object *bp_obj;
 
   state = PyGILState_Ensure ();
-  if (bpnum_is_valid (num))
+  bp = get_breakpoint (num);
+  if (! bp)
+    return;
+
+  bp_obj = ((breakpoint_object *) bp->py_bp_object);
+  if (bp_obj)
     {
-      bppy_breakpoints[num]->bp = NULL;
-      Py_DECREF (bppy_breakpoints[num]);
-      bppy_breakpoints[num] = NULL;
+      bp_obj->bp = NULL;
       --bppy_live;
+      Py_DECREF (bp_obj);
     }
   PyGILState_Release (state);
 }
@@ -819,6 +834,8 @@ 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,
+    "Whether the breakpoint is visible to the user."},
   { NULL }  /* Sentinel.  */
 };
 
index b34833c..0e73d92 100644 (file)
@@ -1895,7 +1895,8 @@ spu_catch_start (struct objfile *objfile)
                     bp_breakpoint /* type_wanted */,
                     0 /* ignore_count */,
                     AUTO_BOOLEAN_FALSE /* pending_break_support */,
-                    NULL /* ops */, 0 /* from_tty */, 1 /* enabled */);
+                    NULL /* ops */, 0 /* from_tty */, 1 /* enabled */,
+                    0 /* internal  */););
 }
 
 
index dae986b..11b86ad 100644 (file)
@@ -1,3 +1,8 @@
+2010-11-11  Phil Muldoon  <pmuldoon@redhat.com>
+
+       * gdb.python/py-breakpoint.exp: Add internal watchpoint and
+       breakpoint tests.
+
 2010-11-09  Pedro Alves  <pedro@codesourcery.com>
 
        * gdb.base/watchpoint.exp: Test "watch -location" with an
index 7da94c4..d030b55 100644 (file)
@@ -117,6 +117,33 @@ 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\", internal=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" "True" "Check breakpoint visibility"
+gdb_test "info breakpoints" "py-breakpoint\.c:$ibp_location.*" "Check info breakpoints shows visible breakpoints"
+delete_breakpoints
+gdb_py_test_silent_cmd  "python ibp = gdb.Breakpoint(\"$ibp_location\", internal=True)" "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" "False" "Check breakpoint visibility"
+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"
+
+
 # Watchpoints
 # Start with a fresh gdb.
 clean_restart ${testfile}
@@ -134,5 +161,17 @@ if ![runto_main] then {
 gdb_py_test_silent_cmd  "python wp1 = gdb.Breakpoint (\"result\", type=gdb.BP_WATCHPOINT, wp_class=gdb.WP_WRITE )" "Set watchpoint" 0
 gdb_test "continue" ".*\[Ww\]atchpoint.*result.*Old value = 0.*New value = 25.*main.*" "Test watchpoint write"
 
+# Internal breakpoints.
 
+# Start with a fresh gdb.
+clean_restart ${testfile}
 
+if ![runto_main] then {
+    fail "Cannot run to main."
+    return 0
+}
+delete_breakpoints
+gdb_py_test_silent_cmd  "python wp1 = gdb.Breakpoint (\"result\", type=gdb.BP_WATCHPOINT, wp_class=gdb.WP_WRITE, internal=True )" "Set watchpoint" 0
+gdb_test "info breakpoints" "No breakpoints or watchpoints.*" "Check info breakpoints does not show invisible breakpoints"
+gdb_test "maint info breakpoints" ".*hw watchpoint.*result.*" "Check maint info breakpoints shows invisible breakpoints"
+gdb_test "continue" ".*\[Ww\]atchpoint.*result.*Old value = 0.*New value = 25.*" "Test watchpoint write"
index 09f91eb..9cff971 100644 (file)
@@ -39,8 +39,6 @@
 #if HAVE_PYTHON
 #include "python/python.h"
 #include "python/python-internal.h"
-#else
-typedef int PyObject;
 #endif
 
 /* Non-zero if we want to see trace of varobj level stuff.  */