diff options
author | Vladimir Prus <vladimir@codesourcery.com> | 2011-04-27 10:17:39 +0000 |
---|---|---|
committer | Vladimir Prus <vladimir@codesourcery.com> | 2011-04-27 10:17:39 +0000 |
commit | 8d3788bd590aa066f4f8383b7f8da20211e4ea9e (patch) | |
tree | 70a6d9187ed169486305055cf406ee9d0a79c08f | |
parent | b4e7b88557a669c6a400014f406fcf5a5abb5290 (diff) | |
download | gdb-8d3788bd590aa066f4f8383b7f8da20211e4ea9e.zip gdb-8d3788bd590aa066f4f8383b7f8da20211e4ea9e.tar.gz gdb-8d3788bd590aa066f4f8383b7f8da20211e4ea9e.tar.bz2 |
MI breakpoint notifications.
* annotate.c (breakpoint_changed): Adjust parameter type.
* breakpoint.c (set_breakpoint_condition): Adjust to change
in breakpoint_modified type.
(breakpoint_set_commands): Likewise.
(do_map_commands_command): Likewise.
(bpstat_check_breakpoint_conditions): Notify that breakpoint has
changed after bumping hit count.
(bpstat_stop_status): Likewise.
(print_one_breakpoint_location): Don't wrap in tuple here.
(print_one_breakpoint): Always print individual locations.
For locations, use unnamed tuple.
(disable_breakpoints_in_unloaded_shlib): Notify that breakpoint
has changed.
(create_catchpoint, create_syscall_event_catchpoint): Call
breakpoint_created obsever.
(mention): Don't call breakpoint_created observer.
(create_breakpoint_sal): Call breakpoint_created observer.
(create_breakpoint, watch_command_1): Likewise.
(create_ada_exception_breakpoint): Likewise.
(delete_breakpoint): Call breakpoint_deleted breakpoint.
(locations_are_equal): New.
(update_breakpoint_locations): If locations were changed, notify.
(set_ignore_count, disable_breakpoint, do_enable_breakpoint):
Call breakpoint_modified observer.
* mi/mi-cmd-break.c (breakpoint_notify): Adjust.
(mi_cmd_break_insert): Don't set observers for modify and delete.
* mi/mi-interp.c (mi_suppress_breakpoint_notifications): New.
(mi_breakpoint_created, mi_breakpoint_deleted)
(mi_breakpoint_modified): New.
(mi_interpreter_init): Hook the above.
* mi/mi-main.c (mi_cmd_execute): Disable breakpoint notifications
while -break-* commands are executing.
* mi/mi-main.h (mi_suppress_breakpoint_notifications): New.
* mi/mi-out.c (struct ui_out_data): New field original_buffer.
(mi_redirect): New.
(mi_ui_out_impl): Hook in mi_redirect.
(mi_field_skip): True to the name, skip the field, don't output
a field with an empty value.
* python/py-breakpoint.c (gdbpy_breakpoint_created)
(gdbpy_breakpoint_deleted): Adjust.
* tui/tui-hooks.c (tui_event_create_breakpoint)
(tui_event_delete_breakpoint, tui_event_modify_breakpoint): Adjust.
-rw-r--r-- | gdb/ChangeLog | 49 | ||||
-rw-r--r-- | gdb/annotate.c | 4 | ||||
-rw-r--r-- | gdb/breakpoint.c | 112 | ||||
-rw-r--r-- | gdb/doc/gdb.texinfo | 13 | ||||
-rw-r--r-- | gdb/doc/observer.texi | 17 | ||||
-rw-r--r-- | gdb/mi/mi-cmd-break.c | 7 | ||||
-rw-r--r-- | gdb/mi/mi-interp.c | 96 | ||||
-rw-r--r-- | gdb/mi/mi-main.c | 10 | ||||
-rw-r--r-- | gdb/mi/mi-main.h | 1 | ||||
-rw-r--r-- | gdb/mi/mi-out.c | 28 | ||||
-rw-r--r-- | gdb/python/py-breakpoint.c | 12 | ||||
-rw-r--r-- | gdb/testsuite/ChangeLog | 11 | ||||
-rw-r--r-- | gdb/testsuite/gdb.mi/mi-cli.exp | 2 | ||||
-rw-r--r-- | gdb/testsuite/gdb.mi/mi-watch.exp | 2 | ||||
-rw-r--r-- | gdb/testsuite/gdb.mi/mi2-cli.exp | 2 | ||||
-rw-r--r-- | gdb/testsuite/gdb.mi/mi2-watch.exp | 2 | ||||
-rw-r--r-- | gdb/testsuite/lib/mi-support.exp | 6 | ||||
-rw-r--r-- | gdb/tui/tui-hooks.c | 6 |
18 files changed, 305 insertions, 75 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index c4995c7..13014b9 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,52 @@ +2011-04-27 Vladimir Prus <vladimir@codesourcery.com> + + MI breakpoint notifications. + + * annotate.c (breakpoint_changed): Adjust parameter type. + * breakpoint.c (set_breakpoint_condition): Adjust to change + in breakpoint_modified type. + (breakpoint_set_commands): Likewise. + (do_map_commands_command): Likewise. + (bpstat_check_breakpoint_conditions): Notify that breakpoint has + changed after bumping hit count. + (bpstat_stop_status): Likewise. + (print_one_breakpoint_location): Don't wrap in tuple here. + (print_one_breakpoint): Always print individual locations. + For locations, use unnamed tuple. + (disable_breakpoints_in_unloaded_shlib): Notify that breakpoint + has changed. + (create_catchpoint, create_syscall_event_catchpoint): Call + breakpoint_created obsever. + (mention): Don't call breakpoint_created observer. + (create_breakpoint_sal): Call breakpoint_created observer. + (create_breakpoint, watch_command_1): Likewise. + (create_ada_exception_breakpoint): Likewise. + (delete_breakpoint): Call breakpoint_deleted breakpoint. + (locations_are_equal): New. + (update_breakpoint_locations): If locations were changed, notify. + (set_ignore_count, disable_breakpoint, do_enable_breakpoint): + Call breakpoint_modified observer. + + * mi/mi-cmd-break.c (breakpoint_notify): Adjust. + (mi_cmd_break_insert): Don't set observers for modify and delete. + * mi/mi-interp.c (mi_suppress_breakpoint_notifications): New. + (mi_breakpoint_created, mi_breakpoint_deleted) + (mi_breakpoint_modified): New. + (mi_interpreter_init): Hook the above. + * mi/mi-main.c (mi_cmd_execute): Disable breakpoint notifications + while -break-* commands are executing. + * mi/mi-main.h (mi_suppress_breakpoint_notifications): New. + * mi/mi-out.c (struct ui_out_data): New field original_buffer. + (mi_redirect): New. + (mi_ui_out_impl): Hook in mi_redirect. + (mi_field_skip): True to the name, skip the field, don't output + a field with an empty value. + + * python/py-breakpoint.c (gdbpy_breakpoint_created) + (gdbpy_breakpoint_deleted): Adjust. + * tui/tui-hooks.c (tui_event_create_breakpoint) + (tui_event_delete_breakpoint, tui_event_modify_breakpoint): Adjust. + 2011-04-26 Aleksandar Ristovski <aristovski@qnx.com> * nto-procfs.c (procfs_insert_hw_watchpoint): Fix prototype. diff --git a/gdb/annotate.c b/gdb/annotate.c index d24120c..2f0769a 100644 --- a/gdb/annotate.c +++ b/gdb/annotate.c @@ -32,7 +32,7 @@ extern void _initialize_annotate (void); static void print_value_flags (struct type *); -static void breakpoint_changed (int); +static void breakpoint_changed (struct breakpoint *b); void (*deprecated_annotate_signalled_hook) (void); @@ -561,7 +561,7 @@ annotate_array_section_end (void) } static void -breakpoint_changed (int bpno) +breakpoint_changed (struct breakpoint *b) { breakpoints_changed (); } diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 3dbee85..bf6b1ef 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -626,7 +626,7 @@ set_breakpoint_condition (struct breakpoint *b, char *exp, } } breakpoints_changed (); - observer_notify_breakpoint_modified (b->number); + observer_notify_breakpoint_modified (b); } /* condition N EXP -- set break condition of breakpoint N to EXP. */ @@ -791,7 +791,7 @@ breakpoint_set_commands (struct breakpoint *b, decref_counted_command_line (&b->commands); b->commands = alloc_counted_command_line (commands); breakpoints_changed (); - observer_notify_breakpoint_modified (b->number); + observer_notify_breakpoint_modified (b); } /* Set the internal `silent' flag on the breakpoint. Note that this @@ -805,7 +805,7 @@ breakpoint_set_silent (struct breakpoint *b, int silent) b->silent = silent; if (old_silent != silent) - observer_notify_breakpoint_modified (b->number); + observer_notify_breakpoint_modified (b); } /* Set the thread for this breakpoint. If THREAD is -1, make the @@ -818,7 +818,7 @@ breakpoint_set_thread (struct breakpoint *b, int thread) b->thread = thread; if (old_thread != thread) - observer_notify_breakpoint_modified (b->number); + observer_notify_breakpoint_modified (b); } /* Set the task for this breakpoint. If TASK is 0, make the @@ -831,7 +831,7 @@ breakpoint_set_task (struct breakpoint *b, int task) b->task = task; if (old_task != task) - observer_notify_breakpoint_modified (b->number); + observer_notify_breakpoint_modified (b); } void @@ -908,7 +908,7 @@ do_map_commands_command (struct breakpoint *b, void *data) decref_counted_command_line (&b->commands); b->commands = info->cmd; breakpoints_changed (); - observer_notify_breakpoint_modified (b->number); + observer_notify_breakpoint_modified (b); } } @@ -1672,6 +1672,7 @@ insert_bp_location (struct bp_location *bl, /* See also: disable_breakpoints_in_shlibs. */ val = 0; bl->shlib_disabled = 1; + observer_notify_breakpoint_modified (bl->owner); if (!*disabled_breaks) { fprintf_unfiltered (tmp_error_stream, @@ -4173,6 +4174,7 @@ bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid) bs->stop = 0; /* Increase the hit count even though we don't stop. */ ++(b->hit_count); + observer_notify_breakpoint_modified (b); } } } @@ -4301,6 +4303,7 @@ bpstat_stop_status (struct address_space *aspace, if (bs->stop) { ++(b->hit_count); + observer_notify_breakpoint_modified (b); /* We will stop here. */ if (b->disposition == disp_disable) @@ -4768,7 +4771,6 @@ print_one_breakpoint_location (struct breakpoint *b, { struct command_line *l; static char bpenables[] = "nynny"; - struct cleanup *bkpt_chain; int header_of_multiple = 0; int part_of_multiple = (loc != NULL); @@ -4787,7 +4789,6 @@ print_one_breakpoint_location (struct breakpoint *b, loc = b->loc; annotate_record (); - bkpt_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "bkpt"); /* 1 */ annotate_field (0); @@ -5052,8 +5053,6 @@ print_one_breakpoint_location (struct breakpoint *b, else if (b->exp_string) ui_out_field_string (uiout, "original-location", b->exp_string); } - - do_cleanups (bkpt_chain); } static void @@ -5061,7 +5060,12 @@ print_one_breakpoint (struct breakpoint *b, struct bp_location **last_loc, int allflag) { + struct cleanup *bkpt_chain; + + bkpt_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "bkpt"); + print_one_breakpoint_location (b, NULL, 0, last_loc, allflag); + do_cleanups (bkpt_chain); /* If this breakpoint has custom print function, it's already printed. Otherwise, print individual @@ -5077,13 +5081,18 @@ print_one_breakpoint (struct breakpoint *b, internally, that's not a property exposed to user. */ if (b->loc && !is_hardware_watchpoint (b) - && (b->loc->next || !b->loc->enabled) - && !ui_out_is_mi_like_p (uiout)) + && (b->loc->next || !b->loc->enabled)) { struct bp_location *loc; int n = 1; + for (loc = b->loc; loc; loc = loc->next, ++n) - print_one_breakpoint_location (b, loc, n, last_loc, allflag); + { + struct cleanup *inner2 = + make_cleanup_ui_out_tuple_begin_end (uiout, NULL); + print_one_breakpoint_location (b, loc, n, last_loc, allflag); + do_cleanups (inner2); + } } } } @@ -6191,6 +6200,10 @@ disable_breakpoints_in_unloaded_shlib (struct so_list *solib) succeeding so we must mark the breakpoint as not inserted to prevent future errors occurring in remove_breakpoints. */ loc->inserted = 0; + + /* This may cause duplicate notifications for the same breakpoint. */ + observer_notify_breakpoint_modified (b); + if (!disabled_shlib_breaks) { target_terminal_ours_for_output (); @@ -6747,6 +6760,7 @@ create_catchpoint (struct gdbarch *gdbarch, int tempflag, create_catchpoint_without_mention (gdbarch, tempflag, cond_string, ops); mention (b); + observer_notify_breakpoint_created (b); update_global_location_list (1); return b; @@ -6858,6 +6872,7 @@ create_syscall_event_catchpoint (int tempflag, VEC(int) *filter, /* Now, we have to mention the breakpoint and update the global location list. */ mention (b); + observer_notify_breakpoint_created (b); update_global_location_list (1); } @@ -7094,12 +7109,6 @@ mention (struct breakpoint *b) get_user_print_options (&opts); - /* FIXME: This is misplaced; mention() is called by things (like - hitting a watchpoint) other than breakpoint creation. It should - be possible to clean this up and at the same time replace the - random calls to breakpoint_changed with this hook. */ - observer_notify_breakpoint_created (b->number); - if (b->ops != NULL && b->ops->print_mention != NULL) b->ops->print_mention (b); else @@ -7454,12 +7463,11 @@ create_breakpoint_sal (struct gdbarch *gdbarch, = xstrprintf ("*%s", paddress (b->loc->gdbarch, b->loc->address)); b->ops = ops; - if (internal) - /* Do not mention breakpoints with a negative number, but do - notify observers. */ - observer_notify_breakpoint_created (b->number); - else + /* Do not mention breakpoints with a negative number, but do + notify observers. */ + if (!internal) mention (b); + observer_notify_breakpoint_created (b); } /* Remove element at INDEX_TO_REMOVE from SAL, shifting other @@ -8122,12 +8130,11 @@ create_breakpoint (struct gdbarch *gdbarch, || b->type == bp_hardware_breakpoint)) b->enable_state = bp_startup_disabled; - if (internal) + if (!internal) /* Do not mention breakpoints with a negative number, but do notify observers. */ - observer_notify_breakpoint_created (b->number); - else - mention (b); + mention (b); + observer_notify_breakpoint_created (b); } if (sals.nelts > 1) @@ -8631,6 +8638,7 @@ break_range_command (char *arg, int from_tty) discard_cleanups (cleanup_bkpt); mention (b); + observer_notify_breakpoint_created (b); update_global_location_list (1); } @@ -9065,12 +9073,13 @@ watch_command_1 (char *arg, int accessflag, int from_tty, /* Finally update the new watchpoint. This creates the locations that should be inserted. */ update_watchpoint (b, 1); - if (internal) - /* Do not mention breakpoints with a negative number, but do + + /* Do not mention breakpoints with a negative number, but do notify observers. */ - observer_notify_breakpoint_created (b->number); - else + if (!internal) mention (b); + observer_notify_breakpoint_created (b); + update_global_location_list (1); } @@ -9690,6 +9699,7 @@ create_ada_exception_breakpoint (struct gdbarch *gdbarch, b->ops = ops; mention (b); + observer_notify_breakpoint_created (b); update_global_location_list (1); } @@ -10496,7 +10506,7 @@ delete_breakpoint (struct breakpoint *bpt) bpt->related_breakpoint = bpt; } - observer_notify_breakpoint_deleted (bpt->number); + observer_notify_breakpoint_deleted (bpt); if (breakpoint_chain == bpt) breakpoint_chain = bpt->next; @@ -10807,6 +10817,33 @@ update_static_tracepoint (struct breakpoint *b, struct symtab_and_line sal) return sal; } +/* Returns 1 iff locations A and B are sufficiently same that + we don't need to report breakpoint as changed. */ + +static int +locations_are_equal (struct bp_location *a, struct bp_location *b) +{ + while (a && b) + { + if (a->address != b->address) + return 0; + + if (a->shlib_disabled != b->shlib_disabled) + return 0; + + if (a->enabled != b->enabled) + return 0; + + a = a->next; + b = b->next; + } + + if ((a == NULL) != (b == NULL)) + return 0; + + return 1; +} + /* Create new breakpoint locations for B (a hardware or software breakpoint) based on SALS and SALS_END. If SALS_END.NELTS is not zero, then B is a ranged breakpoint. */ @@ -10921,6 +10958,9 @@ update_breakpoint_locations (struct breakpoint *b, } } + if (!locations_are_equal (existing_locations, b->loc)) + observer_notify_breakpoint_modified (b); + update_global_location_list (1); } @@ -11264,7 +11304,7 @@ set_ignore_count (int bptnum, int count, int from_tty) count, bptnum); } breakpoints_changed (); - observer_notify_breakpoint_modified (b->number); + observer_notify_breakpoint_modified (b); return; } @@ -11419,7 +11459,7 @@ disable_breakpoint (struct breakpoint *bpt) update_global_location_list (0); - observer_notify_breakpoint_modified (bpt->number); + observer_notify_breakpoint_modified (bpt); } /* A callback for map_breakpoint_numbers that calls @@ -11510,7 +11550,7 @@ do_enable_breakpoint (struct breakpoint *bpt, enum bpdisp disposition) update_global_location_list (1); breakpoints_changed (); - observer_notify_breakpoint_modified (bpt->number); + observer_notify_breakpoint_modified (bpt); } diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index e58dd57..15ccf2e 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -25191,6 +25191,19 @@ thread group in whose context the library was unloaded. If the field is absent, it means the library was unloaded in the context of all present thread groups. +@item =breakpoint-created,bkpt=@{...@} +@itemx =breakpoint-modified,bkpt=@{...@} +@itemx =breakpoint-deleted,bkpt=@{...@} +Reports that a breakpoint was created, modified, or deleted, +respectively. Only user-visible breakpoints are reported to the MI +user. + +The @var{bkpt} argument is of the same form as returned by the various +breakpoint commands; @xref{GDB/MI Breakpoint Commands}. + +Note that if a breakpoint is emitted in the result record of a +command, then it will not also be emitted in an async record. + @end table @node GDB/MI Frame Information diff --git a/gdb/doc/observer.texi b/gdb/doc/observer.texi index d16c865..d8c3924 100644 --- a/gdb/doc/observer.texi +++ b/gdb/doc/observer.texi @@ -159,19 +159,18 @@ thread was resume, and may be RESUME_ALL if all threads are resumed. The target is about to be proceeded. @end deftypefun -@deftypefun void breakpoint_created (int @var{bpnum}) -A new breakpoint has been created. The argument @var{bpnum} is the -number of the newly-created breakpoint. +@deftypefun void breakpoint_created (struct breakpoint *@var{b}) +A new breakpoint @var{b} has been created. @end deftypefun -@deftypefun void breakpoint_deleted (int @var{bpnum}) -A breakpoint has been destroyed. The argument @var{bpnum} is the -number of the newly-destroyed breakpoint. +@deftypefun void breakpoint_deleted (struct breakpoint *@var{b}) +A breakpoint has been destroyed. The argument @var{b} is the +pointer to the destroyed breakpoint. @end deftypefun -@deftypefun void breakpoint_modified (int @var{bpnum}) -A breakpoint has been modified in some way. The argument @var{bpnum} -is the number of the modified breakpoint. +@deftypefun void breakpoint_modified (struct breakpoint *@var{b}) +A breakpoint has been modified in some way. The argument @var{b} +is the modified breakpoint. @end deftypefun @deftypefun void tracepoint_created (int @var{tpnum}) diff --git a/gdb/mi/mi-cmd-break.c b/gdb/mi/mi-cmd-break.c index fe007a5..d68a033 100644 --- a/gdb/mi/mi-cmd-break.c +++ b/gdb/mi/mi-cmd-break.c @@ -29,6 +29,7 @@ #include "gdb.h" #include "exceptions.h" #include "observer.h" +#include "mi-main.h" enum { @@ -46,10 +47,10 @@ static int mi_can_breakpoint_notify; /* Output a single breakpoint, when allowed. */ static void -breakpoint_notify (int b) +breakpoint_notify (struct breakpoint *b) { if (mi_can_breakpoint_notify) - gdb_breakpoint_query (uiout, b, NULL); + gdb_breakpoint_query (uiout, b->number, NULL); } enum bp_type @@ -146,8 +147,6 @@ mi_cmd_break_insert (char *command, char **argv, int argc) if (! mi_breakpoint_observers_installed) { observer_attach_breakpoint_created (breakpoint_notify); - observer_attach_breakpoint_modified (breakpoint_notify); - observer_attach_breakpoint_deleted (breakpoint_notify); mi_breakpoint_observers_installed = 1; } diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c index 23c60f6..c075b0c 100644 --- a/gdb/mi/mi-interp.c +++ b/gdb/mi/mi-interp.c @@ -35,6 +35,7 @@ #include "observer.h" #include "gdbthread.h" #include "solist.h" +#include "gdb.h" /* These are the interpreter setup, etc. functions for the MI interpreter */ static void mi_execute_command_wrapper (char *cmd); @@ -64,6 +65,9 @@ static void mi_on_resume (ptid_t ptid); static void mi_solib_loaded (struct so_list *solib); static void mi_solib_unloaded (struct so_list *solib); static void mi_about_to_proceed (void); +static void mi_breakpoint_created (struct breakpoint *b); +static void mi_breakpoint_deleted (struct breakpoint *b); +static void mi_breakpoint_modified (struct breakpoint *b); static int report_initial_inferior (struct inferior *inf, void *closure); @@ -99,6 +103,9 @@ mi_interpreter_init (int top_level) observer_attach_solib_loaded (mi_solib_loaded); observer_attach_solib_unloaded (mi_solib_unloaded); observer_attach_about_to_proceed (mi_about_to_proceed); + observer_attach_breakpoint_created (mi_breakpoint_created); + observer_attach_breakpoint_deleted (mi_breakpoint_deleted); + observer_attach_breakpoint_modified (mi_breakpoint_modified); /* The initial inferior is created before this function is called, so we need to report it explicitly. Use iteration in case future version @@ -445,6 +452,95 @@ mi_about_to_proceed (void) mi_proceeded = 1; } +/* When non-zero, no MI notifications will be emitted in + response to breakpoint change observers. */ +int mi_suppress_breakpoint_notifications = 0; + +/* Emit notification about a created breakpoint. */ +static void +mi_breakpoint_created (struct breakpoint *b) +{ + struct mi_interp *mi = top_level_interpreter_data (); + struct ui_out *mi_uiout = interp_ui_out (top_level_interpreter ()); + struct gdb_exception e; + + if (mi_suppress_breakpoint_notifications) + return; + + if (b->number <= 0) + return; + + target_terminal_ours (); + fprintf_unfiltered (mi->event_channel, + "breakpoint-created"); + /* We want the output from gdb_breakpoint_query to go to + mi->event_channel. One approach would be to just + call gdb_breakpoint_query, and then use mi_out_put to + send the current content of mi_outout into mi->event_channel. + However, that will break if anything is output to mi_uiout + prior the calling the breakpoint_created notifications. + So, we use ui_out_redirect. */ + ui_out_redirect (mi_uiout, mi->event_channel); + TRY_CATCH (e, RETURN_MASK_ERROR) + gdb_breakpoint_query (mi_uiout, b->number, NULL); + ui_out_redirect (mi_uiout, NULL); + + gdb_flush (mi->event_channel); +} + +/* Emit notification about deleted breakpoint. */ +static void +mi_breakpoint_deleted (struct breakpoint *b) +{ + struct mi_interp *mi = top_level_interpreter_data (); + + if (mi_suppress_breakpoint_notifications) + return; + + if (b->number <= 0) + return; + + target_terminal_ours (); + + fprintf_unfiltered (mi->event_channel, "breakpoint-deleted,id=\"%d\"", + b->number); + + gdb_flush (mi->event_channel); +} + +/* Emit notification about modified breakpoint. */ +static void +mi_breakpoint_modified (struct breakpoint *b) +{ + struct mi_interp *mi = top_level_interpreter_data (); + struct ui_out *mi_uiout = interp_ui_out (top_level_interpreter ()); + struct gdb_exception e; + + if (mi_suppress_breakpoint_notifications) + return; + + if (b->number <= 0) + return; + + target_terminal_ours (); + fprintf_unfiltered (mi->event_channel, + "breakpoint-modified"); + /* We want the output from gdb_breakpoint_query to go to + mi->event_channel. One approach would be to just + call gdb_breakpoint_query, and then use mi_out_put to + send the current content of mi_outout into mi->event_channel. + However, that will break if anything is output to mi_uiout + prior the calling the breakpoint_created notifications. + So, we use ui_out_redirect. */ + ui_out_redirect (mi_uiout, mi->event_channel); + TRY_CATCH (e, RETURN_MASK_ERROR) + gdb_breakpoint_query (mi_uiout, b->number, NULL); + ui_out_redirect (mi_uiout, NULL); + + gdb_flush (mi->event_channel); +} + + static int mi_output_running_pid (struct thread_info *info, void *arg) { diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c index 6410e97..e37f3b5 100644 --- a/gdb/mi/mi-main.c +++ b/gdb/mi/mi-main.c @@ -2088,8 +2088,16 @@ mi_cmd_execute (struct mi_parse *parse) current_context = parse; + if (strncmp (parse->command, "break-", sizeof ("break-") - 1 ) == 0) + { + make_cleanup_restore_integer (&mi_suppress_breakpoint_notifications); + mi_suppress_breakpoint_notifications = 1; + } + if (parse->cmd->argv_func != NULL) - parse->cmd->argv_func (parse->command, parse->argv, parse->argc); + { + parse->cmd->argv_func (parse->command, parse->argv, parse->argc); + } else if (parse->cmd->cli.cmd != 0) { /* FIXME: DELETE THIS. */ diff --git a/gdb/mi/mi-main.h b/gdb/mi/mi-main.h index 3ad6d0f..4de0983 100644 --- a/gdb/mi/mi-main.h +++ b/gdb/mi/mi-main.h @@ -33,6 +33,7 @@ extern char *current_token; extern int running_result_record_printed; extern int mi_proceeded; +extern int mi_suppress_breakpoint_notifications; #endif diff --git a/gdb/mi/mi-out.c b/gdb/mi/mi-out.c index 9aaeec6..ea77e50 100644 --- a/gdb/mi/mi-out.c +++ b/gdb/mi/mi-out.c @@ -30,6 +30,7 @@ struct ui_out_data int suppress_output; int mi_version; struct ui_file *buffer; + struct ui_file *original_buffer; }; typedef struct ui_out_data mi_out_data; @@ -63,6 +64,7 @@ static void mi_message (struct ui_out *uiout, int verbosity, ATTRIBUTE_PRINTF (3, 0); static void mi_wrap_hint (struct ui_out *uiout, char *identstring); static void mi_flush (struct ui_out *uiout); +static int mi_redirect (struct ui_out *uiout, struct ui_file *outstream); /* This is the MI ui-out implementation functions vector */ @@ -86,7 +88,7 @@ struct ui_out_impl mi_ui_out_impl = mi_message, mi_wrap_hint, mi_flush, - NULL, + mi_redirect, 1, /* Needs MI hacks. */ }; @@ -210,11 +212,6 @@ void mi_field_skip (struct ui_out *uiout, int fldno, int width, enum ui_align alignment, const char *fldname) { - mi_out_data *data = ui_out_data (uiout); - - if (data->suppress_output) - return; - mi_field_string (uiout, fldno, width, alignment, fldname, ""); } /* other specific mi_field_* end up here so alignment and field @@ -294,6 +291,25 @@ mi_flush (struct ui_out *uiout) gdb_flush (data->buffer); } +int +mi_redirect (struct ui_out *uiout, struct ui_file *outstream) +{ + mi_out_data *data = ui_out_data (uiout); + + if (outstream != NULL) + { + data->original_buffer = data->buffer; + data->buffer = outstream; + } + else if (data->original_buffer != NULL) + { + data->buffer = data->original_buffer; + data->original_buffer = NULL; + } + + return 0; +} + /* local functions */ /* access to ui_out format private members */ diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c index 0c21bfc..39578f1 100644 --- a/gdb/python/py-breakpoint.c +++ b/gdb/python/py-breakpoint.c @@ -782,16 +782,11 @@ gdbpy_breakpoint_has_py_cond (struct breakpoint_object *bp_obj) /* Callback that is used when a breakpoint is created. This function will create a new Python breakpoint object. */ static void -gdbpy_breakpoint_created (int num) +gdbpy_breakpoint_created (struct breakpoint *bp) { breakpoint_object *newbp; - struct breakpoint *bp = NULL; PyGILState_STATE state; - bp = get_breakpoint (num); - if (! bp) - return; - if (num < 0 && bppy_pending_object == NULL) return; @@ -813,7 +808,7 @@ gdbpy_breakpoint_created (int num) newbp = PyObject_New (breakpoint_object, &breakpoint_object_type); if (newbp) { - newbp->number = num; + newbp->number = bp->number; newbp->bp = bp; newbp->bp->py_bp_object = newbp; Py_INCREF (newbp); @@ -832,8 +827,9 @@ gdbpy_breakpoint_created (int num) /* Callback that is used when a breakpoint is deleted. This will invalidate the corresponding Python object. */ static void -gdbpy_breakpoint_deleted (int num) +gdbpy_breakpoint_deleted (struct breakpoint *b) { + int num = b->number; PyGILState_STATE state; struct breakpoint *bp = NULL; breakpoint_object *bp_obj; diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 0485d21..3bb5725 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,14 @@ +2011-04-27 Vladimir Prus <vladimir@codesourcery.com> + + MI breakpoint notifications. + + * testsuite/gdb.mi/mi-cli.exp: Adust. + * testsuite/gdb.mi/mi2-cli.exp: Adust. + * testsuite/gdb.mi/mi-watch.exp: Adust. + * testsuite/gdb.mi/mi2-watch.exp: Adust. + * testsuite/lib/mi-support.exp (mi_expect_stop): Accept breakpoint + notifications. + 2011-04-25 Jan Kratochvil <jan.kratochvil@redhat.com> * gdb.base/gdbindex-stabs-dwarf.c: New file. diff --git a/gdb/testsuite/gdb.mi/mi-cli.exp b/gdb/testsuite/gdb.mi/mi-cli.exp index e3096f8..d24f95f 100644 --- a/gdb/testsuite/gdb.mi/mi-cli.exp +++ b/gdb/testsuite/gdb.mi/mi-cli.exp @@ -108,7 +108,7 @@ mi_execute_to "exec-continue" "breakpoint-hit" "callee4" "" ".*basics.c" $line_c # {.*=breakpoint-delete,number=\"2\".*\^done} \ # "-interpreter-exec console \"delete 2\"" mi_gdb_test "100-interpreter-exec console \"delete 2\"" \ - {100\^done} \ + {=breakpoint-deleted,id=\"2\"\r\n100\^done} \ "-interpreter-exec console \"delete 2\"" # NOTE: cagney/2003-02-03: Not yet. diff --git a/gdb/testsuite/gdb.mi/mi-watch.exp b/gdb/testsuite/gdb.mi/mi-watch.exp index 6b1db46..a2c69e1 100644 --- a/gdb/testsuite/gdb.mi/mi-watch.exp +++ b/gdb/testsuite/gdb.mi/mi-watch.exp @@ -59,7 +59,7 @@ proc test_watchpoint_creation_and_listing {type} { "break-watch operation" mi_gdb_test "222-break-list" \ - "222\\\^done,BreakpointTable=\{nr_rows=\".\",nr_cols=\".\",hdr=\\\[\{width=\".*\",alignment=\".*\",col_name=\"number\",colhdr=\"Num\"\}.*colhdr=\"Type\".*colhdr=\"Disp\".*colhdr=\"Enb\".*colhdr=\"Address\".*colhdr=\"What\".*\\\],body=\\\[bkpt=\{number=\"2\",type=\".*watchpoint\",disp=\"keep\",enabled=\"y\",addr=\"\",what=\"C\",times=\"0\",original-location=\"C\"\}\\\]\}" \ + "222\\\^done,BreakpointTable=\{nr_rows=\".\",nr_cols=\".\",hdr=\\\[\{width=\".*\",alignment=\".*\",col_name=\"number\",colhdr=\"Num\"\}.*colhdr=\"Type\".*colhdr=\"Disp\".*colhdr=\"Enb\".*colhdr=\"Address\".*colhdr=\"What\".*\\\],body=\\\[bkpt=\{number=\"2\",type=\".*watchpoint\",disp=\"keep\",enabled=\"y\",what=\"C\",times=\"0\",original-location=\"C\"\}\\\]\}" \ "list of watchpoints" } diff --git a/gdb/testsuite/gdb.mi/mi2-cli.exp b/gdb/testsuite/gdb.mi/mi2-cli.exp index ba4a770..8dce12d 100644 --- a/gdb/testsuite/gdb.mi/mi2-cli.exp +++ b/gdb/testsuite/gdb.mi/mi2-cli.exp @@ -108,7 +108,7 @@ mi_execute_to "exec-continue" "breakpoint-hit" "callee4" "" ".*basics.c" $line_c # {.*=breakpoint-delete,number=\"2\".*\^done} \ # "-interpreter-exec console \"delete 2\"" mi_gdb_test "100-interpreter-exec console \"delete 2\"" \ - {100\^done} \ + {=breakpoint-deleted,id=\"2\"\r\n100\^done} \ "-interpreter-exec console \"delete 2\"" # NOTE: cagney/2003-02-03: Not yet. diff --git a/gdb/testsuite/gdb.mi/mi2-watch.exp b/gdb/testsuite/gdb.mi/mi2-watch.exp index 4c7d4a7..6ea2db0 100644 --- a/gdb/testsuite/gdb.mi/mi2-watch.exp +++ b/gdb/testsuite/gdb.mi/mi2-watch.exp @@ -59,7 +59,7 @@ proc test_watchpoint_creation_and_listing {type} { "break-watch operation" mi_gdb_test "222-break-list" \ - "222\\\^done,BreakpointTable=\{nr_rows=\".\",nr_cols=\".\",hdr=\\\[\{width=\".*\",alignment=\".*\",col_name=\"number\",colhdr=\"Num\"\}.*colhdr=\"Type\".*colhdr=\"Disp\".*colhdr=\"Enb\".*colhdr=\"Address\".*colhdr=\"What\".*\\\],body=\\\[bkpt=\{number=\"2\",type=\".*watchpoint\",disp=\"keep\",enabled=\"y\",addr=\"\",what=\"C\",times=\"0\",original-location=\"C\"\}\\\]\}" \ + "222\\\^done,BreakpointTable=\{nr_rows=\".\",nr_cols=\".\",hdr=\\\[\{width=\".*\",alignment=\".*\",col_name=\"number\",colhdr=\"Num\"\}.*colhdr=\"Type\".*colhdr=\"Disp\".*colhdr=\"Enb\".*colhdr=\"Address\".*colhdr=\"What\".*\\\],body=\\\[bkpt=\{number=\"2\",type=\".*watchpoint\",disp=\"keep\",enabled=\"y\",what=\"C\",times=\"0\",original-location=\"C\"\}\\\]\}" \ "list of watchpoints" } diff --git a/gdb/testsuite/lib/mi-support.exp b/gdb/testsuite/lib/mi-support.exp index e75a4f5..e3f6b03 100644 --- a/gdb/testsuite/lib/mi-support.exp +++ b/gdb/testsuite/lib/mi-support.exp @@ -32,6 +32,7 @@ set MIFLAGS "-i=mi" set thread_selected_re "=thread-selected,id=\"\[0-9\]+\"\r\n" set library_loaded_re "=library-loaded\[^\n\]+\"\r\n" +set breakpoint_re "=(breakpoint-created|breakpoint-deleted)\[^\n\]+\"\r\n" # # mi_gdb_exit -- exit the GDB, killing the target program if necessary @@ -978,6 +979,7 @@ proc mi_expect_stop { reason func args file line extra test } { global fullname_syntax global async global thread_selected_re + global breakpoint_re set after_stopped "" set after_reason "" @@ -1038,9 +1040,9 @@ proc mi_expect_stop { reason func args file line extra test } { set any "\[^\n\]*" - verbose -log "mi_expect_stop: expecting: \\*stopped,${r}${a}${bn}frame=\{addr=\"$hex\",func=\"$func\",args=$args,file=\"$any$file\",fullname=\"${fullname_syntax}$file\",line=\"$line\"\}$after_stopped,thread-id=\"$decimal\",stopped-threads=$any\r\n($thread_selected_re)?$prompt_re" + verbose -log "mi_expect_stop: expecting: \\*stopped,${r}${a}${bn}frame=\{addr=\"$hex\",func=\"$func\",args=$args,file=\"$any$file\",fullname=\"${fullname_syntax}$file\",line=\"$line\"\}$after_stopped,thread-id=\"$decimal\",stopped-threads=$any\r\n($thread_selected_re|$breakpoint_re)*$prompt_re" gdb_expect { - -re "\\*stopped,${r}${a}${bn}frame=\{addr=\"$hex\",func=\"$func\",args=$args,file=\"$any$file\",fullname=\"${fullname_syntax}$file\",line=\"($line)\"\}$after_stopped,thread-id=\"$decimal\",stopped-threads=$any\r\n($thread_selected_re)?$prompt_re" { + -re "\\*stopped,${r}${a}${bn}frame=\{addr=\"$hex\",func=\"$func\",args=$args,file=\"$any$file\",fullname=\"${fullname_syntax}$file\",line=\"($line)\"\}$after_stopped,thread-id=\"$decimal\",stopped-threads=$any\r\n($thread_selected_re|$breakpoint_re)*$prompt_re" { pass "$test" return $expect_out(2,string) } diff --git a/gdb/tui/tui-hooks.c b/gdb/tui/tui-hooks.c index 97b99a7..bfe9b8b 100644 --- a/gdb/tui/tui-hooks.c +++ b/gdb/tui/tui-hooks.c @@ -137,7 +137,7 @@ tui_register_changed_hook (int regno) /* Breakpoint creation hook. Update the screen to show the new breakpoint. */ static void -tui_event_create_breakpoint (int number) +tui_event_create_breakpoint (struct breakpoint *b) { tui_update_all_breakpoint_info (); } @@ -145,13 +145,13 @@ tui_event_create_breakpoint (int number) /* Breakpoint deletion hook. Refresh the screen to update the breakpoint marks. */ static void -tui_event_delete_breakpoint (int number) +tui_event_delete_breakpoint (struct breakpoint *b) { tui_update_all_breakpoint_info (); } static void -tui_event_modify_breakpoint (int number) +tui_event_modify_breakpoint (struct breakpoint *b) { tui_update_all_breakpoint_info (); } |