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 /gdb/mi | |
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.
Diffstat (limited to 'gdb/mi')
-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 |
5 files changed, 131 insertions, 11 deletions
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 */ |