diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 0f0b01a728..9f9067d8ea 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,17 @@ +2012-09-18 Yao Qi + + * mi/mi-interp.c: Declare mi_tsv_created and mi_tsv_deleted. + (mi_interpreter_init): Call observer_attach_tsv_created and + observer_attach_tsv_deleted. + (mi_tsv_created, mi_tsv_deleted): New. + * tracepoint.c (delete_trace_state_variable): Call + observer_notify_tsv_deleted. + (trace_variable_command): Call observer_notify_tsv_created. + (delete_trace_variable_command): Call + observer_notify_tsv_deleted. + (create_tsv_from_upload): Call observer_notify_tsv_created. + * NEWS: Mention it. + 2012-09-18 Yao Qi * tracepoint.c (tfind_1): Call observer_notify_traceframe_changed diff --git a/gdb/NEWS b/gdb/NEWS index e28292777b..1364fdbf91 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -45,6 +45,8 @@ py [command] "=cmd-param-changed". ** Trace frame changes caused by command "tfind" are now notified using new async record "=traceframe-changed". + ** The creation and deletion of trace state variables are now notified + using new async records "=tsv-created" and "=tsv-deleted". *** Changes in GDB 7.5 diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 80e1b6069c..232337451b 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,10 @@ +2012-09-18 Yao Qi + + * gdb.texinfo (GDB/MI Async Records): Document new MI + notifications '=tsv-created' and '=tsv-deleted'. + * observer.texi (GDB Observers): New observer tsv_created and + tsv_deleted. + 2012-09-18 Yao Qi * observer.texi (GDB Observers): New observer 'traceframe_changed'. diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index ee035219f2..cd4513bc17 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -27639,6 +27639,15 @@ Reports that the trace frame was changed and its new number is @var{tfnum}. The number of the tracepoint associated with this trace frame is @var{tpnum}. +@item =tsv-created,name=@var{name},value=@var{value} +Reports that the new trace state variable @var{name} is created with +value @var{value}. + +@item =tsv-deleted,name=@var{name} +@itemx =tsv-deleted +Reports that the trace state variable @var{name} is deleted or all +trace state variables are deleted. + @item =breakpoint-created,bkpt=@{...@} @itemx =breakpoint-modified,bkpt=@{...@} @itemx =breakpoint-deleted,id=@var{number} diff --git a/gdb/doc/observer.texi b/gdb/doc/observer.texi index 42702869f8..09aa91f216 100644 --- a/gdb/doc/observer.texi +++ b/gdb/doc/observer.texi @@ -242,7 +242,16 @@ The parameter of some @code{set} commands in console are changed. This method is called after a command @code{set @var{param} @var{value}}. @var{param} is the parameter of @code{set} command, and @var{value} is the value of changed parameter. +@end deftypefun +@deftypefun void tsv_created (const char *@var{name}, LONGEST @var{value}) +The new trace state variable @var{name} is created with value +@var{value}. +@end deftypefun + +@deftypefun void tsv_deleted (const char *@var{name}) +The trace state variable @var{name} is deleted. If @var{name} is +@code{NULL}, all trace state variables are deleted. @end deftypefun @deftypefun void test_notification (int @var{somearg}) diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c index 9537aac25b..5c37bc7f6d 100644 --- a/gdb/mi/mi-interp.c +++ b/gdb/mi/mi-interp.c @@ -69,6 +69,8 @@ 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_traceframe_changed (int tfnum, int tpnum); +static void mi_tsv_created (const char *name, LONGEST value); +static void mi_tsv_deleted (const char *name); static void mi_breakpoint_created (struct breakpoint *b); static void mi_breakpoint_deleted (struct breakpoint *b); static void mi_breakpoint_modified (struct breakpoint *b); @@ -128,6 +130,8 @@ mi_interpreter_init (struct interp *interp, int top_level) observer_attach_solib_unloaded (mi_solib_unloaded); observer_attach_about_to_proceed (mi_about_to_proceed); observer_attach_traceframe_changed (mi_traceframe_changed); + observer_attach_tsv_created (mi_tsv_created); + observer_attach_tsv_deleted (mi_tsv_deleted); observer_attach_breakpoint_created (mi_breakpoint_created); observer_attach_breakpoint_deleted (mi_breakpoint_deleted); observer_attach_breakpoint_modified (mi_breakpoint_modified); @@ -537,6 +541,40 @@ mi_traceframe_changed (int tfnum, int tpnum) gdb_flush (mi->event_channel); } +/* Emit notification on creating a trace state variable. */ + +static void +mi_tsv_created (const char *name, LONGEST value) +{ + struct mi_interp *mi = top_level_interpreter_data (); + + target_terminal_ours (); + + fprintf_unfiltered (mi->event_channel, "tsv-created," + "name=\"%s\",value=\"%s\"\n", + name, plongest (value)); + + gdb_flush (mi->event_channel); +} + +/* Emit notification on deleting a trace state variable. */ + +static void +mi_tsv_deleted (const char *name) +{ + struct mi_interp *mi = top_level_interpreter_data (); + + target_terminal_ours (); + + if (name != NULL) + fprintf_unfiltered (mi->event_channel, "tsv-deleted," + "name=\"%s\"\n", name); + else + fprintf_unfiltered (mi->event_channel, "tsv-deleted\n"); + + gdb_flush (mi->event_channel); +} + /* Emit notification about a created breakpoint. */ static void diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index cba29fbb2b..21e048a2f4 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2012-09-18 Yao Qi + + * gdb.trace/mi-tsv-changed.exp: New. + 2012-09-18 Yao Qi * gdb.trace/mi-traceframe-changed.exp: New. diff --git a/gdb/testsuite/gdb.trace/mi-tsv-changed.exp b/gdb/testsuite/gdb.trace/mi-tsv-changed.exp new file mode 100644 index 0000000000..411efad86a --- /dev/null +++ b/gdb/testsuite/gdb.trace/mi-tsv-changed.exp @@ -0,0 +1,171 @@ +# Copyright 2012 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +load_lib trace-support.exp +load_lib mi-support.exp + +standard_testfile actions.c +if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \ + executable {debug nowarnings}] != "" } { + untested mi-tsv-changed.exp + return -1 +} + +# Test notifications on creating and deleting TSV. + +proc test_create_delete_tsv { } {with_test_prefix "create delete" { + global binfile + global decimal + + if [mi_gdb_start] { + return + } + mi_gdb_load ${binfile} + + mi_gdb_test "tvariable \$tvar1" \ + ".*=tsv-created,name=\"tvar1\",value=\"0\"\\\\n.*\\^done" \ + "tvariable \$tvar1" + mi_gdb_test "tvariable \$tvar2 = 45" \ + ".*=tsv-created,name=\"tvar2\",value=\"45\"\\\\n.*\\^done" \ + "tvariable \$tvar2" + + mi_gdb_test "delete tvariable \$tvar2" \ + ".*=tsv-deleted,name=\"tvar2\"\\\\n.*\\^done" \ + "delete tvariable \$tvar2" + + mi_gdb_test "delete tvariable" \ + ".*=tsv-deleted\\\\n.*\\^done" \ + "delete all tvariables" + +}} + + +# Test when GDB connects to a disconnected stub, existing TSVs in +# remote stub can be uploaded to GDB, and GDB emits MI notification +# for new uploaded TSVs. + +proc test_upload_tsv { } { with_test_prefix "upload" { + + global gdbserver_reconnect_p + global gdb_prompt + global testfile + global decimal + + set gdbserver_reconnect_p 1 + if { [info proc gdb_reconnect] == "" } { + return 0 + } + + clean_restart $testfile + if ![runto_main] then { + fail "Can't run to main" + return 0 + } + + gdb_test "tvariable \$tvar1" \ + "Trace state variable \\\$tvar1 created, with initial value 0." \ + "Create a trace state variable" + + gdb_test "tvariable \$tvar2 = 45" \ + "Trace state variable \\\$tvar2 created, with initial value 45." \ + "Create a trace state variable with initial value" + # Define a tracepoint otherwise tracing cannot be started. + gdb_test "trace main" "Tracepoint $decimal at .*" + gdb_test_no_output "tstart" "start trace experiment" + + set test "disconnect" + gdb_test_multiple "disconnect" $test { + -re "Trace is running but will stop on detach; detach anyway\\? \\(y or n\\) $" { + pass $test + + set test "disconnected" + gdb_test_multiple "y" $test { + -re "$gdb_prompt $" { + pass "$test" + } + } + } + } + + gdb_exit + + if [mi_gdb_start] { + return + } + + global srcdir + global subdir + global binfile + + mi_gdb_reinitialize_dir $srcdir/$subdir + mi_gdb_load ${binfile} + + global gdbserver_protocol + global gdbserver_gdbport + + send_gdb "47-target-select $gdbserver_protocol $gdbserver_gdbport\n" + + global mi_gdb_prompt + set tsv1_created 0 + set tsv2_created 0 + gdb_expect { + -re "=tsv-created,name=\"tvar1\",value=\"0\"" { + set tsv1_created 1 + exp_continue + } + -re "=tsv-created,name=\"tvar2\",value=\"45\"" { + set tsv2_created 1 + exp_continue + } + -re ".*${mi_gdb_prompt}" { + + } + } + + if $tsv1_created { + pass "tsv1 created" + } else { + fail "tsv1 created" + } + if $tsv2_created { + pass "tsv2 created" + } else { + fail "tsv2 created" + } + + set gdbserver_reconnect_p 0 +}} + + test_create_delete_tsv + +# Test target supports tracepoints or not. + +clean_restart $testfile + +if ![runto_main] { + fail "Can't run to main to check for trace support" + return -1 +} + +if ![gdb_target_supports_trace] { + unsupported "Current target does not support trace" + return -1; +} + +gdb_exit + +test_upload_tsv + +return 0 diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index 296999bbff..bdd6f50fc4 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -359,6 +359,9 @@ delete_trace_state_variable (const char *name) { xfree ((void *)tsv->name); VEC_unordered_remove (tsv_s, tvariables, ix); + + observer_notify_tsv_deleted (name); + return; } @@ -423,6 +426,8 @@ trace_variable_command (char *args, int from_tty) tsv = create_trace_state_variable (internalvar_name (intvar)); tsv->initial_value = initval; + observer_notify_tsv_created (tsv->name, initval); + printf_filtered (_("Trace state variable $%s " "created, with initial value %s.\n"), tsv->name, plongest (tsv->initial_value)); @@ -442,6 +447,7 @@ delete_trace_variable_command (char *args, int from_tty) if (query (_("Delete all trace state variables? "))) VEC_free (tsv_s, tvariables); dont_repeat (); + observer_notify_tsv_deleted (NULL); return; } @@ -3551,6 +3557,8 @@ create_tsv_from_upload (struct uploaded_tsv *utsv) tsv->initial_value = utsv->initial_value; tsv->builtin = utsv->builtin; + observer_notify_tsv_created (tsv->name, tsv->initial_value); + do_cleanups (old_chain); return tsv;