aboutsummaryrefslogtreecommitdiff
path: root/gdb/mi
diff options
context:
space:
mode:
authorVladimir Prus <vladimir@codesourcery.com>2011-04-27 10:17:39 +0000
committerVladimir Prus <vladimir@codesourcery.com>2011-04-27 10:17:39 +0000
commit8d3788bd590aa066f4f8383b7f8da20211e4ea9e (patch)
tree70a6d9187ed169486305055cf406ee9d0a79c08f /gdb/mi
parentb4e7b88557a669c6a400014f406fcf5a5abb5290 (diff)
downloadfsf-binutils-gdb-8d3788bd590aa066f4f8383b7f8da20211e4ea9e.zip
fsf-binutils-gdb-8d3788bd590aa066f4f8383b7f8da20211e4ea9e.tar.gz
fsf-binutils-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.c7
-rw-r--r--gdb/mi/mi-interp.c96
-rw-r--r--gdb/mi/mi-main.c10
-rw-r--r--gdb/mi/mi-main.h1
-rw-r--r--gdb/mi/mi-out.c28
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 */