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.
This commit is contained in:
Vladimir Prus
2011-04-27 10:17:39 +00:00
parent b4e7b88557
commit 8d3788bd59
18 changed files with 305 additions and 75 deletions

View File

@ -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> 2011-04-26 Aleksandar Ristovski <aristovski@qnx.com>
* nto-procfs.c (procfs_insert_hw_watchpoint): Fix prototype. * nto-procfs.c (procfs_insert_hw_watchpoint): Fix prototype.

View File

@ -32,7 +32,7 @@ extern void _initialize_annotate (void);
static void print_value_flags (struct type *); 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); void (*deprecated_annotate_signalled_hook) (void);
@ -561,7 +561,7 @@ annotate_array_section_end (void)
} }
static void static void
breakpoint_changed (int bpno) breakpoint_changed (struct breakpoint *b)
{ {
breakpoints_changed (); breakpoints_changed ();
} }

View File

@ -626,7 +626,7 @@ set_breakpoint_condition (struct breakpoint *b, char *exp,
} }
} }
breakpoints_changed (); breakpoints_changed ();
observer_notify_breakpoint_modified (b->number); observer_notify_breakpoint_modified (b);
} }
/* condition N EXP -- set break condition of breakpoint N to EXP. */ /* 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); decref_counted_command_line (&b->commands);
b->commands = alloc_counted_command_line (commands); b->commands = alloc_counted_command_line (commands);
breakpoints_changed (); breakpoints_changed ();
observer_notify_breakpoint_modified (b->number); observer_notify_breakpoint_modified (b);
} }
/* Set the internal `silent' flag on the breakpoint. Note that this /* 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; b->silent = silent;
if (old_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 /* 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; b->thread = thread;
if (old_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 /* 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; b->task = task;
if (old_task != task) if (old_task != task)
observer_notify_breakpoint_modified (b->number); observer_notify_breakpoint_modified (b);
} }
void void
@ -908,7 +908,7 @@ do_map_commands_command (struct breakpoint *b, void *data)
decref_counted_command_line (&b->commands); decref_counted_command_line (&b->commands);
b->commands = info->cmd; b->commands = info->cmd;
breakpoints_changed (); 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. */ /* See also: disable_breakpoints_in_shlibs. */
val = 0; val = 0;
bl->shlib_disabled = 1; bl->shlib_disabled = 1;
observer_notify_breakpoint_modified (bl->owner);
if (!*disabled_breaks) if (!*disabled_breaks)
{ {
fprintf_unfiltered (tmp_error_stream, fprintf_unfiltered (tmp_error_stream,
@ -4173,6 +4174,7 @@ bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid)
bs->stop = 0; bs->stop = 0;
/* Increase the hit count even though we don't stop. */ /* Increase the hit count even though we don't stop. */
++(b->hit_count); ++(b->hit_count);
observer_notify_breakpoint_modified (b);
} }
} }
} }
@ -4301,6 +4303,7 @@ bpstat_stop_status (struct address_space *aspace,
if (bs->stop) if (bs->stop)
{ {
++(b->hit_count); ++(b->hit_count);
observer_notify_breakpoint_modified (b);
/* We will stop here. */ /* We will stop here. */
if (b->disposition == disp_disable) if (b->disposition == disp_disable)
@ -4768,7 +4771,6 @@ print_one_breakpoint_location (struct breakpoint *b,
{ {
struct command_line *l; struct command_line *l;
static char bpenables[] = "nynny"; static char bpenables[] = "nynny";
struct cleanup *bkpt_chain;
int header_of_multiple = 0; int header_of_multiple = 0;
int part_of_multiple = (loc != NULL); int part_of_multiple = (loc != NULL);
@ -4787,7 +4789,6 @@ print_one_breakpoint_location (struct breakpoint *b,
loc = b->loc; loc = b->loc;
annotate_record (); annotate_record ();
bkpt_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "bkpt");
/* 1 */ /* 1 */
annotate_field (0); annotate_field (0);
@ -5052,8 +5053,6 @@ print_one_breakpoint_location (struct breakpoint *b,
else if (b->exp_string) else if (b->exp_string)
ui_out_field_string (uiout, "original-location", b->exp_string); ui_out_field_string (uiout, "original-location", b->exp_string);
} }
do_cleanups (bkpt_chain);
} }
static void static void
@ -5061,7 +5060,12 @@ print_one_breakpoint (struct breakpoint *b,
struct bp_location **last_loc, struct bp_location **last_loc,
int allflag) 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); print_one_breakpoint_location (b, NULL, 0, last_loc, allflag);
do_cleanups (bkpt_chain);
/* If this breakpoint has custom print function, /* If this breakpoint has custom print function,
it's already printed. Otherwise, print individual 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. */ internally, that's not a property exposed to user. */
if (b->loc if (b->loc
&& !is_hardware_watchpoint (b) && !is_hardware_watchpoint (b)
&& (b->loc->next || !b->loc->enabled) && (b->loc->next || !b->loc->enabled))
&& !ui_out_is_mi_like_p (uiout))
{ {
struct bp_location *loc; struct bp_location *loc;
int n = 1; int n = 1;
for (loc = b->loc; loc; loc = loc->next, ++n) 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 succeeding so we must mark the breakpoint as not inserted
to prevent future errors occurring in remove_breakpoints. */ to prevent future errors occurring in remove_breakpoints. */
loc->inserted = 0; loc->inserted = 0;
/* This may cause duplicate notifications for the same breakpoint. */
observer_notify_breakpoint_modified (b);
if (!disabled_shlib_breaks) if (!disabled_shlib_breaks)
{ {
target_terminal_ours_for_output (); 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); create_catchpoint_without_mention (gdbarch, tempflag, cond_string, ops);
mention (b); mention (b);
observer_notify_breakpoint_created (b);
update_global_location_list (1); update_global_location_list (1);
return b; 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 /* Now, we have to mention the breakpoint and update the global
location list. */ location list. */
mention (b); mention (b);
observer_notify_breakpoint_created (b);
update_global_location_list (1); update_global_location_list (1);
} }
@ -7094,12 +7109,6 @@ mention (struct breakpoint *b)
get_user_print_options (&opts); 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) if (b->ops != NULL && b->ops->print_mention != NULL)
b->ops->print_mention (b); b->ops->print_mention (b);
else else
@ -7454,12 +7463,11 @@ create_breakpoint_sal (struct gdbarch *gdbarch,
= xstrprintf ("*%s", paddress (b->loc->gdbarch, b->loc->address)); = xstrprintf ("*%s", paddress (b->loc->gdbarch, b->loc->address));
b->ops = ops; b->ops = ops;
if (internal) /* Do not mention breakpoints with a negative number, but do
/* Do not mention breakpoints with a negative number, but do notify observers. */
notify observers. */ if (!internal)
observer_notify_breakpoint_created (b->number);
else
mention (b); mention (b);
observer_notify_breakpoint_created (b);
} }
/* Remove element at INDEX_TO_REMOVE from SAL, shifting other /* 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->type == bp_hardware_breakpoint))
b->enable_state = bp_startup_disabled; b->enable_state = bp_startup_disabled;
if (internal) if (!internal)
/* Do not mention breakpoints with a negative number, /* Do not mention breakpoints with a negative number,
but do notify observers. */ but do notify observers. */
observer_notify_breakpoint_created (b->number); mention (b);
else observer_notify_breakpoint_created (b);
mention (b);
} }
if (sals.nelts > 1) if (sals.nelts > 1)
@ -8631,6 +8638,7 @@ break_range_command (char *arg, int from_tty)
discard_cleanups (cleanup_bkpt); discard_cleanups (cleanup_bkpt);
mention (b); mention (b);
observer_notify_breakpoint_created (b);
update_global_location_list (1); 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 /* Finally update the new watchpoint. This creates the locations
that should be inserted. */ that should be inserted. */
update_watchpoint (b, 1); 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. */ notify observers. */
observer_notify_breakpoint_created (b->number); if (!internal)
else
mention (b); mention (b);
observer_notify_breakpoint_created (b);
update_global_location_list (1); update_global_location_list (1);
} }
@ -9690,6 +9699,7 @@ create_ada_exception_breakpoint (struct gdbarch *gdbarch,
b->ops = ops; b->ops = ops;
mention (b); mention (b);
observer_notify_breakpoint_created (b);
update_global_location_list (1); update_global_location_list (1);
} }
@ -10496,7 +10506,7 @@ delete_breakpoint (struct breakpoint *bpt)
bpt->related_breakpoint = bpt; bpt->related_breakpoint = bpt;
} }
observer_notify_breakpoint_deleted (bpt->number); observer_notify_breakpoint_deleted (bpt);
if (breakpoint_chain == bpt) if (breakpoint_chain == bpt)
breakpoint_chain = bpt->next; breakpoint_chain = bpt->next;
@ -10807,6 +10817,33 @@ update_static_tracepoint (struct breakpoint *b, struct symtab_and_line sal)
return 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) /* 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 based on SALS and SALS_END. If SALS_END.NELTS is not zero, then B is
a ranged breakpoint. */ 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); update_global_location_list (1);
} }
@ -11264,7 +11304,7 @@ set_ignore_count (int bptnum, int count, int from_tty)
count, bptnum); count, bptnum);
} }
breakpoints_changed (); breakpoints_changed ();
observer_notify_breakpoint_modified (b->number); observer_notify_breakpoint_modified (b);
return; return;
} }
@ -11419,7 +11459,7 @@ disable_breakpoint (struct breakpoint *bpt)
update_global_location_list (0); update_global_location_list (0);
observer_notify_breakpoint_modified (bpt->number); observer_notify_breakpoint_modified (bpt);
} }
/* A callback for map_breakpoint_numbers that calls /* 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); update_global_location_list (1);
breakpoints_changed (); breakpoints_changed ();
observer_notify_breakpoint_modified (bpt->number); observer_notify_breakpoint_modified (bpt);
} }

View File

@ -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 absent, it means the library was unloaded in the context of all present
thread groups. 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 @end table
@node GDB/MI Frame Information @node GDB/MI Frame Information

View File

@ -159,19 +159,18 @@ thread was resume, and may be RESUME_ALL if all threads are resumed.
The target is about to be proceeded. The target is about to be proceeded.
@end deftypefun @end deftypefun
@deftypefun void breakpoint_created (int @var{bpnum}) @deftypefun void breakpoint_created (struct breakpoint *@var{b})
A new breakpoint has been created. The argument @var{bpnum} is the A new breakpoint @var{b} has been created.
number of the newly-created breakpoint.
@end deftypefun @end deftypefun
@deftypefun void breakpoint_deleted (int @var{bpnum}) @deftypefun void breakpoint_deleted (struct breakpoint *@var{b})
A breakpoint has been destroyed. The argument @var{bpnum} is the A breakpoint has been destroyed. The argument @var{b} is the
number of the newly-destroyed breakpoint. pointer to the destroyed breakpoint.
@end deftypefun @end deftypefun
@deftypefun void breakpoint_modified (int @var{bpnum}) @deftypefun void breakpoint_modified (struct breakpoint *@var{b})
A breakpoint has been modified in some way. The argument @var{bpnum} A breakpoint has been modified in some way. The argument @var{b}
is the number of the modified breakpoint. is the modified breakpoint.
@end deftypefun @end deftypefun
@deftypefun void tracepoint_created (int @var{tpnum}) @deftypefun void tracepoint_created (int @var{tpnum})

View File

@ -29,6 +29,7 @@
#include "gdb.h" #include "gdb.h"
#include "exceptions.h" #include "exceptions.h"
#include "observer.h" #include "observer.h"
#include "mi-main.h"
enum enum
{ {
@ -46,10 +47,10 @@ static int mi_can_breakpoint_notify;
/* Output a single breakpoint, when allowed. */ /* Output a single breakpoint, when allowed. */
static void static void
breakpoint_notify (int b) breakpoint_notify (struct breakpoint *b)
{ {
if (mi_can_breakpoint_notify) if (mi_can_breakpoint_notify)
gdb_breakpoint_query (uiout, b, NULL); gdb_breakpoint_query (uiout, b->number, NULL);
} }
enum bp_type enum bp_type
@ -146,8 +147,6 @@ mi_cmd_break_insert (char *command, char **argv, int argc)
if (! mi_breakpoint_observers_installed) if (! mi_breakpoint_observers_installed)
{ {
observer_attach_breakpoint_created (breakpoint_notify); observer_attach_breakpoint_created (breakpoint_notify);
observer_attach_breakpoint_modified (breakpoint_notify);
observer_attach_breakpoint_deleted (breakpoint_notify);
mi_breakpoint_observers_installed = 1; mi_breakpoint_observers_installed = 1;
} }

View File

@ -35,6 +35,7 @@
#include "observer.h" #include "observer.h"
#include "gdbthread.h" #include "gdbthread.h"
#include "solist.h" #include "solist.h"
#include "gdb.h"
/* These are the interpreter setup, etc. functions for the MI interpreter */ /* These are the interpreter setup, etc. functions for the MI interpreter */
static void mi_execute_command_wrapper (char *cmd); 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_loaded (struct so_list *solib);
static void mi_solib_unloaded (struct so_list *solib); static void mi_solib_unloaded (struct so_list *solib);
static void mi_about_to_proceed (void); 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); 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_loaded (mi_solib_loaded);
observer_attach_solib_unloaded (mi_solib_unloaded); observer_attach_solib_unloaded (mi_solib_unloaded);
observer_attach_about_to_proceed (mi_about_to_proceed); 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 /* The initial inferior is created before this function is called, so we
need to report it explicitly. Use iteration in case future version need to report it explicitly. Use iteration in case future version
@ -445,6 +452,95 @@ mi_about_to_proceed (void)
mi_proceeded = 1; 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 static int
mi_output_running_pid (struct thread_info *info, void *arg) mi_output_running_pid (struct thread_info *info, void *arg)
{ {

View File

@ -2088,8 +2088,16 @@ mi_cmd_execute (struct mi_parse *parse)
current_context = 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) 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) else if (parse->cmd->cli.cmd != 0)
{ {
/* FIXME: DELETE THIS. */ /* FIXME: DELETE THIS. */

View File

@ -33,6 +33,7 @@ extern char *current_token;
extern int running_result_record_printed; extern int running_result_record_printed;
extern int mi_proceeded; extern int mi_proceeded;
extern int mi_suppress_breakpoint_notifications;
#endif #endif

View File

@ -30,6 +30,7 @@ struct ui_out_data
int suppress_output; int suppress_output;
int mi_version; int mi_version;
struct ui_file *buffer; struct ui_file *buffer;
struct ui_file *original_buffer;
}; };
typedef struct ui_out_data mi_out_data; 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); ATTRIBUTE_PRINTF (3, 0);
static void mi_wrap_hint (struct ui_out *uiout, char *identstring); static void mi_wrap_hint (struct ui_out *uiout, char *identstring);
static void mi_flush (struct ui_out *uiout); 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 */ /* This is the MI ui-out implementation functions vector */
@ -86,7 +88,7 @@ struct ui_out_impl mi_ui_out_impl =
mi_message, mi_message,
mi_wrap_hint, mi_wrap_hint,
mi_flush, mi_flush,
NULL, mi_redirect,
1, /* Needs MI hacks. */ 1, /* Needs MI hacks. */
}; };
@ -210,11 +212,6 @@ void
mi_field_skip (struct ui_out *uiout, int fldno, int width, mi_field_skip (struct ui_out *uiout, int fldno, int width,
enum ui_align alignment, const char *fldname) 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 /* 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); 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 */ /* local functions */
/* access to ui_out format private members */ /* access to ui_out format private members */

View File

@ -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 /* Callback that is used when a breakpoint is created. This function
will create a new Python breakpoint object. */ will create a new Python breakpoint object. */
static void static void
gdbpy_breakpoint_created (int num) gdbpy_breakpoint_created (struct breakpoint *bp)
{ {
breakpoint_object *newbp; breakpoint_object *newbp;
struct breakpoint *bp = NULL;
PyGILState_STATE state; PyGILState_STATE state;
bp = get_breakpoint (num);
if (! bp)
return;
if (num < 0 && bppy_pending_object == NULL) if (num < 0 && bppy_pending_object == NULL)
return; return;
@ -813,7 +808,7 @@ gdbpy_breakpoint_created (int num)
newbp = PyObject_New (breakpoint_object, &breakpoint_object_type); newbp = PyObject_New (breakpoint_object, &breakpoint_object_type);
if (newbp) if (newbp)
{ {
newbp->number = num; newbp->number = bp->number;
newbp->bp = bp; newbp->bp = bp;
newbp->bp->py_bp_object = newbp; newbp->bp->py_bp_object = newbp;
Py_INCREF (newbp); Py_INCREF (newbp);
@ -832,8 +827,9 @@ gdbpy_breakpoint_created (int num)
/* Callback that is used when a breakpoint is deleted. This will /* Callback that is used when a breakpoint is deleted. This will
invalidate the corresponding Python object. */ invalidate the corresponding Python object. */
static void static void
gdbpy_breakpoint_deleted (int num) gdbpy_breakpoint_deleted (struct breakpoint *b)
{ {
int num = b->number;
PyGILState_STATE state; PyGILState_STATE state;
struct breakpoint *bp = NULL; struct breakpoint *bp = NULL;
breakpoint_object *bp_obj; breakpoint_object *bp_obj;

View File

@ -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> 2011-04-25 Jan Kratochvil <jan.kratochvil@redhat.com>
* gdb.base/gdbindex-stabs-dwarf.c: New file. * gdb.base/gdbindex-stabs-dwarf.c: New file.

View File

@ -108,7 +108,7 @@ mi_execute_to "exec-continue" "breakpoint-hit" "callee4" "" ".*basics.c" $line_c
# {.*=breakpoint-delete,number=\"2\".*\^done} \ # {.*=breakpoint-delete,number=\"2\".*\^done} \
# "-interpreter-exec console \"delete 2\"" # "-interpreter-exec console \"delete 2\""
mi_gdb_test "100-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\"" "-interpreter-exec console \"delete 2\""
# NOTE: cagney/2003-02-03: Not yet. # NOTE: cagney/2003-02-03: Not yet.

View File

@ -59,7 +59,7 @@ proc test_watchpoint_creation_and_listing {type} {
"break-watch operation" "break-watch operation"
mi_gdb_test "222-break-list" \ 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" "list of watchpoints"
} }

View File

@ -108,7 +108,7 @@ mi_execute_to "exec-continue" "breakpoint-hit" "callee4" "" ".*basics.c" $line_c
# {.*=breakpoint-delete,number=\"2\".*\^done} \ # {.*=breakpoint-delete,number=\"2\".*\^done} \
# "-interpreter-exec console \"delete 2\"" # "-interpreter-exec console \"delete 2\""
mi_gdb_test "100-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\"" "-interpreter-exec console \"delete 2\""
# NOTE: cagney/2003-02-03: Not yet. # NOTE: cagney/2003-02-03: Not yet.

View File

@ -59,7 +59,7 @@ proc test_watchpoint_creation_and_listing {type} {
"break-watch operation" "break-watch operation"
mi_gdb_test "222-break-list" \ 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" "list of watchpoints"
} }

View File

@ -32,6 +32,7 @@ set MIFLAGS "-i=mi"
set thread_selected_re "=thread-selected,id=\"\[0-9\]+\"\r\n" set thread_selected_re "=thread-selected,id=\"\[0-9\]+\"\r\n"
set library_loaded_re "=library-loaded\[^\n\]+\"\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 # 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 fullname_syntax
global async global async
global thread_selected_re global thread_selected_re
global breakpoint_re
set after_stopped "" set after_stopped ""
set after_reason "" set after_reason ""
@ -1038,9 +1040,9 @@ proc mi_expect_stop { reason func args file line extra test } {
set any "\[^\n\]*" 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 { 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" pass "$test"
return $expect_out(2,string) return $expect_out(2,string)
} }

View File

@ -137,7 +137,7 @@ tui_register_changed_hook (int regno)
/* Breakpoint creation hook. /* Breakpoint creation hook.
Update the screen to show the new breakpoint. */ Update the screen to show the new breakpoint. */
static void static void
tui_event_create_breakpoint (int number) tui_event_create_breakpoint (struct breakpoint *b)
{ {
tui_update_all_breakpoint_info (); tui_update_all_breakpoint_info ();
} }
@ -145,13 +145,13 @@ tui_event_create_breakpoint (int number)
/* Breakpoint deletion hook. /* Breakpoint deletion hook.
Refresh the screen to update the breakpoint marks. */ Refresh the screen to update the breakpoint marks. */
static void static void
tui_event_delete_breakpoint (int number) tui_event_delete_breakpoint (struct breakpoint *b)
{ {
tui_update_all_breakpoint_info (); tui_update_all_breakpoint_info ();
} }
static void static void
tui_event_modify_breakpoint (int number) tui_event_modify_breakpoint (struct breakpoint *b)
{ {
tui_update_all_breakpoint_info (); tui_update_all_breakpoint_info ();
} }