* [PATCH 3/4] MI notification on trace started/stopped:basic
2013-12-12 13:51 [PATCH 0/4 V7] MI notification on trace started/stopped Yao Qi
@ 2013-12-12 13:51 ` Yao Qi
2013-12-12 13:51 ` [PATCH 4/4] MI notification on trace stop: triggered by remote Yao Qi
` (3 subsequent siblings)
4 siblings, 0 replies; 11+ messages in thread
From: Yao Qi @ 2013-12-12 13:51 UTC (permalink / raw)
To: gdb-patches
Hi,
This patch adds the notifications of 'trace-started' and
'trace-stopped', which are emitted when trace is started or stopped by
command 'tstart' and 'tstop', so that when trace is started or stopped
in console, MI frontend can be notified.
This patch doesn't handle the case the trace is stopped due to some
reasons in remote side, because we don't have any existing RSP
notification yet. This issue will be addressed in another post.
Regression tested on x86_64-linux with native and gdbserver. Is it
OK?
The documentation patch was approved by Eli here
<http://sourceware.org/ml/gdb-patches/2013-02/msg00441.html>
gdb/doc:
* gdb.texinfo (GDB/MI Async Records): New MI notifications
'trace-changed'.
* observer.texi (GDB Observers): New observer 'trace-changed'
gdb:
* mi/mi-cmds.c (mi_cmds): Adjust for commands 'trace-start'
and 'trace-stop'.
* mi/mi-interp.c: Declare mi_trace_changed.
(mi_interpreter_init): Install mi_trace_changed to observer.
(mi_trace_changed): New.
* mi/mi-main.h (struct mi_suppress_notification) <trace>:
New field.
* tracepoint.c (start_tracing): Call
observer_notify_trace_changed.
(stop_tracing): Call observer_notify_trace_changed.
* NEWS: Mention it.
gdb/testsuite/
* gdb.mi/mi-trace-changed.exp: New.
---
gdb/NEWS | 2 +
gdb/doc/gdb.texinfo | 4 ++
gdb/doc/observer.texi | 6 ++
gdb/mi/mi-cmds.c | 6 ++-
gdb/mi/mi-interp.c | 22 ++++++++
gdb/mi/mi-main.h | 2 +
gdb/testsuite/gdb.trace/mi-trace-changed.exp | 74 ++++++++++++++++++++++++++
gdb/tracepoint.c | 4 ++
8 files changed, 118 insertions(+), 2 deletions(-)
create mode 100644 gdb/testsuite/gdb.trace/mi-trace-changed.exp
diff --git a/gdb/NEWS b/gdb/NEWS
index eff057f..0b9291d 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -174,6 +174,8 @@ show code-cache
** The -trace-save MI command can optionally save trace buffer in Common
Trace Format now.
+ ** The start and stop of trace are now notified using new async records
+ "=trace-started" and "=trace-stopped".
** The new command -dprintf-insert sets a dynamic printf breakpoint.
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index e91c01e..0538b53 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -29638,6 +29638,10 @@ written in an inferior. The @var{id} is the identifier of the
thread group corresponding to the affected inferior. The optional
@code{type="code"} part is reported if the memory written to holds
executable code.
+
+@item =trace-started
+@itemx =trace-stopped
+Reports that trace was started or stopped.
@end table
@node GDB/MI Breakpoint Information
diff --git a/gdb/doc/observer.texi b/gdb/doc/observer.texi
index f753965..450d732 100644
--- a/gdb/doc/observer.texi
+++ b/gdb/doc/observer.texi
@@ -253,6 +253,12 @@ The trace state variable @var{tsv} is deleted. If @var{tsv} is
The trace state value @var{tsv} is modified.
@end deftypefun
+@deftypefun void trace_changed (int @var{started})
+The status of trace in @value{GDBN} has changed. The trace is started
+if @var{started} is non-zero, and the trace is stopped if
+@var{started} is zero.
+@end deftypefun
+
@deftypefun void test_notification (int @var{somearg})
This observer is used for internal testing. Do not use.
See testsuite/gdb.gdb/observer.exp.
diff --git a/gdb/mi/mi-cmds.c b/gdb/mi/mi-cmds.c
index 58a8b89..eaf42ff 100644
--- a/gdb/mi/mi-cmds.c
+++ b/gdb/mi/mi-cmds.c
@@ -158,9 +158,11 @@ static struct mi_cmd mi_cmds[] =
mi_cmd_trace_frame_collected),
DEF_MI_CMD_MI ("trace-list-variables", mi_cmd_trace_list_variables),
DEF_MI_CMD_MI ("trace-save", mi_cmd_trace_save),
- DEF_MI_CMD_MI ("trace-start", mi_cmd_trace_start),
+ DEF_MI_CMD_MI_1 ("trace-start", mi_cmd_trace_start,
+ &mi_suppress_notification.trace),
DEF_MI_CMD_MI ("trace-status", mi_cmd_trace_status),
- DEF_MI_CMD_MI ("trace-stop", mi_cmd_trace_stop),
+ DEF_MI_CMD_MI_1 ("trace-stop", mi_cmd_trace_stop,
+ &mi_suppress_notification.trace),
DEF_MI_CMD_MI ("var-assign", mi_cmd_var_assign),
DEF_MI_CMD_MI ("var-create", mi_cmd_var_create),
DEF_MI_CMD_MI ("var-delete", mi_cmd_var_delete),
diff --git a/gdb/mi/mi-interp.c b/gdb/mi/mi-interp.c
index 2ed1726..7a564d2 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -64,6 +64,7 @@ static void mi_inferior_appeared (struct inferior *inf);
static void mi_inferior_exit (struct inferior *inf);
static void mi_inferior_removed (struct inferior *inf);
static void mi_on_resume (ptid_t ptid);
+static void mi_trace_changed (int started);
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);
@@ -129,6 +130,7 @@ mi_interpreter_init (struct interp *interp, int top_level)
observer_attach_record_changed (mi_record_changed);
observer_attach_normal_stop (mi_on_normal_stop);
observer_attach_target_resumed (mi_on_resume);
+ observer_attach_trace_changed (mi_trace_changed);
observer_attach_solib_loaded (mi_solib_loaded);
observer_attach_solib_unloaded (mi_solib_unloaded);
observer_attach_about_to_proceed (mi_about_to_proceed);
@@ -582,6 +584,26 @@ mi_tsv_modified (const struct trace_state_variable *tsv)
gdb_flush (mi->event_channel);
}
+/* Emit notification on trace was started or stopped. */
+
+static void
+mi_trace_changed (int started)
+{
+ struct mi_interp *mi = top_level_interpreter_data ();
+
+ if (mi_suppress_notification.trace)
+ return;
+
+ target_terminal_ours ();
+
+ if (started)
+ fprintf_unfiltered (mi->event_channel, "trace-started\n");
+ else
+ fprintf_unfiltered (mi->event_channel, "trace-stopped\n");
+
+ gdb_flush (mi->event_channel);
+}
+
/* Emit notification about a created breakpoint. */
static void
diff --git a/gdb/mi/mi-main.h b/gdb/mi/mi-main.h
index d75526a..0903d60 100644
--- a/gdb/mi/mi-main.h
+++ b/gdb/mi/mi-main.h
@@ -43,6 +43,8 @@ struct mi_suppress_notification
int traceframe;
/* Memory changed notification suppressed? */
int memory;
+ /* Trace started/stopped notification suppressed? */
+ int trace;
};
extern struct mi_suppress_notification mi_suppress_notification;
diff --git a/gdb/testsuite/gdb.trace/mi-trace-changed.exp b/gdb/testsuite/gdb.trace/mi-trace-changed.exp
new file mode 100644
index 0000000..fbd6fe7
--- /dev/null
+++ b/gdb/testsuite/gdb.trace/mi-trace-changed.exp
@@ -0,0 +1,74 @@
+# Copyright 2013 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 <http://www.gnu.org/licenses/>.
+
+load_lib mi-support.exp
+load_lib trace-support.exp
+
+standard_testfile status-stop.c
+
+if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \
+ executable {debug nowarnings}] != "" } {
+ untested mi-record-changed.exp
+ return -1
+}
+
+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 "target does not support trace"
+ return -1;
+}
+
+gdb_exit
+
+# Verify that MI notification '=trace-started' and '=trace-stopped' are
+# emitted for normal 'tstart' and 'tstart' command.
+
+proc test_normal_tstart_stop { } {
+ with_test_prefix "tstart_tstop" {
+ global decimal hex
+
+ if [mi_gdb_start] {
+ return
+ }
+ mi_run_to_main
+
+ mi_gdb_test "-break-insert -a main" {.*\^done,bkpt=.*} \
+ "insert tracepoint on main"
+
+ # No =trace-started notification.
+ mi_gdb_test "-trace-start" "-trace-start\r\n=breakpoint-modified\[^\n\]+\r\n\\^done" \
+ "start trace without notification"
+ mi_gdb_test "-trace-stop" \
+ "-trace-stop\r\n\\^done,stop-reason=\"request\".*" \
+ "stop trace without notification"
+
+ mi_gdb_test "tstart" \
+ ".*=trace-started.*\\^done" "start trace notification"
+ mi_gdb_test "tstop" ".*=trace-stopped\\\\n\r\n\\^done" \
+ "stop trace notification"
+
+ mi_gdb_exit
+ }
+}
+
+test_normal_tstart_stop
+
+return 0
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index f30282b..bf48038 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -1898,6 +1898,8 @@ start_tracing (char *notes)
/* Now insert traps and begin collecting data. */
target_trace_start ();
+ observer_notify_trace_changed (1);
+
/* Reset our local state. */
trace_reset_local_state ();
current_trace_status()->running = 1;
@@ -1980,6 +1982,8 @@ stop_tracing (char *note)
/* Should change in response to reply? */
current_trace_status ()->running = 0;
+
+ observer_notify_trace_changed (0);
}
/* tstatus command */
--
1.7.7.6
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 1/4] Query supported notifications by qSupported
2013-12-12 13:51 [PATCH 0/4 V7] MI notification on trace started/stopped Yao Qi
2013-12-12 13:51 ` [PATCH 3/4] MI notification on trace started/stopped:basic Yao Qi
2013-12-12 13:51 ` [PATCH 4/4] MI notification on trace stop: triggered by remote Yao Qi
@ 2013-12-12 13:51 ` Yao Qi
2013-12-18 14:11 ` Pedro Alves
2013-12-12 13:51 ` [PATCH 2/4] async remote notification 'Trace' Yao Qi
2013-12-18 14:09 ` [PATCH 0/4 V7] MI notification on trace started/stopped Pedro Alves
4 siblings, 1 reply; 11+ messages in thread
From: Yao Qi @ 2013-12-12 13:51 UTC (permalink / raw)
To: gdb-patches
V7: remove annex.
V6: the supported flag of each notification is saved in
'struct remote_notif_state' in GDB. In GDBserver, the supported flag
is still associated with each notification.
As we we adding more notifications, both GDB and GDBserver
has to know what notifications are supported in the other
side. This is what this patch does. When GDB connects to GDBserver,
it will happen:
--> qSupported:XXX;notifications=N1,N2.N3
(GDB supports notification N1, N2 and N3)
<-- XXX;Notifications=N1,N2,N4
(GDBsever supports notification N1, N2 and N4)
after this, GDB knows what notifications GDBserver is able to send,
and GDBservers knows what notifications GDB doesn't support.
gdb/gdbserver:
* notif.c (notif_qsupported_record): New function.
(notif_qsupported_reply): New function.
* notif.h (struct notif_server) <supported>: New field.
(notif_qsupported_reply): Declare.
(notif_qsupported_record): Declare.
* server.c (notif_annex_stop): Update.
(handle_query): Call notif_qsupported_record and
notif_qsupported_reply.
gdb:
* remote-notif.c (remote_notif_ack): Add argument 'state'.
Callers update.
(remote_notif_parse): Likewise.
(remote_notif_qsupported): New function.
(remote_notif_qsupported_reply): New function.
(remote_notif_state_allocate): Initialize field 'supported'.
(remote_notif_state_xfree): Free field 'supported'.
* remote-notif.h (struct remote_notif_state) <supported>: New
field.
(remote_notif_ack, remote_notif_parse): Update declarations.
(remote_notif_qsupported): Declare.
(remote_notif_qsupported_reply): Declare.
* remote.c (PACKET_notifications): New enum.
(remote_notifications_feature): New function.
(remote_protocol_features): Add new element.
(remote_query_supported): Call remote_notif_qsupported and
append supported notifications to qSupported feature.
gdb/doc:
* gdb.texinfo (General Query Packets): Document the new feature
'notifications' of 'qSupported' packet.
Document the new feature in qSupported reply.
---
gdb/doc/gdb.texinfo | 18 ++++++++
gdb/gdbserver/notif.c | 83 ++++++++++++++++++++++++++++++++++++
gdb/gdbserver/notif.h | 5 ++
gdb/gdbserver/server.c | 16 +++++++-
gdb/remote-notif.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++-
gdb/remote-notif.h | 14 ++++++-
gdb/remote.c | 29 +++++++++++--
7 files changed, 265 insertions(+), 9 deletions(-)
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 7dfa9f6..e76f73b 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -39383,6 +39383,14 @@ description.
This feature indicates whether @value{GDBN} supports the
@samp{qRelocInsn} packet (@pxref{Tracepoint Packets,,Relocate
instruction reply packet}).
+
+@item notifications
+@anchor{notifications feature}
+This feature indicates that @value{GDBN} supports the async remote
+notifications (@pxref{Notification Packets}). If the stub sees
+@samp{notifications=} with a string of name of supported
+notifications, separated by commas, it will report notifications
+supported by the stub.
@end table
Stubs should ignore any unknown values for
@@ -39601,6 +39609,11 @@ These are the currently defined stub features and their properties:
@tab @samp{-}
@tab No
+@item @samp{Notifications}
+@tab Yes
+@tab @samp{-}
+@tab No
+
@end multitable
These are the currently defined stub features, in more detail:
@@ -39768,6 +39781,11 @@ See @ref{Bytecode Descriptions} for details about the bytecode.
The remote stub supports running a breakpoint's command list itself,
rather than reporting the hit to @value{GDBN}.
+@item Notifications=@var{name}@r{[},@var{name}@r{]}@dots{}
+@cindex notifications, in remote protocol
+The remote stub supports a string of notifications. @var{name} is
+the name of the notification.
+
@item Qbtrace:off
The remote stub understands the @samp{Qbtrace:off} packet.
diff --git a/gdb/gdbserver/notif.c b/gdb/gdbserver/notif.c
index 6da2c5c..4766bba 100644
--- a/gdb/gdbserver/notif.c
+++ b/gdb/gdbserver/notif.c
@@ -159,6 +159,89 @@ notif_event_xfree (struct notif_event *event)
xfree (event);
}
+/* Record the notifications supported by GDB. GDB_NOTIFICATIONS is a
+ string about notifications GDB supports. */
+
+void
+notif_qsupported_record (char *gdb_notifications)
+{
+ const char *p = gdb_notifications;
+
+ while (1)
+ {
+ char *end = strchr (p, ',');
+ struct notif_server *nc = NULL;
+
+ if (end == NULL)
+ {
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE (notifs); i++)
+ {
+ if (strcmp (p, notifs[i]->notif_name) == 0)
+ {
+ nc = notifs[i];
+ break;
+ }
+ }
+ }
+ else
+ {
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE (notifs); i++)
+ {
+ if (strncmp (p, notifs[i]->notif_name, end - p) == 0
+ && strlen (notifs[i]->notif_name) == (end - p))
+ {
+ nc = notifs[i];
+ break;
+ }
+ }
+
+ p = end + 1;
+ }
+
+ /* Notification NC is supported. */
+ if (nc != NULL)
+ nc->supported = 1;
+
+ if (end == NULL)
+ break;
+ }
+}
+
+/* Return a string about notifications that GDBserver supports.
+ Return NULL if no notification is supported. The caller is
+ responsible to free the returned string. Suppose GDBserver
+ supports notifications N1, N2, and N3. The returned string is
+ "N1,N2,N3". */
+
+char *
+notif_qsupported_reply (void)
+{
+ int i;
+ char * p = NULL;
+
+#define BUF_LEN 128
+
+ for (i = 0; i < ARRAY_SIZE (notifs); i++)
+ {
+ struct notif_server *nb = notifs[i];
+
+ if (p == NULL)
+ {
+ p = xmalloc (BUF_LEN);
+ strcpy (p, nb->notif_name);
+ }
+ else
+ xsnprintf (p + strlen (p), BUF_LEN - strlen (p), ",%s",
+ nb->notif_name);
+ }
+
+ return p;
+}
+
void
initialize_notif (void)
{
diff --git a/gdb/gdbserver/notif.h b/gdb/gdbserver/notif.h
index c714e7b..80e084e 100644
--- a/gdb/gdbserver/notif.h
+++ b/gdb/gdbserver/notif.h
@@ -52,12 +52,17 @@ typedef struct notif_server
/* Write event EVENT to OWN_BUF. */
void (*write) (struct notif_event *event, char *own_buf);
+
+ /* This notification is supported by GDB or not. */
+ int supported;
} *notif_server_p;
extern struct notif_server notif_stop;
int handle_notif_ack (char *own_buf, int packet_len);
void notif_write_event (struct notif_server *notif, char *own_buf);
+char* notif_qsupported_reply (void);
+void notif_qsupported_record (char *gdb_notifications);
void notif_push (struct notif_server *np, struct notif_event *event);
void notif_event_enque (struct notif_server *notif,
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index e0af785..d79c8db 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -187,7 +187,7 @@ vstop_notif_reply (struct notif_event *event, char *own_buf)
struct notif_server notif_stop =
{
- "vStopped", "Stop", NULL, vstop_notif_reply,
+ "vStopped", "Stop", NULL, vstop_notif_reply, 1,
};
static int
@@ -1731,6 +1731,11 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
/* GDB supports relocate instruction requests. */
gdb_supports_qRelocInsn = 1;
}
+ else if (strncmp (p, "notifications=", 14) == 0)
+ {
+ /* Record what notifications GDB supports. */
+ notif_qsupported_record (&p[14]);
+ }
else
target_process_qsupported (p);
@@ -1820,6 +1825,15 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
strcat (own_buf, ";qXfer:btrace:read+");
}
+ p = notif_qsupported_reply ();
+
+ if (p != NULL)
+ {
+ strcat (own_buf, ";Notifications=");
+ strcat (own_buf, p);
+ xfree (p);
+ }
+
return;
}
diff --git a/gdb/remote-notif.c b/gdb/remote-notif.c
index 163979d..4685d30 100644
--- a/gdb/remote-notif.c
+++ b/gdb/remote-notif.c
@@ -59,7 +59,8 @@ static void do_notif_event_xfree (void *arg);
acknowledge. */
void
-remote_notif_ack (struct notif_client *nc, char *buf)
+remote_notif_ack (struct notif_client *nc,
+ struct remote_notif_state *state, char *buf)
{
struct notif_event *event = nc->alloc_event ();
struct cleanup *old_chain
@@ -78,7 +79,8 @@ remote_notif_ack (struct notif_client *nc, char *buf)
/* Parse the BUF for the expected notification NC. */
struct notif_event *
-remote_notif_parse (struct notif_client *nc, char *buf)
+remote_notif_parse (struct notif_client *nc,
+ struct remote_notif_state *state, char *buf)
{
struct notif_event *event = nc->alloc_event ();
struct cleanup *old_chain
@@ -158,7 +160,7 @@ handle_notification (struct remote_notif_state *state, char *buf)
else
{
struct notif_event *event
- = remote_notif_parse (nc, buf + strlen (nc->name) + 1);
+ = remote_notif_parse (nc, state, buf + strlen (nc->name) + 1);
/* Be careful to only set it after parsing, since an error
may be thrown then. */
@@ -234,6 +236,99 @@ do_notif_event_xfree (void *arg)
notif_event_xfree (arg);
}
+/* Return a string about notifications that GDB supports. The caller
+ is responsible to free the returned string. Suppose GDB supports
+ notifications N1, N2, and N3. The returned string is
+ "N1,N2,N3". */
+
+char *
+remote_notif_qsupported (void)
+{
+ int i;
+ char * p = NULL;
+
+#define BUF_LEN 128
+
+ for (i = 0; i < ARRAY_SIZE (notifs); i++)
+ {
+ struct notif_client *nb = notifs[i];
+
+ if (p == NULL)
+ {
+ p = xmalloc (BUF_LEN);
+ strcpy (p, nb->name);
+ }
+ else
+ xsnprintf (p + strlen (p), BUF_LEN - strlen (p), ",%s",
+ nb->name);
+ }
+
+ return p;
+}
+
+/* Parse the qSupported reply REPLY from the remote stub and enable
+ notifications if the remote stub supports. */
+
+void
+remote_notif_qsupported_reply (const char *reply,
+ struct remote_notif_state *state)
+{
+ const char *p = reply;
+
+ if (notif_debug)
+ fprintf_unfiltered (gdb_stdlog,
+ "notif: stub supported notifications '%s'\n",
+ reply);
+
+ while (1)
+ {
+ char *end = strchr (p, ',');
+ struct notif_client *nc = NULL;
+
+ if (end == NULL)
+ {
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE (notifs); i++)
+ {
+ if (strcmp (p, notifs[i]->name) == 0)
+ {
+ nc = notifs[i];
+ break;
+ }
+ }
+ }
+ else
+ {
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE (notifs); i++)
+ {
+ if (strncmp (p, notifs[i]->name, end - p) == 0
+ && strlen (notifs[i]->name) == (end - p))
+ {
+ nc = notifs[i];
+ break;
+ }
+ }
+
+ p = end + 1;
+ }
+
+ if (nc != NULL)
+ {
+ /* Notification NC is supported. */
+ state->supported[nc->id] = 1;
+ if (notif_debug)
+ fprintf_unfiltered (gdb_stdlog, "notif: '%s' is supported\n",
+ nc->name);
+ }
+
+ if (end == NULL)
+ break;
+ }
+}
+
/* Return an allocated remote_notif_state. */
struct remote_notif_state *
@@ -249,6 +344,12 @@ remote_notif_state_allocate (void)
= create_async_event_handler (remote_async_get_pending_events_handler,
notif_state);
+ notif_state->supported = xcalloc (ARRAY_SIZE (notifs), sizeof (int));
+
+ /* Even the remote stub doesn't understand
+ 'qSupported:notifications=', it may still support notification
+ stop if it supports non-stop. */
+ notif_state->supported[notif_client_stop.id] = 1;
return notif_state;
}
@@ -268,6 +369,8 @@ remote_notif_state_xfree (struct remote_notif_state *state)
for (i = 0; i < REMOTE_NOTIF_LAST; i++)
notif_event_xfree (state->pending_event[i]);
+ xfree (state->supported);
+
xfree (state);
}
diff --git a/gdb/remote-notif.h b/gdb/remote-notif.h
index e5ebbc7..14984b4 100644
--- a/gdb/remote-notif.h
+++ b/gdb/remote-notif.h
@@ -96,10 +96,17 @@ struct remote_notif_state
remote.c:remote_notif_pending_replies). */
struct notif_event *pending_event[REMOTE_NOTIF_LAST];
+
+ /* Each element indicates the notification is supported by the
+ remote stub or not. The index is the field 'id' in
+ 'struct notif_client'. */
+ int *supported;
};
-void remote_notif_ack (struct notif_client *nc, char *buf);
+void remote_notif_ack (struct notif_client *nc,
+ struct remote_notif_state *state, char *buf);
struct notif_event *remote_notif_parse (struct notif_client *nc,
+ struct remote_notif_state *state,
char *buf);
void notif_event_xfree (struct notif_event *event);
@@ -112,6 +119,11 @@ void remote_notif_process (struct remote_notif_state *state,
struct remote_notif_state *remote_notif_state_allocate (void);
void remote_notif_state_xfree (struct remote_notif_state *state);
+
+char * remote_notif_qsupported (void);
+void remote_notif_qsupported_reply (const char *reply,
+ struct remote_notif_state *state);
+
extern struct notif_client notif_client_stop;
extern int notif_debug;
diff --git a/gdb/remote.c b/gdb/remote.c
index 2ac8c36..82dce9c 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -1367,6 +1367,7 @@ enum {
PACKET_Qbtrace_off,
PACKET_Qbtrace_bts,
PACKET_qXfer_btrace,
+ PACKET_notifications,
PACKET_MAX
};
@@ -3569,7 +3570,7 @@ remote_start_remote (int from_tty, struct target_ops *target, int extended_p)
/* remote_notif_get_pending_replies acks this one, and gets
the rest out. */
rs->notif_state->pending_event[notif_client_stop.id]
- = remote_notif_parse (notif, rs->buf);
+ = remote_notif_parse (notif, rs->notif_state, rs->buf);
remote_notif_get_pending_events (notif);
/* Make sure that threads that were stopped remain
@@ -3989,6 +3990,17 @@ remote_augmented_libraries_svr4_read_feature
rs->augmented_libraries_svr4_read = (support == PACKET_ENABLE);
}
+static void
+remote_notifications_feature (const struct protocol_feature *feature,
+ enum packet_support support,
+ const char *value)
+{
+ struct remote_state *rs = get_remote_state ();
+
+ if (support == PACKET_ENABLE)
+ remote_notif_qsupported_reply (value, rs->notif_state);
+}
+
static const struct protocol_feature remote_protocol_features[] = {
{ "PacketSize", PACKET_DISABLE, remote_packet_size, -1 },
{ "qXfer:auxv:read", PACKET_DISABLE, remote_supported_packet,
@@ -4063,7 +4075,9 @@ static const struct protocol_feature remote_protocol_features[] = {
{ "Qbtrace:off", PACKET_DISABLE, remote_supported_packet, PACKET_Qbtrace_off },
{ "Qbtrace:bts", PACKET_DISABLE, remote_supported_packet, PACKET_Qbtrace_bts },
{ "qXfer:btrace:read", PACKET_DISABLE, remote_supported_packet,
- PACKET_qXfer_btrace }
+ PACKET_qXfer_btrace },
+ { "Notifications", PACKET_DISABLE, remote_notifications_feature,
+ -1 },
};
static char *remote_support_xml;
@@ -4128,6 +4142,7 @@ remote_query_supported (void)
if (remote_protocol_packets[PACKET_qSupported].support != PACKET_DISABLE)
{
char *q = NULL;
+ char *notifications = remote_notif_qsupported ();
struct cleanup *old_chain = make_cleanup (free_current_contents, &q);
q = remote_query_supported_append (q, "multiprocess+");
@@ -4137,6 +4152,10 @@ remote_query_supported (void)
q = remote_query_supported_append (q, "qRelocInsn+");
+ q = reconcat (q, q, ";notifications=", notifications,
+ (char *) NULL);
+ xfree (notifications);
+
q = reconcat (q, "qSupported:", q, (char *) NULL);
putpkt (q);
@@ -4592,7 +4611,8 @@ extended_remote_attach_1 (struct target_ops *target, char *args, int from_tty)
if (target_can_async_p ())
{
struct notif_event *reply
- = remote_notif_parse (¬if_client_stop, wait_status);
+ = remote_notif_parse (¬if_client_stop, rs->notif_state,
+ wait_status);
push_stop_reply ((struct stop_reply *) reply);
@@ -5854,7 +5874,7 @@ remote_notif_get_pending_events (struct notif_client *nc)
if (strcmp (rs->buf, "OK") == 0)
break;
else
- remote_notif_ack (nc, rs->buf);
+ remote_notif_ack (nc, rs->notif_state, rs->buf);
}
}
else
@@ -6058,6 +6078,7 @@ remote_wait_as (ptid_t ptid, struct target_waitstatus *status, int options)
{
struct stop_reply *stop_reply
= (struct stop_reply *) remote_notif_parse (¬if_client_stop,
+ rs->notif_state,
rs->buf);
event_ptid = process_stop_reply (stop_reply, status);
--
1.7.7.6
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 2/4] async remote notification 'Trace'.
2013-12-12 13:51 [PATCH 0/4 V7] MI notification on trace started/stopped Yao Qi
` (2 preceding siblings ...)
2013-12-12 13:51 ` [PATCH 1/4] Query supported notifications by qSupported Yao Qi
@ 2013-12-12 13:51 ` Yao Qi
2013-12-18 14:09 ` [PATCH 0/4 V7] MI notification on trace started/stopped Pedro Alves
4 siblings, 0 replies; 11+ messages in thread
From: Yao Qi @ 2013-12-12 13:51 UTC (permalink / raw)
To: gdb-patches
Hi,
This patch adds a new async remote notification 'Trace' to report the
trace-status-related changes in the stub. So far, it is only used for
reporting 'tracing status change', like this,
%Trace:status:T0;tstop::0;tframes:0;tcreated:0;tfree:500000;tsize:500000;circular:0;disconn:0;starttime:001355728912543287;stoptime:001355728912543768;username::;notes:666f6f:\n
gdb/gdbserver:
* notif.c (notifs): Add "notif_trace".
* notif.h (ontif_trace): Declare.
* tracepoint.c [!IN_PROCESS_AGENT]: Include "notif.h".
[!IN_PROCESS_AGENT] (notif_reply_trace): New function.
[!IN_PROCESS_AGENT] (notif_trace): New variable.
(stop_tracing): Call notif_push.
gdb:
* Makefile.in (REMOTE_OBS): Append remote-notif-trace.o
(SFILES): Add remote-notif-trace.c
* remote-notif.c (notifs): Add "notif_client_trace".
* remote-notif.h (notif_client_trace): Declare.
(REMOTE_NOTIF_TRACE): New enum
* remote-notif-trace.c: New.
gdb/doc:
* gdb.texinfo (Packets): Add "vTraced".
(Notification Packets): Add doc about "Trace" notification
and "vTraced" packet.
---
gdb/Makefile.in | 5 ++-
gdb/doc/gdb.texinfo | 9 +++++
gdb/gdbserver/notif.c | 1 +
gdb/gdbserver/notif.h | 1 +
gdb/gdbserver/tracepoint.c | 27 +++++++++++++++
gdb/remote-notif-trace.c | 76 ++++++++++++++++++++++++++++++++++++++++++++
gdb/remote-notif.c | 1 +
gdb/remote-notif.h | 2 +
8 files changed, 120 insertions(+), 2 deletions(-)
create mode 100644 gdb/remote-notif-trace.c
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index be30dfd..2829aba 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -526,7 +526,7 @@ SER_HARDWIRE = @SER_HARDWIRE@
# The `remote' debugging target is supported for most architectures,
# but not all (e.g. 960)
REMOTE_OBS = remote.o dcache.o tracepoint.o ax-general.o ax-gdb.o remote-fileio.o \
- remote-notif.o ctf.o
+ remote-notif.o ctf.o remote-notif-trace.o
# This is remote-sim.o if a simulator is to be linked in.
SIM_OBS = @SIM_OBS@
@@ -756,7 +756,8 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
p-exp.y p-lang.c p-typeprint.c p-valprint.c parse.c printcmd.c \
proc-service.list progspace.c \
prologue-value.c psymtab.c \
- regcache.c reggroups.c remote.c remote-fileio.c remote-notif.c reverse.c \
+ regcache.c reggroups.c remote.c remote-fileio.c remote-notif.c \
+ remote-notif-trace.c reverse.c \
sentinel-frame.c \
serial.c ser-base.c ser-unix.c skip.c \
solib.c solib-target.c source.c \
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index e76f73b..e91c01e 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -38550,6 +38550,8 @@ for success (@pxref{Stop Reply Packets})
@item vStopped
@cindex @samp{vStopped} packet
+@itemx vTraced
+@cindex @samp{vTraced} packet
@xref{Notification Packets}.
@item X @var{addr},@var{length}:@var{XX@dots{}}
@@ -40570,6 +40572,7 @@ continue the tracing run, while 0 tells the target to stop tracing if
@value{GDBN} is no longer in the picture.
@item qTStatus
+@anchor{qTStatus packet}
@cindex @samp{qTStatus} packet
Ask the stub if there is a trace experiment running right now.
@@ -41100,6 +41103,12 @@ for information on how these notifications are acknowledged by
@value{GDBN}.
@tab Report an asynchronous stop event in non-stop mode.
+@item Trace
+@tab vTraced
+@tab @var{status}. The @var{reply} has the form of the reply to
+packet @samp{qTStatus}, as described in @ref{qTStatus packet}.
+@tab Report an asynchronous event related to trace status.
+
@end multitable
@node Remote Non-Stop
diff --git a/gdb/gdbserver/notif.c b/gdb/gdbserver/notif.c
index 4766bba..123581d 100644
--- a/gdb/gdbserver/notif.c
+++ b/gdb/gdbserver/notif.c
@@ -52,6 +52,7 @@
static struct notif_server *notifs[] =
{
¬if_stop,
+ ¬if_trace,
};
/* Write another event or an OK, if there are no more left, to
diff --git a/gdb/gdbserver/notif.h b/gdb/gdbserver/notif.h
index 80e084e..c1abae0 100644
--- a/gdb/gdbserver/notif.h
+++ b/gdb/gdbserver/notif.h
@@ -58,6 +58,7 @@ typedef struct notif_server
} *notif_server_p;
extern struct notif_server notif_stop;
+extern struct notif_server notif_trace;
int handle_notif_ack (char *own_buf, int packet_len);
void notif_write_event (struct notif_server *notif, char *own_buf);
diff --git a/gdb/gdbserver/tracepoint.c b/gdb/gdbserver/tracepoint.c
index ea1a8a1..c47dd88 100644
--- a/gdb/gdbserver/tracepoint.c
+++ b/gdb/gdbserver/tracepoint.c
@@ -3381,6 +3381,25 @@ cmd_qtstart (char *packet)
write_ok (packet);
}
+#ifndef IN_PROCESS_AGENT
+#include "notif.h"
+
+static void cmd_qtstatus (char *packet);
+
+static void
+notif_reply_trace (struct notif_event *event, char *own_buf)
+{
+ sprintf (own_buf, "status:");
+ cmd_qtstatus (own_buf + 7);
+}
+
+struct notif_server notif_trace =
+{
+ "vTraced", "Trace", NULL, notif_reply_trace, 0,
+};
+
+#endif
+
/* End a tracing run, filling in a stop reason to report back to GDB,
and removing the tracepoints from the code. */
@@ -3481,6 +3500,14 @@ stop_tracing (void)
}
unpause_all (1);
+
+ if (notif_trace.supported)
+ {
+ struct notif_event *event
+ = xmalloc (sizeof (struct notif_event));
+
+ notif_push (¬if_trace, event);
+ }
}
static int
diff --git a/gdb/remote-notif-trace.c b/gdb/remote-notif-trace.c
new file mode 100644
index 0000000..ec7f46c
--- /dev/null
+++ b/gdb/remote-notif-trace.c
@@ -0,0 +1,76 @@
+/* Async remote notification on trace.
+
+ Copyright (C) 2013 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ 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 <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include <string.h>
+#include "remote.h"
+#include "tracepoint.h"
+#include "remote-notif.h"
+
+static void
+remote_notif_trace_parse (struct notif_client *self, char *buf,
+ struct notif_event *event)
+{
+ if (strncmp (buf, "status:", 7) == 0)
+ {
+ struct trace_status *ts = current_trace_status ();
+
+ if (buf[7] != 'T')
+ error (_("Unknown trace status in trace notification."));
+ parse_trace_status (buf + 7 + 1, ts);
+ }
+ else
+ error (_("Unknown trace notification."));
+}
+
+static void
+remote_notif_trace_ack (struct notif_client *self, char *buf,
+ struct notif_event *event)
+{
+ /* acknowledge */
+ putpkt ((char *) self->ack_command);
+}
+
+static int
+remote_notif_trace_can_get_pending_events (struct notif_client *self)
+{
+ return 1;
+}
+
+static struct notif_event *
+remote_notif_trace_alloc_event (void)
+{
+ struct notif_event *event = xmalloc (sizeof (struct notif_event));
+
+ event->dtr = NULL;
+
+ return event;
+}
+
+/* A client of notification 'Trace'. */
+
+struct notif_client notif_client_trace =
+{
+ "Trace", "vTraced",
+ remote_notif_trace_parse,
+ remote_notif_trace_ack,
+ remote_notif_trace_can_get_pending_events,
+ remote_notif_trace_alloc_event,
+ REMOTE_NOTIF_TRACE,
+};
diff --git a/gdb/remote-notif.c b/gdb/remote-notif.c
index 4685d30..86a709a 100644
--- a/gdb/remote-notif.c
+++ b/gdb/remote-notif.c
@@ -49,6 +49,7 @@ int notif_debug = 0;
static struct notif_client *notifs[] =
{
¬if_client_stop,
+ ¬if_client_trace,
};
gdb_static_assert (ARRAY_SIZE (notifs) == REMOTE_NOTIF_LAST);
diff --git a/gdb/remote-notif.h b/gdb/remote-notif.h
index 14984b4..1a9e81c 100644
--- a/gdb/remote-notif.h
+++ b/gdb/remote-notif.h
@@ -36,6 +36,7 @@ struct notif_event
enum REMOTE_NOTIF_ID
{
REMOTE_NOTIF_STOP = 0,
+ REMOTE_NOTIF_TRACE,
REMOTE_NOTIF_LAST,
};
@@ -125,6 +126,7 @@ void remote_notif_qsupported_reply (const char *reply,
struct remote_notif_state *state);
extern struct notif_client notif_client_stop;
+extern struct notif_client notif_client_trace;
extern int notif_debug;
--
1.7.7.6
^ permalink raw reply [flat|nested] 11+ messages in thread