From 84f4c1fe0525fb92c79216087fd8c1744aafb203 Mon Sep 17 00:00:00 2001 From: Phil Muldoon Date: Thu, 11 Nov 2010 14:11:56 +0000 Subject: [PATCH] 2010-11-11 Phil Muldoon * 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 * gdb.texinfo (Breakpoints In Python): Document "internal" parameter, and visible attribute. 2010-11-11 Phil Muldoon * gdb.python/py-breakpoint.exp: Add internal watchpoint and breakpoint tests. --- gdb/ChangeLog | 36 +++++ gdb/breakpoint.c | 137 +++++++++++++----- gdb/breakpoint.h | 34 ++++- gdb/defs.h | 4 + gdb/doc/ChangeLog | 5 + gdb/doc/gdb.texinfo | 18 ++- gdb/mi/mi-cmd-break.c | 8 +- gdb/python/py-breakpoint.c | 161 ++++++++++++--------- gdb/spu-tdep.c | 3 +- gdb/testsuite/ChangeLog | 5 + gdb/testsuite/gdb.python/py-breakpoint.exp | 39 +++++ gdb/varobj.c | 2 - 12 files changed, 326 insertions(+), 126 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 8c8a5bdf3f..2c413a3413 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,39 @@ +2010-11-11 Phil Muldoon + + * 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 * python/lib/gdb/command/pretty_printers.py diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index ffa8c52026..6b55313734 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -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) { diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h index 9f7600a3b7..e34c2d3e84 100644 --- a/gdb/breakpoint.h +++ b/gdb/breakpoint.h @@ -24,6 +24,11 @@ #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) */ diff --git a/gdb/defs.h b/gdb/defs.h index 489de74e75..d36f7c19b5 100644 --- a/gdb/defs.h +++ b/gdb/defs.h @@ -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 */ diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 7e006ce4e4..d999772c26 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,8 @@ +2010-11-11 Phil Muldoon + + * gdb.texinfo (Breakpoints In Python): Document "internal" + parameter, and visible attribute. + 2010-11-05 Doug Evans * gdb.texinfo (Source Path): Document "set directories". diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 257ff191f7..cf70ce43ef 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -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: diff --git a/gdb/mi/mi-cmd-break.c b/gdb/mi/mi-cmd-break.c index 34082440a1..2aad420466 100644 --- a/gdb/mi/mi-cmd-break.c +++ b/gdb/mi/mi-cmd-break.c @@ -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.")); diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c index b18f7f32d6..8afa414ecb 100644 --- a/gdb/python/py-breakpoint.c +++ b/gdb/python/py-breakpoint.c @@ -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) +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); } @@ -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. */ }; diff --git a/gdb/spu-tdep.c b/gdb/spu-tdep.c index b34833cf93..0e73d92d24 100644 --- a/gdb/spu-tdep.c +++ b/gdb/spu-tdep.c @@ -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 */);); } diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index dae986b628..11b86ad387 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2010-11-11 Phil Muldoon + + * gdb.python/py-breakpoint.exp: Add internal watchpoint and + breakpoint tests. + 2010-11-09 Pedro Alves * gdb.base/watchpoint.exp: Test "watch -location" with an diff --git a/gdb/testsuite/gdb.python/py-breakpoint.exp b/gdb/testsuite/gdb.python/py-breakpoint.exp index 7da94c490f..d030b550ed 100644 --- a/gdb/testsuite/gdb.python/py-breakpoint.exp +++ b/gdb/testsuite/gdb.python/py-breakpoint.exp @@ -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\]" "" "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\]" "" "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" diff --git a/gdb/varobj.c b/gdb/varobj.c index 09f91eb669..9cff971403 100644 --- a/gdb/varobj.c +++ b/gdb/varobj.c @@ -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. */ -- 2.34.1