* [PATCH 2/5] Query supported notifications by qSupported
2013-01-22 7:05 [PATCH 0/5] MI notification on trace started/stopped (V3) Yao Qi
@ 2013-01-22 7:05 ` Yao Qi
2013-01-22 8:09 ` Eli Zaretskii
2013-01-22 7:05 ` [PATCH 3/5] async remote notification 'Trace' Yao Qi
` (6 subsequent siblings)
7 siblings, 1 reply; 43+ messages in thread
From: Yao Qi @ 2013-01-22 7:05 UTC (permalink / raw)
To: gdb-patches
As we we adding more notifications and annexes, both GDB and GDBserver
has to know what notifications and annexes 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.A1.A2,N3
(GDB supports notification N1, N2 with annexes A1,A2, and N3)
<-- XXX;Notifications=N1,N2.A1,N4
(GDBsever supports notification N1, N2 with annex A1 and N4)
after this, GDB knows what notifications GDBserver is able to send,
and GDBservers knows what notifications GDB doesn't support.
gdb/gdbserver:
2013-01-21 Yao Qi <yao@codesourcery.com>
* Makefile.in (SFILES): Add "common-notif.c".
(OBS): Add common-notif.o.
(common-notif.o): New rule.
* notif.c (notif_find_annex): New.
(notif_qsupported_record): New.
(+notif_qsupported_reply): New.
* notif.h (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:
2013-01-21 Yao Qi <yao@codesourcery.com>
* common/common-notif.c: New.
* common/common-notif.h (struct notif_annex) <supported>: New
field.
* Makefile.in (iREMOTE_OBS): Append "common-notif.o".
(SFILES): Add "common-notif.c".
* remote-notif.c (remote_notif_parse_1): Call the parser of
annex if it is supported.
(remote_notif_qsupported): New.
(remote_notif_qsupported_reply): New.
* remote-notif.h (remote_notif_qsupported): Declare.
(remote_notif_qsupported_reply): Declare.
* remote.c (PACKET_notifications): New enum.
(remote_notifications_feature): New.
(remote_protocol_features): Add new element.
(remote_query_supported): Call remote_notif_qsupported and
append supported notifications to qSupported feature.
(notif_client_annex_stop): Update.
(_initialize_remote): Call add_packet_config_cmd.
gdb/doc:
2013-01-21 Yao Qi <yao@codesourcery.com>
* gdb.texinfo (General Query Packets): Document the new feature
'notifications' of 'qSupported' packet.
Document the new feature in qSupported reply.
---
gdb/Makefile.in | 9 ++-
gdb/common/common-notif.c | 181 +++++++++++++++++++++++++++++++++++++++++++++
gdb/common/common-notif.h | 15 ++++
gdb/doc/gdb.texinfo | 19 +++++
gdb/gdbserver/Makefile.in | 7 +-
gdb/gdbserver/notif.c | 21 +++++
gdb/gdbserver/notif.h | 2 +
gdb/gdbserver/server.c | 15 ++++-
gdb/remote-notif.c | 32 +++++++-
gdb/remote-notif.h | 4 +
gdb/remote.c | 24 ++++++-
11 files changed, 320 insertions(+), 9 deletions(-)
create mode 100644 gdb/common/common-notif.c
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 3bd4363..2e22ed0 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -508,7 +508,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
+ remote-notif.o common-notif.o
# This is remote-sim.o if a simulator is to be linked in.
SIM_OBS = @SIM_OBS@
@@ -732,7 +732,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 \
+ common-notif.c reverse.c \
sentinel-frame.c \
serial.c ser-base.c ser-unix.c skip.c \
solib.c solib-target.c source.c \
@@ -1918,6 +1919,10 @@ common-utils.o: ${srcdir}/common/common-utils.c
$(COMPILE) $(srcdir)/common/common-utils.c
$(POSTCOMPILE)
+common-notif.o: ${srcdir}/common/common-notif.c
+ $(COMPILE) $(srcdir)/common/common-notif.c
+ $(POSTCOMPILE)
+
gdb_vecs.o: ${srcdir}/common/gdb_vecs.c
$(COMPILE) $(srcdir)/common/gdb_vecs.c
$(POSTCOMPILE)
diff --git a/gdb/common/common-notif.c b/gdb/common/common-notif.c
new file mode 100644
index 0000000..4f23865
--- /dev/null
+++ b/gdb/common/common-notif.c
@@ -0,0 +1,181 @@
+/* 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/>. */
+
+#ifdef GDBSERVER
+#include "server.h"
+#else
+#include "defs.h"
+#endif
+#include <string.h>
+#include "common-notif.h"
+#include "gdb_assert.h"
+
+/* Return a string about the notifications in array NOTIFS. NUM is
+ the number of elements in array NOTIFS. */
+
+char *
+notif_supported (struct notif_base *notifs[], int num)
+{
+ int i;
+ char * p = NULL;
+
+#define BUF_LEN 128
+
+ for (i = 0; i < num; i++)
+ {
+ struct notif_base *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);
+
+ if (NOTIF_HAS_ANNEX (nb))
+ {
+ int j;
+
+ NOTIF_ITER_ANNEX (nb, j)
+ {
+ xsnprintf (p + strlen (p), BUF_LEN - strlen (p),
+ ".%s", nb->annexes[j].name);
+ }
+ }
+ }
+
+ return p;
+}
+
+/* Find annex in notification NB by name NAME and length LEN.
+ If found, return annex, otherwise return NULL. */
+
+static struct notif_annex *
+remote_notif_find_annex (struct notif_base *nb,
+ const char *name, int len)
+{
+ if (NOTIF_HAS_ANNEX (nb))
+ {
+ int j;
+
+ NOTIF_ITER_ANNEX (nb, j)
+ if (strncmp (name, nb->annexes[j].name, len) == 0
+ && len == strlen (nb->annexes[j].name))
+ return &nb->annexes[j];
+ }
+ return NULL;
+}
+
+/* Parse the REPLY, which is about supported annexes and
+ notifications in peer, and disable some annexes
+ if the remote stub doesn't support. */
+
+void
+notif_parse_supported (const char *reply,
+ struct notif_base *notifs[], int num)
+{
+ const char *p = reply;
+ int notif_num = 1;
+ char **notif_str;
+ int i;
+
+ for (i = 0; reply[i] != '\0'; i++)
+ if (reply[i] == ',')
+ notif_num++;
+
+ notif_str = xmalloc (notif_num * sizeof (char *));
+ for (i = 0; i < notif_num; i++)
+ {
+ char *end = strchr (p, ',');
+
+ if (end == NULL)
+ notif_str[i] = xstrdup (p);
+ else
+ {
+ /* Can't use xstrndup in GDBserver. */
+ notif_str[i] = strndup (p, end - p);
+ p = end + 1;
+ }
+ }
+
+ for (i = 0; i < notif_num; i++)
+ {
+ int j;
+ struct notif_base *nb = NULL;
+
+ p = notif_str[i];
+
+ for (j = 0; j < num; j++)
+ {
+ int name_len = strlen (notifs[j]->notif_name);
+
+ if (0 == strncmp (notifs[j]->notif_name, p, name_len)
+ && (p[name_len] == '.' || p[name_len] == 0))
+ {
+ nb = notifs[j];
+ p += name_len;
+ break;
+ }
+ }
+
+ if (nb != NULL)
+ {
+ if (p[0] == 0)
+ {
+ /* No annex. */
+ gdb_assert (!NOTIF_HAS_ANNEX (nb));
+ nb->annexes[0].supported = 1;
+ }
+ else if (p[0] == '.')
+ {
+ gdb_assert (NOTIF_HAS_ANNEX (nb));
+
+ p++;
+
+ /* Parse the rest of P and look for annexes. */
+ while (p != NULL)
+ {
+ char *end = strchr (p, '.');
+ struct notif_annex *annex = NULL;
+
+ if (end != NULL)
+ {
+ annex = remote_notif_find_annex (nb, p,
+ end - p);
+ p = end + 1;
+ }
+ else
+ {
+ annex = remote_notif_find_annex (nb, p,
+ strlen (p));
+ p = end;
+ }
+
+ /* If annex is known, mark it supported, otherwise
+ skip it because the peer knows the annex but we
+ don't know. */
+ if (annex != NULL)
+ annex->supported = 1;
+ }
+ }
+ else
+ warning (_("Unknown supported notification"));
+ }
+ }
+}
diff --git a/gdb/common/common-notif.h b/gdb/common/common-notif.h
index 1ffa26c..8e0e0c1 100644
--- a/gdb/common/common-notif.h
+++ b/gdb/common/common-notif.h
@@ -32,6 +32,11 @@ struct notif_annex
notification this annex belongs to. */
const char *name;
+ /* This annex is supported by the peer (GDB or GDBserver)? A
+ notification may have multiple annexes and some of them are
+ supported. Annex is the smallest unit of support. */
+ int supported;
+
#ifdef GDBSERVER
/* Write event EVENT to OWN_BUF. */
void (*write) (struct notif_event *event, char *own_buf);
@@ -53,6 +58,10 @@ struct notif_annex
#define NOTIF_HAS_ANNEX(NOTIF) ((NOTIF)->annexes[0].name != NULL)
+/* Whether the annex of notification N is supported. */
+
+#define NOTIF_ANNEX_SUPPORTED_P(N, INDEX) \
+ ((N).annexes[INDEX].supported)
/* "Base class" of a notification. It can be extended in both GDB
and GDBserver to represent a type of notification. */
@@ -71,3 +80,9 @@ struct notif_base
of the notification. */
struct notif_annex *annexes;
};
+
+char *notif_supported (struct notif_base *notifs[], int num);
+
+void notif_parse_supported (const char *reply,
+ struct notif_base *notifs[], int num);
+
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 8f08e82..bc5a8c7 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -37113,6 +37113,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 supported notifications,
+separated by comma, it will report notifications supported by the
+stub.
@end table
Stubs should ignore any unknown values for
@@ -37301,6 +37309,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:
@@ -37455,6 +37468,12 @@ 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{annex}@r{]}@dots{}@r{[},@var{name}@r{[}.@var{annex}@r{]}@dots{}@r{]}@dots{}
+@cindex notifications, in remote protocol
+The remote stub supports a string of notifications which the remote stub
+supports. @var{name} is the name of the notification and @var{annex}
+is the name of the annex, if the notification has the annex.
+
@end table
@item qSymbol::
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index f8b1794..8533e54 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -155,7 +155,7 @@ SFILES= $(srcdir)/gdbreplay.c $(srcdir)/inferiors.c $(srcdir)/dll.c \
$(srcdir)/common/vec.c $(srcdir)/common/gdb_vecs.c \
$(srcdir)/common/common-utils.c $(srcdir)/common/xml-utils.c \
$(srcdir)/common/linux-osdata.c $(srcdir)/common/ptid.c \
- $(srcdir)/common/buffer.c
+ $(srcdir)/common/buffer.c $(srcdir)/common/common-notif.c
DEPFILES = @GDBSERVER_DEPFILES@
@@ -165,7 +165,7 @@ SOURCES = $(SFILES)
TAGFILES = $(SOURCES) ${HFILES} ${ALLPARAM} ${POSSLIBS}
OBS = agent.o ax.o inferiors.o regcache.o remote-utils.o server.o signals.o target.o \
- utils.o version.o vec.o gdb_vecs.o \
+ utils.o version.o vec.o gdb_vecs.o common-notif.o \
mem-break.o hostio.o event-loop.o tracepoint.o \
xml-utils.o common-utils.o ptid.o buffer.o format.o \
dll.o notif.o \
@@ -517,6 +517,9 @@ linux-ptrace.o: ../common/linux-ptrace.c
common-utils.o: ../common/common-utils.c
$(COMPILE) $<
$(POSTCOMPILE)
+common-notif.o: ../common/common-notif.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
vec.o: ../common/vec.c
$(COMPILE) $<
$(POSTCOMPILE)
diff --git a/gdb/gdbserver/notif.c b/gdb/gdbserver/notif.c
index 168f77d..e6b3756 100644
--- a/gdb/gdbserver/notif.c
+++ b/gdb/gdbserver/notif.c
@@ -182,6 +182,27 @@ 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)
+{
+ return notif_parse_supported (gdb_notifications,
+ (struct notif_base **) notifs,
+ ARRAY_SIZE (notifs));
+}
+
+/* Return a string about notifications that GDBserver supports.
+ Return NULL if no notification is supported. */
+
+char *
+notif_qsupported_reply (void)
+{
+ return notif_supported ((struct notif_base **) notifs,
+ ARRAY_SIZE (notifs));
+}
+
void
initialize_notif (void)
{
diff --git a/gdb/gdbserver/notif.h b/gdb/gdbserver/notif.h
index 5f9b6bc..72417aa 100644
--- a/gdb/gdbserver/notif.h
+++ b/gdb/gdbserver/notif.h
@@ -58,6 +58,8 @@ 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 f98a780..61f08bd 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -185,7 +185,7 @@ vstop_notif_reply (struct notif_event *event, char *own_buf)
static struct notif_annex notif_annex_stop[] =
{
- { NULL, vstop_notif_reply, },
+ { NULL, 1, vstop_notif_reply, },
};
struct notif_server notif_stop =
@@ -1578,6 +1578,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);
@@ -1659,6 +1664,14 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
if (target_supports_agent ())
strcat (own_buf, ";QAgent+");
+ 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 e0bc745..ae05bbf 100644
--- a/gdb/remote-notif.c
+++ b/gdb/remote-notif.c
@@ -75,9 +75,16 @@ remote_notif_parse_1 (struct notif_client *nc,
contents in BUF. */
&& buf[strlen (m->name)] == ':')
{
- /* Pass BUF without annex and ':'. */
- m->parse (nc, buf + strlen (m->name) + 1, event);
- break;
+ if (m->supported)
+ {
+ /* Pass BUF without annex and ':'. */
+ m->parse (nc, buf + strlen (m->name) + 1, event);
+ break;
+ }
+ else
+ warning (_("GDB gets annex '%s' of notification '%s'"
+ "but remote stub doesn't support"),
+ base->notif_name, m->name);
}
m = NULL;
}
@@ -305,6 +312,25 @@ notif_xfree (struct notif_client *notif)
xfree (notif);
}
+/* Return a string of GDB supported features. */
+
+char *
+remote_notif_qsupported (void)
+{
+ return notif_supported ((struct notif_base **) notifs,
+ ARRAY_SIZE (notifs));
+}
+
+/* Parse the qSupported reply REPLY from the remote stub and disable
+ some notifications if the remote stub doesn't support. */
+
+void
+remote_notif_qsupported_reply (const char *reply)
+{
+ notif_parse_supported (reply, (struct notif_base **) notifs,
+ ARRAY_SIZE (notifs));
+}
+
/* -Wmissing-prototypes */
extern initialize_file_ftype _initialize_notif;
diff --git a/gdb/remote-notif.h b/gdb/remote-notif.h
index cb1636f..4859254 100644
--- a/gdb/remote-notif.h
+++ b/gdb/remote-notif.h
@@ -69,6 +69,10 @@ void remote_notif_register_async_event_handler (void);
void remote_notif_unregister_async_event_handler (void);
void remote_notif_process (struct notif_client *except);
+
+char * remote_notif_qsupported (void);
+void remote_notif_qsupported_reply (const char *reply);
+
extern struct notif_client notif_client_stop;
extern unsigned int notif_debug;
diff --git a/gdb/remote.c b/gdb/remote.c
index 92a0f27..aeb93ff 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -1284,6 +1284,7 @@ enum {
PACKET_qXfer_fdpic,
PACKET_QDisableRandomization,
PACKET_QAgent,
+ PACKET_notifications,
PACKET_MAX
};
@@ -3873,6 +3874,14 @@ remote_string_tracing_feature (const struct protocol_feature *feature,
rs->string_tracing = (support == PACKET_ENABLE);
}
+static void
+remote_notifications_feature (const struct protocol_feature *feature,
+ enum packet_support support,
+ const char *value)
+{
+ remote_notif_qsupported_reply (value);
+}
+
static struct protocol_feature remote_protocol_features[] = {
{ "PacketSize", PACKET_DISABLE, remote_packet_size, -1 },
{ "qXfer:auxv:read", PACKET_DISABLE, remote_supported_packet,
@@ -3938,6 +3947,8 @@ static struct protocol_feature remote_protocol_features[] = {
{ "QDisableRandomization", PACKET_DISABLE, remote_supported_packet,
PACKET_QDisableRandomization },
{ "QAgent", PACKET_DISABLE, remote_supported_packet, PACKET_QAgent},
+ { "Notifications", PACKET_DISABLE, remote_notifications_feature,
+ PACKET_notifications },
{ "tracenz", PACKET_DISABLE,
remote_string_tracing_feature, -1 },
};
@@ -4004,6 +4015,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+");
@@ -4013,6 +4025,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);
@@ -5211,7 +5227,10 @@ remote_notif_stop_alloc_reply (void)
static struct notif_annex notif_client_annex_stop[] =
{
- { NULL, remote_notif_stop_parse, },
+ /* Even the remote stub doesn't understand
+ 'qSupported:notifications=', it may still support notification
+ stop if it supports non-stop. */
+ { NULL, 1, remote_notif_stop_parse, },
};
/* A client of notification Stop. */
@@ -11696,6 +11715,9 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
add_packet_config_cmd (&remote_protocol_packets[PACKET_QAgent],
"QAgent", "agent", 0);
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_notifications],
+ "Notifications", "read notifications", 0);
+
/* Keep the old ``set remote Z-packet ...'' working. Each individual
Z sub-packet has its own set and show commands, but users may
have sets to this variable in their .gdbinit files (or in their
--
1.7.7.6
^ permalink raw reply [flat|nested] 43+ messages in thread* Re: [PATCH 2/5] Query supported notifications by qSupported
2013-01-22 7:05 ` [PATCH 2/5] Query supported notifications by qSupported Yao Qi
@ 2013-01-22 8:09 ` Eli Zaretskii
2013-01-22 8:41 ` Yao Qi
0 siblings, 1 reply; 43+ messages in thread
From: Eli Zaretskii @ 2013-01-22 8:09 UTC (permalink / raw)
To: Yao Qi; +Cc: gdb-patches
> From: Yao Qi <yao@codesourcery.com>
> Date: Tue, 22 Jan 2013 15:03:49 +0800
>
> +@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 supported notifications,
> +separated by comma, it will report notifications supported by the
> +stub. ^^^^^^^^
"by commas", in plural.
> +@cindex notifications, in remote protocol
> +The remote stub supports a string of notifications which the remote stub
> +supports.
Something is wrong with this sentence...
^ permalink raw reply [flat|nested] 43+ messages in thread* Re: [PATCH 2/5] Query supported notifications by qSupported
2013-01-22 8:09 ` Eli Zaretskii
@ 2013-01-22 8:41 ` Yao Qi
2013-01-22 10:26 ` Eli Zaretskii
0 siblings, 1 reply; 43+ messages in thread
From: Yao Qi @ 2013-01-22 8:41 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: gdb-patches
On 01/22/2013 04:08 PM, Eli Zaretskii wrote:
> "by commas", in plural.
>
Fixed.
>> >+@cindex notifications, in remote protocol
>> >+The remote stub supports a string of notifications which the remote stub
>> >+supports.
> Something is wrong with this sentence...
How about this?
@cindex notifications, in remote protocol
The remote stub supports a string of notifications. @var{name} is
the name of the notification and @var{annex} is the name of the annex,
if the notification has the annex.
Below is the updated version with some minor non-doc cleanups.
--
Yao (é½å°§)
gdb/gdbserver:
2013-01-21 Yao Qi <yao@codesourcery.com>
* Makefile.in (SFILES): Add "common-notif.c".
(OBS): Add common-notif.o.
(common-notif.o): New rule.
* notif.c (notif_find_annex): New.
(notif_qsupported_record): New.
(+notif_qsupported_reply): New.
* notif.h (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:
2013-01-21 Yao Qi <yao@codesourcery.com>
* common/common-notif.c: New.
* common/common-notif.h (struct notif_annex) <supported>: New
field.
* Makefile.in (iREMOTE_OBS): Append "common-notif.o".
(SFILES): Add "common-notif.c".
* remote-notif.c (remote_notif_parse_1): Call the parser of
annex if it is supported.
(remote_notif_qsupported): New.
(remote_notif_qsupported_reply): New.
* remote-notif.h (remote_notif_qsupported): Declare.
(remote_notif_qsupported_reply): Declare.
* remote.c (PACKET_notifications): New enum.
(remote_notifications_feature): New.
(remote_protocol_features): Add new element.
(remote_query_supported): Call remote_notif_qsupported and
append supported notifications to qSupported feature.
(notif_client_annex_stop): Update.
gdb/doc:
2013-01-21 Yao Qi <yao@codesourcery.com>
* gdb.texinfo (General Query Packets): Document the new feature
'notifications' of 'qSupported' packet.
Document the new feature in qSupported reply.
---
gdb/Makefile.in | 9 ++-
gdb/common/common-notif.c | 181 +++++++++++++++++++++++++++++++++++++++++++++
gdb/common/common-notif.h | 15 ++++
gdb/doc/gdb.texinfo | 19 +++++
gdb/gdbserver/Makefile.in | 7 +-
gdb/gdbserver/notif.c | 21 +++++
gdb/gdbserver/notif.h | 2 +
gdb/gdbserver/server.c | 15 ++++-
gdb/remote-notif.c | 32 +++++++-
gdb/remote-notif.h | 4 +
gdb/remote.c | 22 +++++-
11 files changed, 318 insertions(+), 9 deletions(-)
create mode 100644 gdb/common/common-notif.c
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 3bd4363..2e22ed0 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -508,7 +508,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
+ remote-notif.o common-notif.o
# This is remote-sim.o if a simulator is to be linked in.
SIM_OBS = @SIM_OBS@
@@ -732,7 +732,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 \
+ common-notif.c reverse.c \
sentinel-frame.c \
serial.c ser-base.c ser-unix.c skip.c \
solib.c solib-target.c source.c \
@@ -1918,6 +1919,10 @@ common-utils.o: ${srcdir}/common/common-utils.c
$(COMPILE) $(srcdir)/common/common-utils.c
$(POSTCOMPILE)
+common-notif.o: ${srcdir}/common/common-notif.c
+ $(COMPILE) $(srcdir)/common/common-notif.c
+ $(POSTCOMPILE)
+
gdb_vecs.o: ${srcdir}/common/gdb_vecs.c
$(COMPILE) $(srcdir)/common/gdb_vecs.c
$(POSTCOMPILE)
diff --git a/gdb/common/common-notif.c b/gdb/common/common-notif.c
new file mode 100644
index 0000000..4f23865
--- /dev/null
+++ b/gdb/common/common-notif.c
@@ -0,0 +1,181 @@
+/* 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/>. */
+
+#ifdef GDBSERVER
+#include "server.h"
+#else
+#include "defs.h"
+#endif
+#include <string.h>
+#include "common-notif.h"
+#include "gdb_assert.h"
+
+/* Return a string about the notifications in array NOTIFS. NUM is
+ the number of elements in array NOTIFS. */
+
+char *
+notif_supported (struct notif_base *notifs[], int num)
+{
+ int i;
+ char * p = NULL;
+
+#define BUF_LEN 128
+
+ for (i = 0; i < num; i++)
+ {
+ struct notif_base *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);
+
+ if (NOTIF_HAS_ANNEX (nb))
+ {
+ int j;
+
+ NOTIF_ITER_ANNEX (nb, j)
+ {
+ xsnprintf (p + strlen (p), BUF_LEN - strlen (p),
+ ".%s", nb->annexes[j].name);
+ }
+ }
+ }
+
+ return p;
+}
+
+/* Find annex in notification NB by name NAME and length LEN.
+ If found, return annex, otherwise return NULL. */
+
+static struct notif_annex *
+remote_notif_find_annex (struct notif_base *nb,
+ const char *name, int len)
+{
+ if (NOTIF_HAS_ANNEX (nb))
+ {
+ int j;
+
+ NOTIF_ITER_ANNEX (nb, j)
+ if (strncmp (name, nb->annexes[j].name, len) == 0
+ && len == strlen (nb->annexes[j].name))
+ return &nb->annexes[j];
+ }
+ return NULL;
+}
+
+/* Parse the REPLY, which is about supported annexes and
+ notifications in peer, and disable some annexes
+ if the remote stub doesn't support. */
+
+void
+notif_parse_supported (const char *reply,
+ struct notif_base *notifs[], int num)
+{
+ const char *p = reply;
+ int notif_num = 1;
+ char **notif_str;
+ int i;
+
+ for (i = 0; reply[i] != '\0'; i++)
+ if (reply[i] == ',')
+ notif_num++;
+
+ notif_str = xmalloc (notif_num * sizeof (char *));
+ for (i = 0; i < notif_num; i++)
+ {
+ char *end = strchr (p, ',');
+
+ if (end == NULL)
+ notif_str[i] = xstrdup (p);
+ else
+ {
+ /* Can't use xstrndup in GDBserver. */
+ notif_str[i] = strndup (p, end - p);
+ p = end + 1;
+ }
+ }
+
+ for (i = 0; i < notif_num; i++)
+ {
+ int j;
+ struct notif_base *nb = NULL;
+
+ p = notif_str[i];
+
+ for (j = 0; j < num; j++)
+ {
+ int name_len = strlen (notifs[j]->notif_name);
+
+ if (0 == strncmp (notifs[j]->notif_name, p, name_len)
+ && (p[name_len] == '.' || p[name_len] == 0))
+ {
+ nb = notifs[j];
+ p += name_len;
+ break;
+ }
+ }
+
+ if (nb != NULL)
+ {
+ if (p[0] == 0)
+ {
+ /* No annex. */
+ gdb_assert (!NOTIF_HAS_ANNEX (nb));
+ nb->annexes[0].supported = 1;
+ }
+ else if (p[0] == '.')
+ {
+ gdb_assert (NOTIF_HAS_ANNEX (nb));
+
+ p++;
+
+ /* Parse the rest of P and look for annexes. */
+ while (p != NULL)
+ {
+ char *end = strchr (p, '.');
+ struct notif_annex *annex = NULL;
+
+ if (end != NULL)
+ {
+ annex = remote_notif_find_annex (nb, p,
+ end - p);
+ p = end + 1;
+ }
+ else
+ {
+ annex = remote_notif_find_annex (nb, p,
+ strlen (p));
+ p = end;
+ }
+
+ /* If annex is known, mark it supported, otherwise
+ skip it because the peer knows the annex but we
+ don't know. */
+ if (annex != NULL)
+ annex->supported = 1;
+ }
+ }
+ else
+ warning (_("Unknown supported notification"));
+ }
+ }
+}
diff --git a/gdb/common/common-notif.h b/gdb/common/common-notif.h
index 1ffa26c..8e0e0c1 100644
--- a/gdb/common/common-notif.h
+++ b/gdb/common/common-notif.h
@@ -32,6 +32,11 @@ struct notif_annex
notification this annex belongs to. */
const char *name;
+ /* This annex is supported by the peer (GDB or GDBserver)? A
+ notification may have multiple annexes and some of them are
+ supported. Annex is the smallest unit of support. */
+ int supported;
+
#ifdef GDBSERVER
/* Write event EVENT to OWN_BUF. */
void (*write) (struct notif_event *event, char *own_buf);
@@ -53,6 +58,10 @@ struct notif_annex
#define NOTIF_HAS_ANNEX(NOTIF) ((NOTIF)->annexes[0].name != NULL)
+/* Whether the annex of notification N is supported. */
+
+#define NOTIF_ANNEX_SUPPORTED_P(N, INDEX) \
+ ((N).annexes[INDEX].supported)
/* "Base class" of a notification. It can be extended in both GDB
and GDBserver to represent a type of notification. */
@@ -71,3 +80,9 @@ struct notif_base
of the notification. */
struct notif_annex *annexes;
};
+
+char *notif_supported (struct notif_base *notifs[], int num);
+
+void notif_parse_supported (const char *reply,
+ struct notif_base *notifs[], int num);
+
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 8f08e82..0c25772 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -37113,6 +37113,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 supported notifications,
+separated by commas, it will report notifications supported by the
+stub.
@end table
Stubs should ignore any unknown values for
@@ -37301,6 +37309,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:
@@ -37455,6 +37468,12 @@ 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{annex}@r{]}@dots{}@r{[},@var{name}@r{[}.@var{annex}@r{]}@dots{}@r{]}@dots{}
+@cindex notifications, in remote protocol
+The remote stub supports a string of notifications. @var{name} is
+the name of the notification and @var{annex} is the name of the annex,
+if the notification has the annex.
+
@end table
@item qSymbol::
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index f8b1794..8533e54 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -155,7 +155,7 @@ SFILES= $(srcdir)/gdbreplay.c $(srcdir)/inferiors.c $(srcdir)/dll.c \
$(srcdir)/common/vec.c $(srcdir)/common/gdb_vecs.c \
$(srcdir)/common/common-utils.c $(srcdir)/common/xml-utils.c \
$(srcdir)/common/linux-osdata.c $(srcdir)/common/ptid.c \
- $(srcdir)/common/buffer.c
+ $(srcdir)/common/buffer.c $(srcdir)/common/common-notif.c
DEPFILES = @GDBSERVER_DEPFILES@
@@ -165,7 +165,7 @@ SOURCES = $(SFILES)
TAGFILES = $(SOURCES) ${HFILES} ${ALLPARAM} ${POSSLIBS}
OBS = agent.o ax.o inferiors.o regcache.o remote-utils.o server.o signals.o target.o \
- utils.o version.o vec.o gdb_vecs.o \
+ utils.o version.o vec.o gdb_vecs.o common-notif.o \
mem-break.o hostio.o event-loop.o tracepoint.o \
xml-utils.o common-utils.o ptid.o buffer.o format.o \
dll.o notif.o \
@@ -517,6 +517,9 @@ linux-ptrace.o: ../common/linux-ptrace.c
common-utils.o: ../common/common-utils.c
$(COMPILE) $<
$(POSTCOMPILE)
+common-notif.o: ../common/common-notif.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
vec.o: ../common/vec.c
$(COMPILE) $<
$(POSTCOMPILE)
diff --git a/gdb/gdbserver/notif.c b/gdb/gdbserver/notif.c
index 168f77d..e6b3756 100644
--- a/gdb/gdbserver/notif.c
+++ b/gdb/gdbserver/notif.c
@@ -182,6 +182,27 @@ 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)
+{
+ return notif_parse_supported (gdb_notifications,
+ (struct notif_base **) notifs,
+ ARRAY_SIZE (notifs));
+}
+
+/* Return a string about notifications that GDBserver supports.
+ Return NULL if no notification is supported. */
+
+char *
+notif_qsupported_reply (void)
+{
+ return notif_supported ((struct notif_base **) notifs,
+ ARRAY_SIZE (notifs));
+}
+
void
initialize_notif (void)
{
diff --git a/gdb/gdbserver/notif.h b/gdb/gdbserver/notif.h
index 5f9b6bc..72417aa 100644
--- a/gdb/gdbserver/notif.h
+++ b/gdb/gdbserver/notif.h
@@ -58,6 +58,8 @@ 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 f98a780..61f08bd 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -185,7 +185,7 @@ vstop_notif_reply (struct notif_event *event, char *own_buf)
static struct notif_annex notif_annex_stop[] =
{
- { NULL, vstop_notif_reply, },
+ { NULL, 1, vstop_notif_reply, },
};
struct notif_server notif_stop =
@@ -1578,6 +1578,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);
@@ -1659,6 +1664,14 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
if (target_supports_agent ())
strcat (own_buf, ";QAgent+");
+ 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 e0bc745..ae05bbf 100644
--- a/gdb/remote-notif.c
+++ b/gdb/remote-notif.c
@@ -75,9 +75,16 @@ remote_notif_parse_1 (struct notif_client *nc,
contents in BUF. */
&& buf[strlen (m->name)] == ':')
{
- /* Pass BUF without annex and ':'. */
- m->parse (nc, buf + strlen (m->name) + 1, event);
- break;
+ if (m->supported)
+ {
+ /* Pass BUF without annex and ':'. */
+ m->parse (nc, buf + strlen (m->name) + 1, event);
+ break;
+ }
+ else
+ warning (_("GDB gets annex '%s' of notification '%s'"
+ "but remote stub doesn't support"),
+ base->notif_name, m->name);
}
m = NULL;
}
@@ -305,6 +312,25 @@ notif_xfree (struct notif_client *notif)
xfree (notif);
}
+/* Return a string of GDB supported features. */
+
+char *
+remote_notif_qsupported (void)
+{
+ return notif_supported ((struct notif_base **) notifs,
+ ARRAY_SIZE (notifs));
+}
+
+/* Parse the qSupported reply REPLY from the remote stub and disable
+ some notifications if the remote stub doesn't support. */
+
+void
+remote_notif_qsupported_reply (const char *reply)
+{
+ notif_parse_supported (reply, (struct notif_base **) notifs,
+ ARRAY_SIZE (notifs));
+}
+
/* -Wmissing-prototypes */
extern initialize_file_ftype _initialize_notif;
diff --git a/gdb/remote-notif.h b/gdb/remote-notif.h
index cb1636f..4859254 100644
--- a/gdb/remote-notif.h
+++ b/gdb/remote-notif.h
@@ -69,6 +69,10 @@ void remote_notif_register_async_event_handler (void);
void remote_notif_unregister_async_event_handler (void);
void remote_notif_process (struct notif_client *except);
+
+char * remote_notif_qsupported (void);
+void remote_notif_qsupported_reply (const char *reply);
+
extern struct notif_client notif_client_stop;
extern unsigned int notif_debug;
diff --git a/gdb/remote.c b/gdb/remote.c
index 92a0f27..e20ac80 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -1284,6 +1284,7 @@ enum {
PACKET_qXfer_fdpic,
PACKET_QDisableRandomization,
PACKET_QAgent,
+ PACKET_notifications,
PACKET_MAX
};
@@ -3873,6 +3874,15 @@ remote_string_tracing_feature (const struct protocol_feature *feature,
rs->string_tracing = (support == PACKET_ENABLE);
}
+static void
+remote_notifications_feature (const struct protocol_feature *feature,
+ enum packet_support support,
+ const char *value)
+{
+ if (support == PACKET_ENABLE)
+ remote_notif_qsupported_reply (value);
+}
+
static struct protocol_feature remote_protocol_features[] = {
{ "PacketSize", PACKET_DISABLE, remote_packet_size, -1 },
{ "qXfer:auxv:read", PACKET_DISABLE, remote_supported_packet,
@@ -3938,6 +3948,8 @@ static struct protocol_feature remote_protocol_features[] = {
{ "QDisableRandomization", PACKET_DISABLE, remote_supported_packet,
PACKET_QDisableRandomization },
{ "QAgent", PACKET_DISABLE, remote_supported_packet, PACKET_QAgent},
+ { "Notifications", PACKET_DISABLE, remote_notifications_feature,
+ -1 },
{ "tracenz", PACKET_DISABLE,
remote_string_tracing_feature, -1 },
};
@@ -4004,6 +4016,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+");
@@ -4013,6 +4026,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);
@@ -5211,7 +5228,10 @@ remote_notif_stop_alloc_reply (void)
static struct notif_annex notif_client_annex_stop[] =
{
- { NULL, remote_notif_stop_parse, },
+ /* Even the remote stub doesn't understand
+ 'qSupported:notifications=', it may still support notification
+ stop if it supports non-stop. */
+ { NULL, 1, remote_notif_stop_parse, },
};
/* A client of notification Stop. */
--
1.7.7.6
^ permalink raw reply [flat|nested] 43+ messages in thread* Re: [PATCH 2/5] Query supported notifications by qSupported
2013-01-22 8:41 ` Yao Qi
@ 2013-01-22 10:26 ` Eli Zaretskii
0 siblings, 0 replies; 43+ messages in thread
From: Eli Zaretskii @ 2013-01-22 10:26 UTC (permalink / raw)
To: Yao Qi; +Cc: gdb-patches
> Date: Tue, 22 Jan 2013 16:39:48 +0800
> From: Yao Qi <yao@codesourcery.com>
> CC: <gdb-patches@sourceware.org>
>
> >> >+@cindex notifications, in remote protocol
> >> >+The remote stub supports a string of notifications which the remote stub
> >> >+supports.
> > Something is wrong with this sentence...
>
> How about this?
>
> @cindex notifications, in remote protocol
> The remote stub supports a string of notifications. @var{name} is
> the name of the notification and @var{annex} is the name of the annex,
> if the notification has the annex.
Fine with me, thanks.
^ permalink raw reply [flat|nested] 43+ messages in thread
* [PATCH 3/5] async remote notification 'Trace'.
2013-01-22 7:05 [PATCH 0/5] MI notification on trace started/stopped (V3) Yao Qi
2013-01-22 7:05 ` [PATCH 2/5] Query supported notifications by qSupported Yao Qi
@ 2013-01-22 7:05 ` Yao Qi
2013-01-22 8:06 ` Eli Zaretskii
2013-01-22 7:05 ` [PATCH 1/5] Add annex in a async remote notification Yao Qi
` (5 subsequent siblings)
7 siblings, 1 reply; 43+ messages in thread
From: Yao Qi @ 2013-01-22 7:05 UTC (permalink / raw)
To: gdb-patches
Hi,
This patch adds a new async remote notification 'Trace' to report the
trace-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
and of course, it can be used for other trace-related changes, with
different annex.
gdb/gdbserver:
2013-01-08 Yao Qi <yao@codesourcery.com>
* notif.c (notifs): Add "notif_trace".
* notif.h (ontif_trace): Declare.
* tracepoint.c [!IN_PROCESS_AGENT]: Include "notif.h".
(notif_reply_trace): New.
(notif_trace): New variable.
(stop_tracing): Call notif_push.
gdb:
2012-01-08 Yao Qi <yao@codesourcery.com>
* 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.
(NOTIF_ANNEX_TRACE_STATUS): New macro.
* remote-notif-trace.c: New.
gdb/doc:
2012-01-08 Yao Qi <yao@codesourcery.com>
* gdb.texinfo (Packets): Add "vTraced".
(Notification Packets): Add doc about "Trace" notification
and "vTraced" packet.
---
gdb/Makefile.in | 4 +-
gdb/doc/gdb.texinfo | 10 ++++++
gdb/gdbserver/notif.c | 1 +
gdb/gdbserver/notif.h | 1 +
gdb/gdbserver/tracepoint.c | 36 +++++++++++++++++++++
gdb/remote-notif-trace.c | 75 ++++++++++++++++++++++++++++++++++++++++++++
gdb/remote-notif.c | 1 +
gdb/remote-notif.h | 1 +
8 files changed, 127 insertions(+), 2 deletions(-)
create mode 100644 gdb/remote-notif-trace.c
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 2e22ed0..890d0cc 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -508,7 +508,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 common-notif.o
+ remote-notif.o common-notif.o remote-notif-trace.o
# This is remote-sim.o if a simulator is to be linked in.
SIM_OBS = @SIM_OBS@
@@ -733,7 +733,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
proc-service.list progspace.c \
prologue-value.c psymtab.c \
regcache.c reggroups.c remote.c remote-fileio.c remote-notif.c \
- common-notif.c reverse.c \
+ common-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 bc5a8c7..c41310d 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -36283,6 +36283,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{}}
@@ -38184,6 +38186,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.
@@ -38711,6 +38714,13 @@ 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 @code{status}
+@tab @var{reply}. The @var{reply} has the form of the reply to packet
+@samp{qTStatus}, as described in @ref{qTStatus packet}.
+@tab Report an asynchronous trace-related event.
+
@end multitable
@node Remote Non-Stop
diff --git a/gdb/gdbserver/notif.c b/gdb/gdbserver/notif.c
index e6b3756..5a533f4 100644
--- a/gdb/gdbserver/notif.c
+++ b/gdb/gdbserver/notif.c
@@ -52,6 +52,7 @@
static struct notif_server *notifs[] =
{
¬if_stop,
+ ¬if_trace,
};
/* Helper function to write EVENT of NOTIF to buffer OWN_BUF. */
diff --git a/gdb/gdbserver/notif.h b/gdb/gdbserver/notif.h
index 72417aa..52d09cc 100644
--- a/gdb/gdbserver/notif.h
+++ b/gdb/gdbserver/notif.h
@@ -55,6 +55,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 51b6a0c..8becbbf 100644
--- a/gdb/gdbserver/tracepoint.c
+++ b/gdb/gdbserver/tracepoint.c
@@ -3370,6 +3370,32 @@ 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)
+{
+ cmd_qtstatus (own_buf);
+}
+
+#define NOTIF_ANNEX_TRACE_STATUS 0
+
+static struct notif_annex notif_annex_trace[] =
+{
+ { "status", 0, notif_reply_trace, },
+ { NULL, 0, NULL, },
+};
+
+struct notif_server notif_trace =
+{
+ { "Trace", "vTraced", notif_annex_trace, }, NULL,
+};
+
+#endif
+
/* End a tracing run, filling in a stop reason to report back to GDB,
and removing the tracepoints from the code. */
@@ -3470,6 +3496,16 @@ stop_tracing (void)
}
unpause_all (1);
+
+ if (NOTIF_ANNEX_SUPPORTED_P (notif_trace.base,
+ NOTIF_ANNEX_TRACE_STATUS))
+ {
+ struct notif_annex_event *event
+ = xmalloc (sizeof (struct notif_annex_event));
+
+ event->annex_index = NOTIF_ANNEX_TRACE_STATUS;
+ notif_push (¬if_trace, (struct notif_event *) event);
+ }
}
static int
diff --git a/gdb/remote-notif-trace.c b/gdb/remote-notif-trace.c
new file mode 100644
index 0000000..a0cfa26
--- /dev/null
+++ b/gdb/remote-notif-trace.c
@@ -0,0 +1,75 @@
+/* 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_status_parse (struct notif_client *self, char *buf,
+ struct notif_event *event)
+{
+ struct trace_status *ts = current_trace_status ();
+
+ gdb_assert (buf[0] == 'T');
+ parse_trace_status (buf + 1, ts);
+}
+
+static void
+remote_notif_trace_ack (struct notif_client *self, char *buf,
+ struct notif_event *event)
+{
+ /* acknowledge */
+ putpkt ((char *) self->base.ack_name);
+}
+
+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;
+}
+
+static struct notif_annex notif_client_trace_annex[] =
+{
+ { "status", 0, remote_notif_trace_status_parse, },
+ { NULL, 0, NULL, },
+};
+
+/* A client of notification 'Trace'. */
+
+struct notif_client notif_client_trace =
+{
+ { "Trace", "vTraced", notif_client_trace_annex, },
+ remote_notif_trace_ack,
+ remote_notif_trace_can_get_pending_events,
+ remote_notif_trace_alloc_event,
+ NULL,
+};
diff --git a/gdb/remote-notif.c b/gdb/remote-notif.c
index ae05bbf..aeff038 100644
--- a/gdb/remote-notif.c
+++ b/gdb/remote-notif.c
@@ -49,6 +49,7 @@ unsigned int notif_debug = 0;
static struct notif_client *notifs[] =
{
¬if_client_stop,
+ ¬if_client_trace,
};
static void do_notif_event_xfree (void *arg);
diff --git a/gdb/remote-notif.h b/gdb/remote-notif.h
index 4859254..ce9fd07 100644
--- a/gdb/remote-notif.h
+++ b/gdb/remote-notif.h
@@ -74,6 +74,7 @@ char * remote_notif_qsupported (void);
void remote_notif_qsupported_reply (const char *reply);
extern struct notif_client notif_client_stop;
+extern struct notif_client notif_client_trace;
extern unsigned int notif_debug;
--
1.7.7.6
^ permalink raw reply [flat|nested] 43+ messages in thread* [PATCH 1/5] Add annex in a async remote notification.
2013-01-22 7:05 [PATCH 0/5] MI notification on trace started/stopped (V3) Yao Qi
2013-01-22 7:05 ` [PATCH 2/5] Query supported notifications by qSupported Yao Qi
2013-01-22 7:05 ` [PATCH 3/5] async remote notification 'Trace' Yao Qi
@ 2013-01-22 7:05 ` Yao Qi
2013-01-22 8:06 ` Eli Zaretskii
2013-01-22 7:06 ` [PATCH 4/5] MI notification on trace started/stopped:basic Yao Qi
` (4 subsequent siblings)
7 siblings, 1 reply; 43+ messages in thread
From: Yao Qi @ 2013-01-22 7:05 UTC (permalink / raw)
To: gdb-patches
In order to support "Trace:status" notification and other similar
usage (such as "Point:modified", about a tracepoint is modified), we
introduce "annex" in the async remote notification, which is helpful
to give us more details what the contents about in the async remote
notification. The annex in each notification is optional. In the
RSP:
<-- %name:annex1:event
--> vAck
<-- annex2:event
--> vAck
<-- annex1:event
--> OK
As we can see above, three events of two annexes (annex1 and annex2)
are sent.
The parsing (receiving rsp packet) and writing (sending rsp packet)
can be done on the annex level. Each annex has its own routines to
send and parse packet, which is more OO.
Also, annex, instead of notification, is the unit of support and they
(GDB and GDBserver) can exchange their supported annexes by means of
qSupported mechanism, which is done in the next patch.
This patch adds "annex" to both GDB and GDBserver. I find 'struct
notif_client' and 'struct notif_server' have three fields which can be
shared, so additionally, we move some shared struct to
common/common-notif.h.
gdb:
2013-01-21 Yao Qi <yao@codesourcery.com>
* common/common-notif.h: New.
* Makefile.in (HFILES_NO_SRCDIR): Add "common/common-notif.h".
* remote-notif.h: Include "common-notif.h".
(struct notif_client) <name, ack_command, parse>: Remove.
<base>: New.
Caller update.
* remote-notif.c (remote_notif_parse_1): New.
(remote_notif_ack): Call remote_notif_parse_1.
(remote_notif_parse): Likewise.
(struct notif_client_annex): New.
* remote.c (notif_client_annex_stop): New.
gdb/gdbserver:
2013-01-21 Yao Qi <yao@codesourcery.com>
* notif.h: Include "common-notif.h".
(struct notif_server) <write, ack_name, notif_name>: Remove.
<base>: New field.
Caller update.
(struct notif_annex_event): New.
* notif.c (notif_write_event_1): New.
(notif_write_event): Call notif_write_event_1 to write event.
(notif_push): Likewise.
* server.c (notif_annex_stop): New.
(notif_stop): Update.
gdb/doc:
2013-01-21 Yao Qi <yao@codesourcery.com>
* gdb.texinfo (Notification Packets): Document 'annex'.
---
gdb/Makefile.in | 2 +-
gdb/common/common-notif.h | 73 +++++++++++++++++++++++++++++++++++++++++++++
gdb/doc/gdb.texinfo | 12 +++++--
gdb/gdbserver/notif.c | 40 ++++++++++++++++++++----
gdb/gdbserver/notif.h | 20 +++++++-----
gdb/gdbserver/server.c | 7 ++++-
gdb/remote-notif.c | 59 +++++++++++++++++++++++++++++++-----
gdb/remote-notif.h | 13 +-------
gdb/remote.c | 15 +++++----
9 files changed, 194 insertions(+), 47 deletions(-)
create mode 100644 gdb/common/common-notif.h
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 7305e6d..3bd4363 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -831,7 +831,7 @@ gnulib/import/stddef.in.h gnulib/import/inttypes.in.h inline-frame.h skip.h \
common/common-utils.h common/xml-utils.h common/buffer.h common/ptid.h \
common/format.h common/host-defs.h utils.h common/queue.h \
common/linux-osdata.h gdb-dlfcn.h auto-load.h probe.h stap-probe.h \
-gdb_bfd.h sparc-ravenscar-thread.h ppc-ravenscar-thread.h
+gdb_bfd.h sparc-ravenscar-thread.h ppc-ravenscar-thread.h common/common-notif.h
# Header files that already have srcdir in them, or which are in objdir.
diff --git a/gdb/common/common-notif.h b/gdb/common/common-notif.h
new file mode 100644
index 0000000..1ffa26c
--- /dev/null
+++ b/gdb/common/common-notif.h
@@ -0,0 +1,73 @@
+/* Shared structs of asynchronous remote notification.
+
+ 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/>. */
+
+struct notif_event;
+#ifndef GDBSERVER
+struct notif_client;
+#endif
+
+/* An annex of a notification. A notification may or may not have
+ annexes. */
+
+struct notif_annex
+{
+ /* Name of this annex. If it is NULL, the notification doesn't have
+ annex, and the field PARSE and SUPPORTED is about the
+ notification this annex belongs to. */
+ const char *name;
+
+#ifdef GDBSERVER
+ /* Write event EVENT to OWN_BUF. */
+ void (*write) (struct notif_event *event, char *own_buf);
+#else
+ /* Parse BUF to get the expected event and update EVENT. This
+ function may throw exception if contents in BUF is not the
+ expected event. */
+ void (*parse) (struct notif_client *self, char *buf,
+ struct notif_event *event);
+#endif
+};
+
+/* Iterate over annexes in *NOTIF by increasing INDEX from zero. */
+
+#define NOTIF_ITER_ANNEX(NOTIF, INDEX) \
+ for (INDEX = 0; (NOTIF)->annexes[INDEX].name != NULL; INDEX++)
+
+/* Notification *NOTIF has annex or not. */
+
+#define NOTIF_HAS_ANNEX(NOTIF) ((NOTIF)->annexes[0].name != NULL)
+
+
+/* "Base class" of a notification. It can be extended in both GDB
+ and GDBserver to represent a type of notification. */
+
+struct notif_base
+{
+ /* The notification packet, for example, '%Stop'. Note that '%' is
+ not in 'notif_name'. */
+ const char *notif_name;
+ /* The name of ack packet, for example, 'vStopped'. */
+ const char *ack_name;
+
+ /* Annexes the notification has. The notification may or not have
+ annexes. Macro 'NOTIF_HAS_ANNEX' is to check notification has
+ annexes, and macro 'NOTIF_ITER_ANNEX' is to iterate over annexes
+ of the notification. */
+ struct notif_annex *annexes;
+};
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 728e44b..8f08e82 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -38604,13 +38604,15 @@ transmit notifications without fear of confusing older clients. There
are no notifications defined for @value{GDBN} to send at the moment, but we
assume that most older stubs would ignore them, as well.)
-Each notification is comprised of three parts:
+Each notification is comprised of four parts:
@table @samp
-@item @var{name}:@var{event}
+@item @var{name}[:@var{annex}]:@var{event}
The notification packet is sent by the side that initiates the
exchange (currently, only the stub does that), with @var{event}
carrying the specific information about the notification.
-@var{name} is the name of the notification.
+@var{name} is the name of the notification. The @var{annex} is
+specific to @var{name}; it can supply additional details about
+@var{event}.
@item @var{ack}
The acknowledge sent by the other side, usually @value{GDBN}, to
acknowledge the exchange and request the event.
@@ -38673,15 +38675,17 @@ following example:
@end smallexample
The following notifications are defined:
-@multitable @columnfractions 0.12 0.12 0.38 0.38
+@multitable @columnfractions 0.10 0.10 0.10 0.35 0.35
@item Notification
@tab Ack
+@tab Annex
@tab Event
@tab Description
@item Stop
@tab vStopped
+@tab
@tab @var{reply}. The @var{reply} has the form of a stop reply, as
described in @ref{Stop Reply Packets}. Refer to @ref{Remote Non-Stop},
for information on how these notifications are acknowledged by
diff --git a/gdb/gdbserver/notif.c b/gdb/gdbserver/notif.c
index e27746e..168f77d 100644
--- a/gdb/gdbserver/notif.c
+++ b/gdb/gdbserver/notif.c
@@ -54,6 +54,29 @@ static struct notif_server *notifs[] =
¬if_stop,
};
+/* Helper function to write EVENT of NOTIF to buffer OWN_BUF. */
+
+static void
+notif_write_event_1 (struct notif_base *notif,
+ struct notif_event *event,
+ char *own_buf)
+{
+ int annex_index = 0;
+
+ /* If the NOTIF has annexes, extract the annex index from the
+ EVENT and append annex name to OWN_BUF; otherwise, NOTIF
+ doesn't have annex and use slot 0 of annexes. */
+ if (NOTIF_HAS_ANNEX (notif))
+ {
+ annex_index
+ = ((struct notif_annex_event *) event)->annex_index;
+ sprintf (own_buf, "%s:", notif->annexes[annex_index].name);
+ own_buf += strlen (notif->annexes[annex_index].name) + 1;
+ }
+
+ notif->annexes[annex_index].write (event, own_buf);
+}
+
/* Write another event or an OK, if there are no more left, to
OWN_BUF. */
@@ -65,7 +88,8 @@ notif_write_event (struct notif_server *notif, char *own_buf)
struct notif_event *event
= QUEUE_peek (notif_event_p, notif->queue);
- notif->write (event, own_buf);
+ notif_write_event_1 ((struct notif_base *) notif, event,
+ own_buf);
}
else
write_ok (own_buf);
@@ -84,8 +108,9 @@ handle_notif_ack (char *own_buf, int packet_len)
for (i = 0; i < ARRAY_SIZE (notifs); i++)
{
np = notifs[i];
- if (strncmp (own_buf, np->ack_name, strlen (np->ack_name)) == 0
- && packet_len == strlen (np->ack_name))
+ if (0 == strncmp (own_buf, np->base.ack_name,
+ strlen (np->base.ack_name))
+ && packet_len == strlen (np->base.ack_name))
break;
}
@@ -100,7 +125,7 @@ handle_notif_ack (char *own_buf, int packet_len)
= QUEUE_deque (notif_event_p, np->queue);
if (remote_debug)
- fprintf (stderr, "%s: acking %d\n", np->ack_name,
+ fprintf (stderr, "%s: acking %d\n", np->base.ack_name,
QUEUE_length (notif_event_p, np->queue));
xfree (head);
@@ -120,7 +145,8 @@ notif_event_enque (struct notif_server *notif,
QUEUE_enque (notif_event_p, notif->queue, event);
if (remote_debug)
- fprintf (stderr, "pending events: %s %d\n", notif->notif_name,
+ fprintf (stderr, "pending events: %s %d\n",
+ notif->base.notif_name,
QUEUE_length (notif_event_p, notif->queue));
}
@@ -142,10 +168,10 @@ notif_push (struct notif_server *np, struct notif_event *new_event)
char buf[PBUFSIZ];
char *p = buf;
- xsnprintf (p, PBUFSIZ, "%s:", np->notif_name);
+ xsnprintf (p, PBUFSIZ, "%s:", np->base.notif_name);
p += strlen (p);
- np->write (new_event, p);
+ notif_write_event_1 ((struct notif_base *) np, new_event, p);
putpkt_notif (buf);
}
}
diff --git a/gdb/gdbserver/notif.h b/gdb/gdbserver/notif.h
index 608b763..5f9b6bc 100644
--- a/gdb/gdbserver/notif.h
+++ b/gdb/gdbserver/notif.h
@@ -20,6 +20,7 @@
#include "server.h"
#include "target.h"
#include "queue.h"
+#include "common-notif.h"
/* Structure holding information related to a single event. We
keep a queue of these to push to GDB. It can be extended if
@@ -31,25 +32,26 @@ typedef struct notif_event
DECLARE_QUEUE_P (notif_event_p);
+/* An event of an annex of a notification. */
+
+struct notif_annex_event
+{
+ struct notif_event base;
+ /* The index of the annex in field 'annexes' in 'notif_server'. */
+ int annex_index;
+};
+
/* A type notification to GDB. An object of 'struct notif_server'
represents a type of notification. */
typedef struct notif_server
{
- /* The name of ack packet, for example, 'vStopped'. */
- const char *ack_name;
-
- /* The notification packet, for example, '%Stop'. Note that '%' is
- not in 'notif_name'. */
- const char *notif_name;
+ struct notif_base base;
/* A queue of events to GDB. A new notif_event can be enque'ed
into QUEUE at any appropriate time, and the notif_reply is
deque'ed only when the ack from GDB arrives. */
QUEUE (notif_event_p) *queue;
-
- /* Write event EVENT to OWN_BUF. */
- void (*write) (struct notif_event *event, char *own_buf);
} *notif_server_p;
extern struct notif_server notif_stop;
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index b149a1b..f98a780 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -183,9 +183,14 @@ vstop_notif_reply (struct notif_event *event, char *own_buf)
prepare_resume_reply (own_buf, vstop->ptid, &vstop->status);
}
+static struct notif_annex notif_annex_stop[] =
+{
+ { NULL, vstop_notif_reply, },
+};
+
struct notif_server notif_stop =
{
- "vStopped", "Stop", NULL, vstop_notif_reply,
+ { "Stop", "vStopped", notif_annex_stop, }, NULL,
};
static int
diff --git a/gdb/remote-notif.c b/gdb/remote-notif.c
index 1477879..e0bc745 100644
--- a/gdb/remote-notif.c
+++ b/gdb/remote-notif.c
@@ -53,6 +53,46 @@ static struct notif_client *notifs[] =
static void do_notif_event_xfree (void *arg);
+/* Iterate over annexes in NC to match chars in BUF. */
+
+static void
+remote_notif_parse_1 (struct notif_client *nc,
+ struct notif_event *event, char *buf)
+{
+ const struct notif_annex *m = NULL;
+ const struct notif_base *base = (struct notif_base *) nc;
+
+ if (NOTIF_HAS_ANNEX (base))
+ {
+ int i;
+
+ NOTIF_ITER_ANNEX (base, i)
+ {
+ m = &base->annexes[i];
+
+ if (strncmp (m->name, buf, strlen (base->notif_name)) == 0
+ /* The annex is separated by ':' for the rest of
+ contents in BUF. */
+ && buf[strlen (m->name)] == ':')
+ {
+ /* Pass BUF without annex and ':'. */
+ m->parse (nc, buf + strlen (m->name) + 1, event);
+ break;
+ }
+ m = NULL;
+ }
+ }
+ else
+ {
+ m = &base->annexes[0];
+ m->parse (nc, buf, event);
+ }
+
+ if (m == NULL)
+ error (_("Can't parse '%s' for notif '%s'"), buf,
+ base->notif_name);
+}
+
/* Parse the BUF for the expected notification NC, and send packet to
acknowledge. */
@@ -65,9 +105,9 @@ remote_notif_ack (struct notif_client *nc, char *buf)
if (notif_debug)
fprintf_unfiltered (gdb_stdlog, "notif: ack '%s'\n",
- nc->ack_command);
+ nc->base.ack_name);
- nc->parse (nc, buf, event);
+ remote_notif_parse_1 (nc, event, buf);
nc->ack (nc, buf, event);
discard_cleanups (old_chain);
@@ -83,9 +123,10 @@ remote_notif_parse (struct notif_client *nc, char *buf)
= make_cleanup (do_notif_event_xfree, event);
if (notif_debug)
- fprintf_unfiltered (gdb_stdlog, "notif: parse '%s'\n", nc->name);
+ fprintf_unfiltered (gdb_stdlog, "notif: parse '%s'\n",
+ nc->base.notif_name);
- nc->parse (nc, buf, event);
+ remote_notif_parse_1 (nc, event, buf);
discard_cleanups (old_chain);
return event;
@@ -158,8 +199,9 @@ handle_notification (char *buf)
for (i = 0; i < ARRAY_SIZE (notifs); i++)
{
nc = notifs[i];
- if (strncmp (buf, nc->name, strlen (nc->name)) == 0
- && buf[strlen (nc->name)] == ':')
+ if (0 == strncmp (buf, nc->base.notif_name,
+ strlen (nc->base.notif_name))
+ && buf[strlen (nc->base.notif_name)] == ':')
break;
nc = NULL;
}
@@ -181,7 +223,8 @@ handle_notification (char *buf)
else
{
struct notif_event *event
- = remote_notif_parse (nc, buf + strlen (nc->name) + 1);
+ = remote_notif_parse (nc,
+ buf + strlen (nc->base.notif_name) + 1);
/* Be careful to only set it after parsing, since an error
may be thrown then. */
@@ -234,7 +277,7 @@ handle_notification (char *buf)
if (notif_debug)
fprintf_unfiltered (gdb_stdlog,
"notif: Notification '%s' captured\n",
- nc->name);
+ nc->base.notif_name);
}
}
diff --git a/gdb/remote-notif.h b/gdb/remote-notif.h
index b2a9b8e..cb1636f 100644
--- a/gdb/remote-notif.h
+++ b/gdb/remote-notif.h
@@ -21,6 +21,7 @@
#define REMOTE_NOTIF_H
#include "queue.h"
+#include "common-notif.h"
/* An event of a type of async remote notification. */
@@ -35,17 +36,7 @@ struct notif_event
typedef struct notif_client
{
- /* The name of notification packet. */
- const char *name;
-
- /* The packet to acknowledge a previous reply. */
- const char *ack_command;
-
- /* Parse BUF to get the expected event and update EVENT. This
- function may throw exception if contents in BUF is not the
- expected event. */
- void (*parse) (struct notif_client *self, char *buf,
- struct notif_event *event);
+ struct notif_base base;
/* Send field <ack_command> to remote, and do some checking. If
something wrong, throw an exception. */
diff --git a/gdb/remote.c b/gdb/remote.c
index 7aebb80..92a0f27 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -5169,7 +5169,7 @@ remote_notif_stop_ack (struct notif_client *self, char *buf,
struct stop_reply *stop_reply = (struct stop_reply *) event;
/* acknowledge */
- putpkt ((char *) self->ack_command);
+ putpkt ((char *) self->base.ack_name);
if (stop_reply->ws.kind == TARGET_WAITKIND_IGNORE)
/* We got an unknown stop reply. */
@@ -5209,13 +5209,16 @@ remote_notif_stop_alloc_reply (void)
return r;
}
+static struct notif_annex notif_client_annex_stop[] =
+{
+ { NULL, remote_notif_stop_parse, },
+};
+
/* A client of notification Stop. */
struct notif_client notif_client_stop =
{
- "Stop",
- "vStopped",
- remote_notif_stop_parse,
+ { "Stop", "vStopped", notif_client_annex_stop, },
remote_notif_stop_ack,
remote_notif_stop_can_get_pending_events,
remote_notif_stop_alloc_reply,
@@ -5642,7 +5645,7 @@ remote_notif_get_pending_events (struct notif_client *nc)
if (notif_debug)
fprintf_unfiltered (gdb_stdlog,
"notif: process: '%s' ack pending event\n",
- nc->name);
+ nc->base.notif_name);
/* acknowledge */
nc->ack (nc, rs->buf, nc->pending_event);
@@ -5662,7 +5665,7 @@ remote_notif_get_pending_events (struct notif_client *nc)
if (notif_debug)
fprintf_unfiltered (gdb_stdlog,
"notif: process: '%s' no pending reply\n",
- nc->name);
+ nc->base.notif_name);
}
}
--
1.7.7.6
^ permalink raw reply [flat|nested] 43+ messages in thread* Re: [PATCH 1/5] Add annex in a async remote notification.
2013-01-22 7:05 ` [PATCH 1/5] Add annex in a async remote notification Yao Qi
@ 2013-01-22 8:06 ` Eli Zaretskii
2013-02-16 3:40 ` Yao Qi
0 siblings, 1 reply; 43+ messages in thread
From: Eli Zaretskii @ 2013-01-22 8:06 UTC (permalink / raw)
To: Yao Qi; +Cc: gdb-patches
> From: Yao Qi <yao@codesourcery.com>
> Date: Tue, 22 Jan 2013 15:03:48 +0800
>
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
> @@ -38604,13 +38604,15 @@ transmit notifications without fear of confusing older clients. There
> are no notifications defined for @value{GDBN} to send at the moment, but we
> assume that most older stubs would ignore them, as well.)
>
> -Each notification is comprised of three parts:
> +Each notification is comprised of four parts:
> @table @samp
> -@item @var{name}:@var{event}
> +@item @var{name}[:@var{annex}]:@var{event}
Is it a good idea to have the optional part in the middle? If there
are MI clients out there that support the previous form, they might
now confuse ANNEX to be an EVENT.
The documentation patch in this changeset is OK with me.
^ permalink raw reply [flat|nested] 43+ messages in thread* Re: [PATCH 1/5] Add annex in a async remote notification.
2013-01-22 8:06 ` Eli Zaretskii
@ 2013-02-16 3:40 ` Yao Qi
2013-02-16 9:27 ` Eli Zaretskii
0 siblings, 1 reply; 43+ messages in thread
From: Yao Qi @ 2013-02-16 3:40 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: gdb-patches
On 01/22/2013 04:05 PM, Eli Zaretskii wrote:
> Is it a good idea to have the optional part in the middle? If there
> are MI clients out there that support the previous form, they might
> now confuse ANNEX to be an EVENT.
It can't be confused. The "optional" here means some notifications have
annexes and some don't. Given an notification, the annexes of it are
determined, and annex is separated with event by ":".
--
Yao (é½å°§)
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 1/5] Add annex in a async remote notification.
2013-02-16 3:40 ` Yao Qi
@ 2013-02-16 9:27 ` Eli Zaretskii
2013-03-29 17:17 ` Yao Qi
0 siblings, 1 reply; 43+ messages in thread
From: Eli Zaretskii @ 2013-02-16 9:27 UTC (permalink / raw)
To: Yao Qi; +Cc: gdb-patches
> Date: Sat, 16 Feb 2013 11:35:18 +0800
> From: Yao Qi <yao@codesourcery.com>
> CC: <gdb-patches@sourceware.org>
>
> On 01/22/2013 04:05 PM, Eli Zaretskii wrote:
> > Is it a good idea to have the optional part in the middle? If there
> > are MI clients out there that support the previous form, they might
> > now confuse ANNEX to be an EVENT.
>
> It can't be confused. The "optional" here means some notifications have
> annexes and some don't. Given an notification, the annexes of it are
> determined, and annex is separated with event by ":".
Sorry, I don't follow your reasoning.
My concern was about the following use case:
. an old MI client that only supports the old "name:event" form
. a notification is sent in the new form "name:annex:event"
. the MI client only parses the first 2 parts, and confuses "annex"
for "event"
How can we be sure this can never happen? We have no idea what MI
clients are out there, they are out of control of GDB development.
^ permalink raw reply [flat|nested] 43+ messages in thread* Re: [PATCH 1/5] Add annex in a async remote notification.
2013-02-16 9:27 ` Eli Zaretskii
@ 2013-03-29 17:17 ` Yao Qi
2013-03-31 0:39 ` Eli Zaretskii
0 siblings, 1 reply; 43+ messages in thread
From: Yao Qi @ 2013-03-29 17:17 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: gdb-patches
[Eli, sorry for missing this mail. Find it hide in the thread when I
have a chance to revisit this patch series.]
On 02/16/2013 05:26 PM, Eli Zaretskii wrote:
> Sorry, I don't follow your reasoning.
>
> My concern was about the following use case:
>
> . an old MI client that only supports the old "name:event" form
>
> . a notification is sent in the new form "name:annex:event"
>
> . the MI client only parses the first 2 parts, and confuses "annex"
> for "event"
>
> How can we be sure this can never happen? We have no idea what MI
> clients are out there, they are out of control of GDB development.
Patch 2/5 (Query supported notifications by qSupported) is to address
this issue. When GDB connects to the remote stub, they will exchange
the supported annexes. As a result, the new form "name:annex:event"
shouldn't be sent out if the other side doesn't support it. Does it
answer your question?
--
Yao (é½å°§)
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 1/5] Add annex in a async remote notification.
2013-03-29 17:17 ` Yao Qi
@ 2013-03-31 0:39 ` Eli Zaretskii
0 siblings, 0 replies; 43+ messages in thread
From: Eli Zaretskii @ 2013-03-31 0:39 UTC (permalink / raw)
To: Yao Qi; +Cc: gdb-patches
> Date: Sat, 30 Mar 2013 00:17:48 +0800
> From: Yao Qi <yao@codesourcery.com>
> CC: <gdb-patches@sourceware.org>
>
> Patch 2/5 (Query supported notifications by qSupported) is to address
> this issue. When GDB connects to the remote stub, they will exchange
> the supported annexes. As a result, the new form "name:annex:event"
> shouldn't be sent out if the other side doesn't support it. Does it
> answer your question?
Yes, thanks.
^ permalink raw reply [flat|nested] 43+ messages in thread
* [PATCH 4/5] MI notification on trace started/stopped:basic
2013-01-22 7:05 [PATCH 0/5] MI notification on trace started/stopped (V3) Yao Qi
` (2 preceding siblings ...)
2013-01-22 7:05 ` [PATCH 1/5] Add annex in a async remote notification Yao Qi
@ 2013-01-22 7:06 ` Yao Qi
2013-01-22 8:11 ` Eli Zaretskii
2013-01-22 7:06 ` [PATCH 5/5] MI notification on trace stop: triggered by remote Yao Qi
` (3 subsequent siblings)
7 siblings, 1 reply; 43+ messages in thread
From: Yao Qi @ 2013-01-22 7:06 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?
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 49d8447..ddeed5c 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -128,6 +128,8 @@ show print type typedefs
** The response to breakpoint commands and breakpoint async records
includes an "installed" field containing a boolean state about each
non-pending tracepoint location is whether installed on target or not.
+ ** The start and stop of trace are now notified using new async records
+ "=trace-started" and "=trace-stopped".
* GDB now supports the "mini debuginfo" section, .gnu_debugdata.
You must have the LZMA library available when configuring GDB for this
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index c41310d..f1ac4e1 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -27967,6 +27967,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 87c08e1..2f3c99c 100644
--- a/gdb/doc/observer.texi
+++ b/gdb/doc/observer.texi
@@ -246,6 +246,12 @@ The trace state variable @var{name} is deleted. If @var{name} is
@code{NULL}, all trace state variables are deleted.
@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 true, and the trace is stopped if @var{started} is
+false.
+@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 df173fe..f2c037d 100644
--- a/gdb/mi/mi-cmds.c
+++ b/gdb/mi/mi-cmds.c
@@ -146,9 +146,11 @@ static struct mi_cmd mi_cmds[] =
&mi_suppress_notification.traceframe),
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 6617647..a74d782 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -67,6 +67,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);
@@ -131,6 +132,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);
@@ -594,6 +596,26 @@ mi_tsv_deleted (const char *name)
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 be45cb4..39b3822 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -1819,6 +1819,8 @@ start_tracing (char *notes)
/* Now insert traps and begin collecting data. */
target_trace_start ();
+ observer_notify_trace_changed (1);
+
/* Reset our local state. */
set_traceframe_num (-1);
set_tracepoint_num (-1);
@@ -1904,6 +1906,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] 43+ messages in thread* Re: [PATCH 4/5] MI notification on trace started/stopped:basic
2013-01-22 7:06 ` [PATCH 4/5] MI notification on trace started/stopped:basic Yao Qi
@ 2013-01-22 8:11 ` Eli Zaretskii
0 siblings, 0 replies; 43+ messages in thread
From: Eli Zaretskii @ 2013-01-22 8:11 UTC (permalink / raw)
To: Yao Qi; +Cc: gdb-patches
> From: Yao Qi <yao@codesourcery.com>
> Date: Tue, 22 Jan 2013 15:03:51 +0800
>
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -128,6 +128,8 @@ show print type typedefs
> ** The response to breakpoint commands and breakpoint async records
> includes an "installed" field containing a boolean state about each
> non-pending tracepoint location is whether installed on target or not.
> + ** The start and stop of trace are now notified using new async records
> + "=trace-started" and "=trace-stopped".
OK.
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
> @@ -27967,6 +27967,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
OK.
> --- a/gdb/doc/observer.texi
> +++ b/gdb/doc/observer.texi
> @@ -246,6 +246,12 @@ The trace state variable @var{name} is deleted. If @var{name} is
> @code{NULL}, all trace state variables are deleted.
> @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 true, and the trace is stopped if @var{started} is
> +false.
"true" and "false" or "non-zero" and "zero"? This is C, and we don't
use the boolean types in the above deftypefun.
Thanks.
^ permalink raw reply [flat|nested] 43+ messages in thread
* [PATCH 5/5] MI notification on trace stop: triggered by remote
2013-01-22 7:05 [PATCH 0/5] MI notification on trace started/stopped (V3) Yao Qi
` (3 preceding siblings ...)
2013-01-22 7:06 ` [PATCH 4/5] MI notification on trace started/stopped:basic Yao Qi
@ 2013-01-22 7:06 ` Yao Qi
2013-01-30 4:00 ` [ping]: [PATCH 0/5] MI notification on trace started/stopped (V3) Yao Qi
` (2 subsequent siblings)
7 siblings, 0 replies; 43+ messages in thread
From: Yao Qi @ 2013-01-22 7:06 UTC (permalink / raw)
To: gdb-patches
As a result of previous patch, GDB has a Trace rsp notification.
In this patch, GDB starts to use Trace notification, and emits MI
notification '=trace-stopped' to front-end. A test case is
added to see if MI trace-stopped notification is emitted when trace
buffer is full.
gdb:
2013-01-21 Yao Qi <yao@codesourcery.com>
* remote-notif-trace.c: Include "observer.h".
(remote_notif_trace_status_parse): Call
observer_notify_trace_changed.
gdb/testsuite:
2013-01-21 Yao Qi <yao@codesourcery.com>
* gdb.trace/mi-trace-changed.exp (test_trace_buffer_full): New.
---
gdb/remote-notif-trace.c | 11 ++++
gdb/testsuite/gdb.trace/mi-trace-changed.exp | 75 ++++++++++++++++++++++++++
2 files changed, 86 insertions(+), 0 deletions(-)
diff --git a/gdb/remote-notif-trace.c b/gdb/remote-notif-trace.c
index a0cfa26..8c1e8a8 100644
--- a/gdb/remote-notif-trace.c
+++ b/gdb/remote-notif-trace.c
@@ -22,6 +22,7 @@
#include "remote.h"
#include "tracepoint.h"
#include "remote-notif.h"
+#include "observer.h"
static void
remote_notif_trace_status_parse (struct notif_client *self, char *buf,
@@ -31,6 +32,16 @@ remote_notif_trace_status_parse (struct notif_client *self, char *buf,
gdb_assert (buf[0] == 'T');
parse_trace_status (buf + 1, ts);
+
+ /* When the tracing is stopped, there is no changes anymore in
+ the trace, so the remote stub can't send another notification.
+ We don't have to worry about notifying 'trace_changed' observer
+ with argument 1 twice.
+ The remote stub can't request tracing start and the remote stub
+ may send multiple trace notifications on various status changes,
+ we don't notify 'trace_changed' observer with argument 0. */
+ if (!ts->running)
+ observer_notify_trace_changed (0);
}
static void
diff --git a/gdb/testsuite/gdb.trace/mi-trace-changed.exp b/gdb/testsuite/gdb.trace/mi-trace-changed.exp
index fbd6fe7..9d6cfff 100644
--- a/gdb/testsuite/gdb.trace/mi-trace-changed.exp
+++ b/gdb/testsuite/gdb.trace/mi-trace-changed.exp
@@ -71,4 +71,79 @@ proc test_normal_tstart_stop { } {
test_normal_tstart_stop
+# Verify that MI notification '=trace-stopped' is emitted when trace
+# buffer is full.
+
+proc test_trace_buffer_full { } {
+ with_test_prefix "tracebuffer full" {
+ global mi_gdb_prompt
+
+ if [mi_gdb_start] {
+ return
+ }
+ mi_run_to_main
+
+ mi_gdb_test "-break-insert -a func2" {.*\^done,bkpt=.*} \
+ "insert tracepoint on func2"
+
+ send_gdb "actions\n"
+ gdb_expect {
+ -re "End with" {
+ }
+ }
+
+ send_gdb "collect buf\nend\n"
+ set test "define actions"
+ gdb_expect {
+ -re ".*${mi_gdb_prompt}$" {
+ pass $test
+ }
+ timeout {
+ fail "$test (timeout)"
+ }
+ }
+
+ # 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 "-break-insert end" {.*\^done,bkpt=.*} \
+ "insert breakpoint on end"
+
+ mi_send_resuming_command "exec-continue" \
+ "continuing execution to end"
+
+ set test "trace-stopped triggered by bufferfull"
+ gdb_expect {
+ # We don't set stop-notes.
+ -re "=trace-stopped\\\\n" {
+ pass "$test"
+ }
+ timeout {
+ fail "$test (timeout)"
+ }
+ }
+
+ global async
+ # In sync mode, eat all the output. Don't have to do so in
+ # async mode.
+ if {!$async} {
+ gdb_expect {
+ -re ".*${mi_gdb_prompt}$" {
+ }
+ }
+ }
+ # GDB has got the rsp notifcation from remote stub that trace
+ # is stopped.
+ mi_gdb_test "tstop" ".*Trace is not running.*" \
+ "tstop on stopped"
+
+ mi_gdb_test "-trace-status" ".*\\^done.*stop-reason=\"overflow\".*" \
+ "trace-status"
+
+ mi_gdb_exit
+ }
+}
+
+test_trace_buffer_full
+
return 0
--
1.7.7.6
^ permalink raw reply [flat|nested] 43+ messages in thread* [ping]: [PATCH 0/5] MI notification on trace started/stopped (V3)
2013-01-22 7:05 [PATCH 0/5] MI notification on trace started/stopped (V3) Yao Qi
` (4 preceding siblings ...)
2013-01-22 7:06 ` [PATCH 5/5] MI notification on trace stop: triggered by remote Yao Qi
@ 2013-01-30 4:00 ` Yao Qi
2013-02-07 12:41 ` [ping 2]: " Yao Qi
2013-02-16 4:01 ` [PATCH 0/5] MI notification on trace started/stopped (V3.1) Yao Qi
2013-04-02 2:33 ` [PATCH v4 0/5] MI notification on trace started/stopped Yao Qi
7 siblings, 1 reply; 43+ messages in thread
From: Yao Qi @ 2013-01-30 4:00 UTC (permalink / raw)
To: gdb-patches
On 01/22/2013 03:03 PM, Yao Qi wrote:
> Hello,
> This patch series adds the MI notifications of 'trace-started' and
> 'trace-stopped', which are emitted when
>
> 1) trace is started or stopped by commands in GDB,
> 2) trace is stopped due to some reasons in the remote stub, such as
> trace buffer full.
>
> With these notifications, MI front-end can show the status of trace
> up to date.
>
> Patch 4/5 is to address #1, adding new MI notifications and
> notifying observers when the commands are called. #2 needs more work
> here, because GDB doesn't know the trace is stopped in the remote
> stub. So we need an async remote notification 'Trace' to tell GDB.
> That is what patch 3/5 about. Patch 5/5 is to use this async remote
> notification 'Trace' and notify trace_changed observer.
>
> Patch 1/5 and 2/5 are the enhancement to the async remote
> notification, which is needed by the rest of patches in this series.
> Patch 1/5 adds "annex" for notification, which is helpful 1) to give
> more information on each event of notification, 2) to query supported
> notifications on "annex" level. Patch 2/5 teaches both GDB and
> GDBserver to query supported notifications and annexes in the other
> side so that 1) GDBserver doesn't send notifications that GDB doesn't
> understand, 2) GDB doesn't have to fetch status from the GDBserver if
> a certain notification is supported by GDBserver.
>
> This patch series is the V3 of this series. V2 was posted
> <http://sourceware.org/ml/gdb-patches/2012-12/msg00687.html>. Here
> are some changes in V3,
>
> - Introduce query mechanism on supported notifications
> - Introduce concept "annex" into remote notification,
> - Remove trace notes in MI notifications, suggested by Pedro in the
> review.
> - Combine observers 'trace-started' and 'trace-stoped' into one
> observer 'trace-changed'.
>
> Each patch is tested cumulatively on x86_64-linux with the combination
> {unix, native-gdbserver} x {sync, async}. Is it OK?
>
Ping. http://sourceware.org/ml/gdb-patches/2013-01/msg00505.html
--
Yao (é½å°§)
^ permalink raw reply [flat|nested] 43+ messages in thread* [PATCH 0/5] MI notification on trace started/stopped (V3.1)
2013-01-22 7:05 [PATCH 0/5] MI notification on trace started/stopped (V3) Yao Qi
` (5 preceding siblings ...)
2013-01-30 4:00 ` [ping]: [PATCH 0/5] MI notification on trace started/stopped (V3) Yao Qi
@ 2013-02-16 4:01 ` Yao Qi
2013-02-16 4:01 ` [PATCH 1/5] Add annex in a async remote notification Yao Qi
` (6 more replies)
2013-04-02 2:33 ` [PATCH v4 0/5] MI notification on trace started/stopped Yao Qi
7 siblings, 7 replies; 43+ messages in thread
From: Yao Qi @ 2013-02-16 4:01 UTC (permalink / raw)
To: gdb-patches
On 01/22/2013 03:03 PM, Yao Qi wrote:
> This patch series is the V3 of this series. V2 was posted
> <http://sourceware.org/ml/gdb-patches/2012-12/msg00687.html>. Here
> are some changes in V3,
>
> - Introduce query mechanism on supported notifications
> - Introduce concept "annex" into remote notification,
> - Remove trace notes in MI notifications, suggested by Pedro in the
> review.
> - Combine observers 'trace-started' and 'trace-stoped' into one
> observer 'trace-changed'.
The V3 can't be applied to CVS trunk without conflicts, so I resolved
these conflicts, rebase patches to CVS trunk, and post them again.
Beside this, I also add some comments here and there in the patches.
Regression tested them on x86_64-linux with the combination
{unix, native-gdbserver} x {sync, async}. Is it OK?
All doc bits were reviewed by Eli in V3.
--
1.7.7.6
^ permalink raw reply [flat|nested] 43+ messages in thread* [PATCH 1/5] Add annex in a async remote notification.
2013-02-16 4:01 ` [PATCH 0/5] MI notification on trace started/stopped (V3.1) Yao Qi
@ 2013-02-16 4:01 ` Yao Qi
2013-02-16 9:27 ` Eli Zaretskii
2013-02-16 4:02 ` [PATCH 2/5] Query supported notifications by qSupported Yao Qi
` (5 subsequent siblings)
6 siblings, 1 reply; 43+ messages in thread
From: Yao Qi @ 2013-02-16 4:01 UTC (permalink / raw)
To: gdb-patches
In order to support "Trace:status" notification and other similar
usage (such as "Point:modified", about a tracepoint is modified), we
introduce "annex" in the async remote notification, which is helpful
to give us more details what the contents about in the async remote
notification. The annex in each notification is optional. In the
RSP:
<-- %name:annex1:event
--> vAck
<-- annex2:event
--> vAck
<-- annex1:event
--> OK
As we can see above, three events of two annexes (annex1 and annex2)
are sent.
The parsing (receiving rsp packet) and writing (sending rsp packet)
can be done on the annex level. Each annex has its own routines to
send and parse packet, which is more OO.
Also, annex, instead of notification, is the unit of support and they
(GDB and GDBserver) can exchange their supported annexes by means of
qSupported mechanism, which is done in the next patch.
This patch adds "annex" to both GDB and GDBserver. I find 'struct
notif_client' and 'struct notif_server' have three fields which can be
shared, so additionally, we move some shared struct to
common/common-notif.h.
gdb:
2013-02-16 Yao Qi <yao@codesourcery.com>
* common/common-notif.h: New.
* Makefile.in (HFILES_NO_SRCDIR): Add "common/common-notif.h".
* remote-notif.h: Include "common-notif.h".
(struct notif_client) <name, ack_command, parse>: Remove.
<base>: New.
Caller update.
* remote-notif.c (remote_notif_parse_1): New.
(remote_notif_ack): Call remote_notif_parse_1.
(remote_notif_parse): Likewise.
(struct notif_client_annex): New.
* remote.c (notif_client_annex_stop): New.
gdb/gdbserver:
2013-02-16 Yao Qi <yao@codesourcery.com>
* notif.h: Include "common-notif.h".
(struct notif_server) <write, ack_name, notif_name>: Remove.
<base>: New field.
Caller update.
(struct notif_annex_event): New.
* notif.c (notif_write_event_1): New.
(notif_write_event): Call notif_write_event_1 to write event.
(notif_push): Likewise.
* server.c (notif_annex_stop): New.
(notif_stop): Update.
gdb/doc:
2013-02-16 Yao Qi <yao@codesourcery.com>
* gdb.texinfo (Notification Packets): Document 'annex'.
---
gdb/Makefile.in | 2 +-
gdb/common/common-notif.h | 73 +++++++++++++++++++++++++++++++++++++++++++++
gdb/doc/gdb.texinfo | 12 +++++--
gdb/gdbserver/notif.c | 40 ++++++++++++++++++++----
gdb/gdbserver/notif.h | 20 +++++++-----
gdb/gdbserver/server.c | 7 ++++-
gdb/remote-notif.c | 59 +++++++++++++++++++++++++++++++-----
gdb/remote-notif.h | 13 +-------
gdb/remote.c | 15 +++++----
9 files changed, 194 insertions(+), 47 deletions(-)
create mode 100644 gdb/common/common-notif.h
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index ed30db5..a6ff9c3 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -835,7 +835,7 @@ gnulib/import/stddef.in.h gnulib/import/inttypes.in.h inline-frame.h skip.h \
common/common-utils.h common/xml-utils.h common/buffer.h common/ptid.h \
common/format.h common/host-defs.h utils.h common/queue.h \
common/linux-osdata.h gdb-dlfcn.h auto-load.h probe.h stap-probe.h \
-gdb_bfd.h sparc-ravenscar-thread.h ppc-ravenscar-thread.h
+gdb_bfd.h sparc-ravenscar-thread.h ppc-ravenscar-thread.h common/common-notif.h
# Header files that already have srcdir in them, or which are in objdir.
diff --git a/gdb/common/common-notif.h b/gdb/common/common-notif.h
new file mode 100644
index 0000000..1ffa26c
--- /dev/null
+++ b/gdb/common/common-notif.h
@@ -0,0 +1,73 @@
+/* Shared structs of asynchronous remote notification.
+
+ 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/>. */
+
+struct notif_event;
+#ifndef GDBSERVER
+struct notif_client;
+#endif
+
+/* An annex of a notification. A notification may or may not have
+ annexes. */
+
+struct notif_annex
+{
+ /* Name of this annex. If it is NULL, the notification doesn't have
+ annex, and the field PARSE and SUPPORTED is about the
+ notification this annex belongs to. */
+ const char *name;
+
+#ifdef GDBSERVER
+ /* Write event EVENT to OWN_BUF. */
+ void (*write) (struct notif_event *event, char *own_buf);
+#else
+ /* Parse BUF to get the expected event and update EVENT. This
+ function may throw exception if contents in BUF is not the
+ expected event. */
+ void (*parse) (struct notif_client *self, char *buf,
+ struct notif_event *event);
+#endif
+};
+
+/* Iterate over annexes in *NOTIF by increasing INDEX from zero. */
+
+#define NOTIF_ITER_ANNEX(NOTIF, INDEX) \
+ for (INDEX = 0; (NOTIF)->annexes[INDEX].name != NULL; INDEX++)
+
+/* Notification *NOTIF has annex or not. */
+
+#define NOTIF_HAS_ANNEX(NOTIF) ((NOTIF)->annexes[0].name != NULL)
+
+
+/* "Base class" of a notification. It can be extended in both GDB
+ and GDBserver to represent a type of notification. */
+
+struct notif_base
+{
+ /* The notification packet, for example, '%Stop'. Note that '%' is
+ not in 'notif_name'. */
+ const char *notif_name;
+ /* The name of ack packet, for example, 'vStopped'. */
+ const char *ack_name;
+
+ /* Annexes the notification has. The notification may or not have
+ annexes. Macro 'NOTIF_HAS_ANNEX' is to check notification has
+ annexes, and macro 'NOTIF_ITER_ANNEX' is to iterate over annexes
+ of the notification. */
+ struct notif_annex *annexes;
+};
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index e3f336e..68b81a2 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -38693,13 +38693,15 @@ transmit notifications without fear of confusing older clients. There
are no notifications defined for @value{GDBN} to send at the moment, but we
assume that most older stubs would ignore them, as well.)
-Each notification is comprised of three parts:
+Each notification is comprised of four parts:
@table @samp
-@item @var{name}:@var{event}
+@item @var{name}[:@var{annex}]:@var{event}
The notification packet is sent by the side that initiates the
exchange (currently, only the stub does that), with @var{event}
carrying the specific information about the notification.
-@var{name} is the name of the notification.
+@var{name} is the name of the notification. The @var{annex} is
+specific to @var{name}; it can supply additional details about
+@var{event}.
@item @var{ack}
The acknowledge sent by the other side, usually @value{GDBN}, to
acknowledge the exchange and request the event.
@@ -38762,15 +38764,17 @@ following example:
@end smallexample
The following notifications are defined:
-@multitable @columnfractions 0.12 0.12 0.38 0.38
+@multitable @columnfractions 0.10 0.10 0.10 0.35 0.35
@item Notification
@tab Ack
+@tab Annex
@tab Event
@tab Description
@item Stop
@tab vStopped
+@tab
@tab @var{reply}. The @var{reply} has the form of a stop reply, as
described in @ref{Stop Reply Packets}. Refer to @ref{Remote Non-Stop},
for information on how these notifications are acknowledged by
diff --git a/gdb/gdbserver/notif.c b/gdb/gdbserver/notif.c
index e27746e..168f77d 100644
--- a/gdb/gdbserver/notif.c
+++ b/gdb/gdbserver/notif.c
@@ -54,6 +54,29 @@ static struct notif_server *notifs[] =
¬if_stop,
};
+/* Helper function to write EVENT of NOTIF to buffer OWN_BUF. */
+
+static void
+notif_write_event_1 (struct notif_base *notif,
+ struct notif_event *event,
+ char *own_buf)
+{
+ int annex_index = 0;
+
+ /* If the NOTIF has annexes, extract the annex index from the
+ EVENT and append annex name to OWN_BUF; otherwise, NOTIF
+ doesn't have annex and use slot 0 of annexes. */
+ if (NOTIF_HAS_ANNEX (notif))
+ {
+ annex_index
+ = ((struct notif_annex_event *) event)->annex_index;
+ sprintf (own_buf, "%s:", notif->annexes[annex_index].name);
+ own_buf += strlen (notif->annexes[annex_index].name) + 1;
+ }
+
+ notif->annexes[annex_index].write (event, own_buf);
+}
+
/* Write another event or an OK, if there are no more left, to
OWN_BUF. */
@@ -65,7 +88,8 @@ notif_write_event (struct notif_server *notif, char *own_buf)
struct notif_event *event
= QUEUE_peek (notif_event_p, notif->queue);
- notif->write (event, own_buf);
+ notif_write_event_1 ((struct notif_base *) notif, event,
+ own_buf);
}
else
write_ok (own_buf);
@@ -84,8 +108,9 @@ handle_notif_ack (char *own_buf, int packet_len)
for (i = 0; i < ARRAY_SIZE (notifs); i++)
{
np = notifs[i];
- if (strncmp (own_buf, np->ack_name, strlen (np->ack_name)) == 0
- && packet_len == strlen (np->ack_name))
+ if (0 == strncmp (own_buf, np->base.ack_name,
+ strlen (np->base.ack_name))
+ && packet_len == strlen (np->base.ack_name))
break;
}
@@ -100,7 +125,7 @@ handle_notif_ack (char *own_buf, int packet_len)
= QUEUE_deque (notif_event_p, np->queue);
if (remote_debug)
- fprintf (stderr, "%s: acking %d\n", np->ack_name,
+ fprintf (stderr, "%s: acking %d\n", np->base.ack_name,
QUEUE_length (notif_event_p, np->queue));
xfree (head);
@@ -120,7 +145,8 @@ notif_event_enque (struct notif_server *notif,
QUEUE_enque (notif_event_p, notif->queue, event);
if (remote_debug)
- fprintf (stderr, "pending events: %s %d\n", notif->notif_name,
+ fprintf (stderr, "pending events: %s %d\n",
+ notif->base.notif_name,
QUEUE_length (notif_event_p, notif->queue));
}
@@ -142,10 +168,10 @@ notif_push (struct notif_server *np, struct notif_event *new_event)
char buf[PBUFSIZ];
char *p = buf;
- xsnprintf (p, PBUFSIZ, "%s:", np->notif_name);
+ xsnprintf (p, PBUFSIZ, "%s:", np->base.notif_name);
p += strlen (p);
- np->write (new_event, p);
+ notif_write_event_1 ((struct notif_base *) np, new_event, p);
putpkt_notif (buf);
}
}
diff --git a/gdb/gdbserver/notif.h b/gdb/gdbserver/notif.h
index 608b763..5f9b6bc 100644
--- a/gdb/gdbserver/notif.h
+++ b/gdb/gdbserver/notif.h
@@ -20,6 +20,7 @@
#include "server.h"
#include "target.h"
#include "queue.h"
+#include "common-notif.h"
/* Structure holding information related to a single event. We
keep a queue of these to push to GDB. It can be extended if
@@ -31,25 +32,26 @@ typedef struct notif_event
DECLARE_QUEUE_P (notif_event_p);
+/* An event of an annex of a notification. */
+
+struct notif_annex_event
+{
+ struct notif_event base;
+ /* The index of the annex in field 'annexes' in 'notif_server'. */
+ int annex_index;
+};
+
/* A type notification to GDB. An object of 'struct notif_server'
represents a type of notification. */
typedef struct notif_server
{
- /* The name of ack packet, for example, 'vStopped'. */
- const char *ack_name;
-
- /* The notification packet, for example, '%Stop'. Note that '%' is
- not in 'notif_name'. */
- const char *notif_name;
+ struct notif_base base;
/* A queue of events to GDB. A new notif_event can be enque'ed
into QUEUE at any appropriate time, and the notif_reply is
deque'ed only when the ack from GDB arrives. */
QUEUE (notif_event_p) *queue;
-
- /* Write event EVENT to OWN_BUF. */
- void (*write) (struct notif_event *event, char *own_buf);
} *notif_server_p;
extern struct notif_server notif_stop;
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index 775d9ef..3e8ef0a 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -183,9 +183,14 @@ vstop_notif_reply (struct notif_event *event, char *own_buf)
prepare_resume_reply (own_buf, vstop->ptid, &vstop->status);
}
+static struct notif_annex notif_annex_stop[] =
+{
+ { NULL, vstop_notif_reply, },
+};
+
struct notif_server notif_stop =
{
- "vStopped", "Stop", NULL, vstop_notif_reply,
+ { "Stop", "vStopped", notif_annex_stop, }, NULL,
};
static int
diff --git a/gdb/remote-notif.c b/gdb/remote-notif.c
index 1477879..e0bc745 100644
--- a/gdb/remote-notif.c
+++ b/gdb/remote-notif.c
@@ -53,6 +53,46 @@ static struct notif_client *notifs[] =
static void do_notif_event_xfree (void *arg);
+/* Iterate over annexes in NC to match chars in BUF. */
+
+static void
+remote_notif_parse_1 (struct notif_client *nc,
+ struct notif_event *event, char *buf)
+{
+ const struct notif_annex *m = NULL;
+ const struct notif_base *base = (struct notif_base *) nc;
+
+ if (NOTIF_HAS_ANNEX (base))
+ {
+ int i;
+
+ NOTIF_ITER_ANNEX (base, i)
+ {
+ m = &base->annexes[i];
+
+ if (strncmp (m->name, buf, strlen (base->notif_name)) == 0
+ /* The annex is separated by ':' for the rest of
+ contents in BUF. */
+ && buf[strlen (m->name)] == ':')
+ {
+ /* Pass BUF without annex and ':'. */
+ m->parse (nc, buf + strlen (m->name) + 1, event);
+ break;
+ }
+ m = NULL;
+ }
+ }
+ else
+ {
+ m = &base->annexes[0];
+ m->parse (nc, buf, event);
+ }
+
+ if (m == NULL)
+ error (_("Can't parse '%s' for notif '%s'"), buf,
+ base->notif_name);
+}
+
/* Parse the BUF for the expected notification NC, and send packet to
acknowledge. */
@@ -65,9 +105,9 @@ remote_notif_ack (struct notif_client *nc, char *buf)
if (notif_debug)
fprintf_unfiltered (gdb_stdlog, "notif: ack '%s'\n",
- nc->ack_command);
+ nc->base.ack_name);
- nc->parse (nc, buf, event);
+ remote_notif_parse_1 (nc, event, buf);
nc->ack (nc, buf, event);
discard_cleanups (old_chain);
@@ -83,9 +123,10 @@ remote_notif_parse (struct notif_client *nc, char *buf)
= make_cleanup (do_notif_event_xfree, event);
if (notif_debug)
- fprintf_unfiltered (gdb_stdlog, "notif: parse '%s'\n", nc->name);
+ fprintf_unfiltered (gdb_stdlog, "notif: parse '%s'\n",
+ nc->base.notif_name);
- nc->parse (nc, buf, event);
+ remote_notif_parse_1 (nc, event, buf);
discard_cleanups (old_chain);
return event;
@@ -158,8 +199,9 @@ handle_notification (char *buf)
for (i = 0; i < ARRAY_SIZE (notifs); i++)
{
nc = notifs[i];
- if (strncmp (buf, nc->name, strlen (nc->name)) == 0
- && buf[strlen (nc->name)] == ':')
+ if (0 == strncmp (buf, nc->base.notif_name,
+ strlen (nc->base.notif_name))
+ && buf[strlen (nc->base.notif_name)] == ':')
break;
nc = NULL;
}
@@ -181,7 +223,8 @@ handle_notification (char *buf)
else
{
struct notif_event *event
- = remote_notif_parse (nc, buf + strlen (nc->name) + 1);
+ = remote_notif_parse (nc,
+ buf + strlen (nc->base.notif_name) + 1);
/* Be careful to only set it after parsing, since an error
may be thrown then. */
@@ -234,7 +277,7 @@ handle_notification (char *buf)
if (notif_debug)
fprintf_unfiltered (gdb_stdlog,
"notif: Notification '%s' captured\n",
- nc->name);
+ nc->base.notif_name);
}
}
diff --git a/gdb/remote-notif.h b/gdb/remote-notif.h
index b2a9b8e..cb1636f 100644
--- a/gdb/remote-notif.h
+++ b/gdb/remote-notif.h
@@ -21,6 +21,7 @@
#define REMOTE_NOTIF_H
#include "queue.h"
+#include "common-notif.h"
/* An event of a type of async remote notification. */
@@ -35,17 +36,7 @@ struct notif_event
typedef struct notif_client
{
- /* The name of notification packet. */
- const char *name;
-
- /* The packet to acknowledge a previous reply. */
- const char *ack_command;
-
- /* Parse BUF to get the expected event and update EVENT. This
- function may throw exception if contents in BUF is not the
- expected event. */
- void (*parse) (struct notif_client *self, char *buf,
- struct notif_event *event);
+ struct notif_base base;
/* Send field <ack_command> to remote, and do some checking. If
something wrong, throw an exception. */
diff --git a/gdb/remote.c b/gdb/remote.c
index 608f6be..b4a8d24 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -5224,7 +5224,7 @@ remote_notif_stop_ack (struct notif_client *self, char *buf,
struct stop_reply *stop_reply = (struct stop_reply *) event;
/* acknowledge */
- putpkt ((char *) self->ack_command);
+ putpkt ((char *) self->base.ack_name);
if (stop_reply->ws.kind == TARGET_WAITKIND_IGNORE)
/* We got an unknown stop reply. */
@@ -5264,13 +5264,16 @@ remote_notif_stop_alloc_reply (void)
return r;
}
+static struct notif_annex notif_client_annex_stop[] =
+{
+ { NULL, remote_notif_stop_parse, },
+};
+
/* A client of notification Stop. */
struct notif_client notif_client_stop =
{
- "Stop",
- "vStopped",
- remote_notif_stop_parse,
+ { "Stop", "vStopped", notif_client_annex_stop, },
remote_notif_stop_ack,
remote_notif_stop_can_get_pending_events,
remote_notif_stop_alloc_reply,
@@ -5697,7 +5700,7 @@ remote_notif_get_pending_events (struct notif_client *nc)
if (notif_debug)
fprintf_unfiltered (gdb_stdlog,
"notif: process: '%s' ack pending event\n",
- nc->name);
+ nc->base.notif_name);
/* acknowledge */
nc->ack (nc, rs->buf, nc->pending_event);
@@ -5717,7 +5720,7 @@ remote_notif_get_pending_events (struct notif_client *nc)
if (notif_debug)
fprintf_unfiltered (gdb_stdlog,
"notif: process: '%s' no pending reply\n",
- nc->name);
+ nc->base.notif_name);
}
}
--
1.7.7.6
^ permalink raw reply [flat|nested] 43+ messages in thread* [PATCH 2/5] Query supported notifications by qSupported
2013-02-16 4:01 ` [PATCH 0/5] MI notification on trace started/stopped (V3.1) Yao Qi
2013-02-16 4:01 ` [PATCH 1/5] Add annex in a async remote notification Yao Qi
@ 2013-02-16 4:02 ` Yao Qi
2013-02-16 9:33 ` Eli Zaretskii
2013-02-16 4:02 ` [PATCH 3/5] async remote notification 'Trace' Yao Qi
` (4 subsequent siblings)
6 siblings, 1 reply; 43+ messages in thread
From: Yao Qi @ 2013-02-16 4:02 UTC (permalink / raw)
To: gdb-patches
As we we adding more notifications and annexes, both GDB and GDBserver
has to know what notifications and annexes 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.A1.A2,N3
(GDB supports notification N1, N2 with annexes A1,A2, and N3)
<-- XXX;Notifications=N1,N2.A1,N4
(GDBsever supports notification N1, N2 with annex A1 and N4)
after this, GDB knows what notifications GDBserver is able to send,
and GDBservers knows what notifications GDB doesn't support.
gdb/gdbserver:
2013-02-16 Yao Qi <yao@codesourcery.com>
* Makefile.in (SFILES): Add "common-notif.c".
(OBS): Add common-notif.o.
(common-notif.o): New rule.
* notif.c (notif_find_annex): New.
(notif_qsupported_record): New.
(notif_qsupported_reply): New.
* notif.h (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:
2013-02-16 Yao Qi <yao@codesourcery.com>
* common/common-notif.c: New.
* common/common-notif.h (struct notif_annex) <supported>: New
field.
* Makefile.in (iREMOTE_OBS): Append "common-notif.o".
(SFILES): Add "common-notif.c".
* remote-notif.c (remote_notif_parse_1): Call the parser of
annex if it is supported.
(remote_notif_qsupported): New.
(remote_notif_qsupported_reply): New.
* remote-notif.h (remote_notif_qsupported): Declare.
(remote_notif_qsupported_reply): Declare.
* remote.c (PACKET_notifications): New enum.
(remote_notifications_feature): New.
(remote_protocol_features): Add new element.
(remote_query_supported): Call remote_notif_qsupported and
append supported notifications to qSupported feature.
(notif_client_annex_stop): Update.
gdb/doc:
2013-02-16 Yao Qi <yao@codesourcery.com>
* gdb.texinfo (General Query Packets): Document the new feature
'notifications' of 'qSupported' packet.
Document the new feature in qSupported reply.
---
gdb/Makefile.in | 9 ++-
gdb/common/common-notif.c | 186 +++++++++++++++++++++++++++++++++++++++++++++
gdb/common/common-notif.h | 15 ++++
gdb/doc/gdb.texinfo | 19 +++++
gdb/gdbserver/Makefile.in | 7 +-
gdb/gdbserver/notif.c | 21 +++++
gdb/gdbserver/notif.h | 2 +
gdb/gdbserver/server.c | 15 ++++-
gdb/remote-notif.c | 32 +++++++-
gdb/remote-notif.h | 4 +
gdb/remote.c | 22 +++++-
11 files changed, 323 insertions(+), 9 deletions(-)
create mode 100644 gdb/common/common-notif.c
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index a6ff9c3..4eb1548 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -510,7 +510,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
+ remote-notif.o common-notif.o
# This is remote-sim.o if a simulator is to be linked in.
SIM_OBS = @SIM_OBS@
@@ -736,7 +736,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 \
+ common-notif.c reverse.c \
sentinel-frame.c \
serial.c ser-base.c ser-unix.c skip.c \
solib.c solib-target.c source.c \
@@ -1925,6 +1926,10 @@ common-utils.o: ${srcdir}/common/common-utils.c
$(COMPILE) $(srcdir)/common/common-utils.c
$(POSTCOMPILE)
+common-notif.o: ${srcdir}/common/common-notif.c
+ $(COMPILE) $(srcdir)/common/common-notif.c
+ $(POSTCOMPILE)
+
gdb_vecs.o: ${srcdir}/common/gdb_vecs.c
$(COMPILE) $(srcdir)/common/gdb_vecs.c
$(POSTCOMPILE)
diff --git a/gdb/common/common-notif.c b/gdb/common/common-notif.c
new file mode 100644
index 0000000..e53729f
--- /dev/null
+++ b/gdb/common/common-notif.c
@@ -0,0 +1,186 @@
+/* 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/>. */
+
+#ifdef GDBSERVER
+#include "server.h"
+#else
+#include "defs.h"
+#endif
+#include <string.h>
+#include "common-notif.h"
+#include "gdb_assert.h"
+
+/* Return a string about the notifications in array NOTIFS. NUM is
+ the number of elements in array NOTIFS. The caller is responsible
+ to free the returned string. Suppose array NOTIFS has
+ notifications N1, N2, and N3. Only N2 has annexes A1 and A2. The
+ returned string is "N1,N2.A2.A2,N3". */
+
+char *
+notif_supported (struct notif_base *notifs[], int num)
+{
+ int i;
+ char * p = NULL;
+
+#define BUF_LEN 128
+
+ for (i = 0; i < num; i++)
+ {
+ struct notif_base *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);
+
+ if (NOTIF_HAS_ANNEX (nb))
+ {
+ int j;
+
+ NOTIF_ITER_ANNEX (nb, j)
+ {
+ xsnprintf (p + strlen (p), BUF_LEN - strlen (p),
+ ".%s", nb->annexes[j].name);
+ }
+ }
+ }
+
+ return p;
+}
+
+/* Find annex in notification NB by name NAME and length LEN.
+ If found, return annex, otherwise return NULL. */
+
+static struct notif_annex *
+notif_find_annex (struct notif_base *nb, const char *name, int len)
+{
+ if (NOTIF_HAS_ANNEX (nb))
+ {
+ int j;
+
+ NOTIF_ITER_ANNEX (nb, j)
+ if (strncmp (name, nb->annexes[j].name, len) == 0
+ && len == strlen (nb->annexes[j].name))
+ return &nb->annexes[j];
+ }
+ return NULL;
+}
+
+/* Parse the REPLY, which is about supported annexes and
+ notifications from the peer, and disable some annexes of
+ notification in array NOTIFS if the peer doesn't support. NUM is
+ the number of elements in array NOTIFS. */
+
+void
+notif_parse_supported (const char *reply,
+ struct notif_base *notifs[], int num)
+{
+ const char *p = reply;
+ int notif_num = 1;
+ char **notif_str;
+ int i;
+
+ /* Count how many notifications in REPLY. */
+ for (i = 0; reply[i] != '\0'; i++)
+ if (reply[i] == ',')
+ notif_num++;
+
+ /* Copy contents of each notification in REPLY to each slot of
+ NOTIF_STR. */
+ notif_str = xmalloc (notif_num * sizeof (char *));
+ for (i = 0; i < notif_num; i++)
+ {
+ char *end = strchr (p, ',');
+
+ if (end == NULL)
+ notif_str[i] = xstrdup (p);
+ else
+ {
+ /* Can't use xstrndup in GDBserver. */
+ notif_str[i] = strndup (p, end - p);
+ p = end + 1;
+ }
+ }
+
+ /* Iterate each element in NOTIF_STR and parse annex in it. */
+ for (i = 0; i < notif_num; i++)
+ {
+ int j;
+ struct notif_base *nb = NULL;
+
+ p = notif_str[i];
+
+ for (j = 0; j < num; j++)
+ {
+ int name_len = strlen (notifs[j]->notif_name);
+
+ if (0 == strncmp (notifs[j]->notif_name, p, name_len)
+ && (p[name_len] == '.' || p[name_len] == 0))
+ {
+ nb = notifs[j];
+ p += name_len;
+ break;
+ }
+ }
+
+ if (nb != NULL)
+ {
+ if (p[0] == 0)
+ {
+ /* No annex. */
+ gdb_assert (!NOTIF_HAS_ANNEX (nb));
+ nb->annexes[0].supported = 1;
+ }
+ else if (p[0] == '.')
+ {
+ gdb_assert (NOTIF_HAS_ANNEX (nb));
+
+ p++;
+
+ /* Parse the rest of P and look for annexes. */
+ while (p != NULL)
+ {
+ char *end = strchr (p, '.');
+ struct notif_annex *annex = NULL;
+
+ if (end != NULL)
+ {
+ annex = notif_find_annex (nb, p, end - p);
+ p = end + 1;
+ }
+ else
+ {
+ annex = notif_find_annex (nb, p, strlen (p));
+ p = end;
+ }
+
+ /* If annex is known, mark it supported, otherwise
+ skip it because the peer knows the annex but we
+ don't know. */
+ if (annex != NULL)
+ annex->supported = 1;
+ }
+ }
+ else
+ warning (_("Unknown supported notification"));
+ }
+ }
+}
diff --git a/gdb/common/common-notif.h b/gdb/common/common-notif.h
index 1ffa26c..8e0e0c1 100644
--- a/gdb/common/common-notif.h
+++ b/gdb/common/common-notif.h
@@ -32,6 +32,11 @@ struct notif_annex
notification this annex belongs to. */
const char *name;
+ /* This annex is supported by the peer (GDB or GDBserver)? A
+ notification may have multiple annexes and some of them are
+ supported. Annex is the smallest unit of support. */
+ int supported;
+
#ifdef GDBSERVER
/* Write event EVENT to OWN_BUF. */
void (*write) (struct notif_event *event, char *own_buf);
@@ -53,6 +58,10 @@ struct notif_annex
#define NOTIF_HAS_ANNEX(NOTIF) ((NOTIF)->annexes[0].name != NULL)
+/* Whether the annex of notification N is supported. */
+
+#define NOTIF_ANNEX_SUPPORTED_P(N, INDEX) \
+ ((N).annexes[INDEX].supported)
/* "Base class" of a notification. It can be extended in both GDB
and GDBserver to represent a type of notification. */
@@ -71,3 +80,9 @@ struct notif_base
of the notification. */
struct notif_annex *annexes;
};
+
+char *notif_supported (struct notif_base *notifs[], int num);
+
+void notif_parse_supported (const char *reply,
+ struct notif_base *notifs[], int num);
+
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 68b81a2..c94a203 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -37202,6 +37202,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 supported notifications,
+separated by commas, it will report notifications supported by the
+stub.
@end table
Stubs should ignore any unknown values for
@@ -37390,6 +37398,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:
@@ -37544,6 +37557,12 @@ 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{annex}@r{]}@dots{}@r{[},@var{name}@r{[}.@var{annex}@r{]}@dots{}@r{]}@dots{}
+@cindex notifications, in remote protocol
+The remote stub supports a string of notifications. @var{name} is
+the name of the notification and @var{annex} is the name of the annex,
+if the notification has the annex.
+
@end table
@item qSymbol::
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index dffe8ae..346e8c8 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -155,7 +155,7 @@ SFILES= $(srcdir)/gdbreplay.c $(srcdir)/inferiors.c $(srcdir)/dll.c \
$(srcdir)/common/vec.c $(srcdir)/common/gdb_vecs.c \
$(srcdir)/common/common-utils.c $(srcdir)/common/xml-utils.c \
$(srcdir)/common/linux-osdata.c $(srcdir)/common/ptid.c \
- $(srcdir)/common/buffer.c
+ $(srcdir)/common/buffer.c $(srcdir)/common/common-notif.c
DEPFILES = @GDBSERVER_DEPFILES@
@@ -165,7 +165,7 @@ SOURCES = $(SFILES)
TAGFILES = $(SOURCES) ${HFILES} ${ALLPARAM} ${POSSLIBS}
OBS = agent.o ax.o inferiors.o regcache.o remote-utils.o server.o signals.o target.o \
- utils.o version.o vec.o gdb_vecs.o \
+ utils.o version.o vec.o gdb_vecs.o common-notif.o \
mem-break.o hostio.o event-loop.o tracepoint.o \
xml-utils.o common-utils.o ptid.o buffer.o format.o \
dll.o notif.o \
@@ -518,6 +518,9 @@ linux-ptrace.o: ../common/linux-ptrace.c
common-utils.o: ../common/common-utils.c
$(COMPILE) $<
$(POSTCOMPILE)
+common-notif.o: ../common/common-notif.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
vec.o: ../common/vec.c
$(COMPILE) $<
$(POSTCOMPILE)
diff --git a/gdb/gdbserver/notif.c b/gdb/gdbserver/notif.c
index 168f77d..e6b3756 100644
--- a/gdb/gdbserver/notif.c
+++ b/gdb/gdbserver/notif.c
@@ -182,6 +182,27 @@ 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)
+{
+ return notif_parse_supported (gdb_notifications,
+ (struct notif_base **) notifs,
+ ARRAY_SIZE (notifs));
+}
+
+/* Return a string about notifications that GDBserver supports.
+ Return NULL if no notification is supported. */
+
+char *
+notif_qsupported_reply (void)
+{
+ return notif_supported ((struct notif_base **) notifs,
+ ARRAY_SIZE (notifs));
+}
+
void
initialize_notif (void)
{
diff --git a/gdb/gdbserver/notif.h b/gdb/gdbserver/notif.h
index 5f9b6bc..72417aa 100644
--- a/gdb/gdbserver/notif.h
+++ b/gdb/gdbserver/notif.h
@@ -58,6 +58,8 @@ 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 3e8ef0a..d20c1a8 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -185,7 +185,7 @@ vstop_notif_reply (struct notif_event *event, char *own_buf)
static struct notif_annex notif_annex_stop[] =
{
- { NULL, vstop_notif_reply, },
+ { NULL, 1, vstop_notif_reply, },
};
struct notif_server notif_stop =
@@ -1572,6 +1572,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);
@@ -1652,6 +1657,14 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
if (target_supports_agent ())
strcat (own_buf, ";QAgent+");
+ 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 e0bc745..ae05bbf 100644
--- a/gdb/remote-notif.c
+++ b/gdb/remote-notif.c
@@ -75,9 +75,16 @@ remote_notif_parse_1 (struct notif_client *nc,
contents in BUF. */
&& buf[strlen (m->name)] == ':')
{
- /* Pass BUF without annex and ':'. */
- m->parse (nc, buf + strlen (m->name) + 1, event);
- break;
+ if (m->supported)
+ {
+ /* Pass BUF without annex and ':'. */
+ m->parse (nc, buf + strlen (m->name) + 1, event);
+ break;
+ }
+ else
+ warning (_("GDB gets annex '%s' of notification '%s'"
+ "but remote stub doesn't support"),
+ base->notif_name, m->name);
}
m = NULL;
}
@@ -305,6 +312,25 @@ notif_xfree (struct notif_client *notif)
xfree (notif);
}
+/* Return a string of GDB supported features. */
+
+char *
+remote_notif_qsupported (void)
+{
+ return notif_supported ((struct notif_base **) notifs,
+ ARRAY_SIZE (notifs));
+}
+
+/* Parse the qSupported reply REPLY from the remote stub and disable
+ some notifications if the remote stub doesn't support. */
+
+void
+remote_notif_qsupported_reply (const char *reply)
+{
+ notif_parse_supported (reply, (struct notif_base **) notifs,
+ ARRAY_SIZE (notifs));
+}
+
/* -Wmissing-prototypes */
extern initialize_file_ftype _initialize_notif;
diff --git a/gdb/remote-notif.h b/gdb/remote-notif.h
index cb1636f..4859254 100644
--- a/gdb/remote-notif.h
+++ b/gdb/remote-notif.h
@@ -69,6 +69,10 @@ void remote_notif_register_async_event_handler (void);
void remote_notif_unregister_async_event_handler (void);
void remote_notif_process (struct notif_client *except);
+
+char * remote_notif_qsupported (void);
+void remote_notif_qsupported_reply (const char *reply);
+
extern struct notif_client notif_client_stop;
extern unsigned int notif_debug;
diff --git a/gdb/remote.c b/gdb/remote.c
index b4a8d24..cf5cb3f 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -1284,6 +1284,7 @@ enum {
PACKET_qXfer_fdpic,
PACKET_QDisableRandomization,
PACKET_QAgent,
+ PACKET_notifications,
PACKET_MAX
};
@@ -3928,6 +3929,15 @@ remote_string_tracing_feature (const struct protocol_feature *feature,
rs->string_tracing = (support == PACKET_ENABLE);
}
+static void
+remote_notifications_feature (const struct protocol_feature *feature,
+ enum packet_support support,
+ const char *value)
+{
+ if (support == PACKET_ENABLE)
+ remote_notif_qsupported_reply (value);
+}
+
static struct protocol_feature remote_protocol_features[] = {
{ "PacketSize", PACKET_DISABLE, remote_packet_size, -1 },
{ "qXfer:auxv:read", PACKET_DISABLE, remote_supported_packet,
@@ -3993,6 +4003,8 @@ static struct protocol_feature remote_protocol_features[] = {
{ "QDisableRandomization", PACKET_DISABLE, remote_supported_packet,
PACKET_QDisableRandomization },
{ "QAgent", PACKET_DISABLE, remote_supported_packet, PACKET_QAgent},
+ { "Notifications", PACKET_DISABLE, remote_notifications_feature,
+ -1 },
{ "tracenz", PACKET_DISABLE,
remote_string_tracing_feature, -1 },
};
@@ -4059,6 +4071,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+");
@@ -4068,6 +4081,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);
@@ -5266,7 +5283,10 @@ remote_notif_stop_alloc_reply (void)
static struct notif_annex notif_client_annex_stop[] =
{
- { NULL, remote_notif_stop_parse, },
+ /* Even the remote stub doesn't understand
+ 'qSupported:notifications=', it may still support notification
+ stop if it supports non-stop. */
+ { NULL, 1, remote_notif_stop_parse, },
};
/* A client of notification Stop. */
--
1.7.7.6
^ permalink raw reply [flat|nested] 43+ messages in thread* Re: [PATCH 2/5] Query supported notifications by qSupported
2013-02-16 4:02 ` [PATCH 2/5] Query supported notifications by qSupported Yao Qi
@ 2013-02-16 9:33 ` Eli Zaretskii
2013-03-11 9:26 ` Yao Qi
0 siblings, 1 reply; 43+ messages in thread
From: Eli Zaretskii @ 2013-02-16 9:33 UTC (permalink / raw)
To: Yao Qi; +Cc: gdb-patches
> From: Yao Qi <yao@codesourcery.com>
> Date: Sat, 16 Feb 2013 12:00:11 +0800
>
> As we we adding more notifications and annexes, both GDB and GDBserver
> has to know what notifications and annexes 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.A1.A2,N3
> (GDB supports notification N1, N2 with annexes A1,A2, and N3)
This form is not described in your patch for the manual.
> +@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 supported notifications,
> +separated by commas, it will report notifications supported by the
> +stub.
See above: I think you should show here the form of the
"notifications=" part in more detail. In particular, the fact that
each notification is of the form NOTIFICATION.ANNEX1.ANNEX2... is
important and should be described and the meaning of the multiple
ANNEX parts explained.
> +@item Notifications=@var{name}@r{[}.@var{annex}@r{]}@dots{}@r{[},@var{name}@r{[}.@var{annex}@r{]}@dots{}@r{]}@dots{}
> +@cindex notifications, in remote protocol
> +The remote stub supports a string of notifications. @var{name} is
> +the name of the notification and @var{annex} is the name of the annex,
> +if the notification has the annex.
Here, too, we should say explicitly that there could be several
@var{annex} parts separated by periods.
OK with those changes.
Thanks.
^ permalink raw reply [flat|nested] 43+ messages in thread* Re: [PATCH 2/5] Query supported notifications by qSupported
2013-02-16 9:33 ` Eli Zaretskii
@ 2013-03-11 9:26 ` Yao Qi
2013-03-11 16:59 ` Eli Zaretskii
0 siblings, 1 reply; 43+ messages in thread
From: Yao Qi @ 2013-03-11 9:26 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: gdb-patches
On 02/16/2013 05:32 PM, Eli Zaretskii wrote:
> See above: I think you should show here the form of the
> "notifications=" part in more detail. In particular, the fact that
> each notification is of the form NOTIFICATION.ANNEX1.ANNEX2... is
> important and should be described and the meaning of the multiple
> ANNEX parts explained.
How about this below,
.... supported by the
stub. Each notification in the string is composed by the name of the
notification and the annexes, if any, which are separated by periods.
>
>> >+@item Notifications=@var{name}@r{[}.@var{annex}@r{]}@dots{}@r{[},@var{name}@r{[}.@var{annex}@r{]}@dots{}@r{]}@dots{}
>> >+@cindex notifications, in remote protocol
>> >+The remote stub supports a string of notifications. @var{name} is
>> >+the name of the notification and @var{annex} is the name of the annex,
>> >+if the notification has the annex.
> Here, too, we should say explicitly that there could be several
> @var{annex} parts separated by periods.
and this,
if the notification has the annex. Note that the notification may
have several annexes, so here could be several @var{annex} parts
separated by periods.
Patch 2/5 can't be applied to current trunk (again) because of some
changes recently. I resolved the conflicts and post a updated one.
I sincerely ask maintainers to review the non-doc part of this patch
set. The previous review happened on Jan. 8th, two months ago.
I kept posting updated versions to resolve conflicts and sending ping
mail. I even tried to ping this patch set on IRC, but I got no
response. Usually, my patches are reviewed in 1~5 days, thanks to
maintainers' hard work, but don't know why this patch set can't
catch people's eyeball.
--
Yao (é½å°§)
gdb/gdbserver:
2013-03-11 Yao Qi <yao@codesourcery.com>
* Makefile.in (SFILES): Add "common-notif.c".
(OBS): Add common-notif.o.
(common-notif.o): New rule.
* notif.c (notif_find_annex): New.
(notif_qsupported_record): New.
(notif_qsupported_reply): New.
* notif.h (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:
2013-03-11 Yao Qi <yao@codesourcery.com>
* common/common-notif.c: New.
* common/common-notif.h (struct notif_annex) <supported>: New
field.
* Makefile.in (iREMOTE_OBS): Append "common-notif.o".
(SFILES): Add "common-notif.c".
* remote-notif.c (remote_notif_parse_1): Call the parser of
annex if it is supported.
(remote_notif_qsupported): New.
(remote_notif_qsupported_reply): New.
* remote-notif.h (remote_notif_qsupported): Declare.
(remote_notif_qsupported_reply): Declare.
* remote.c (PACKET_notifications): New enum.
(remote_notifications_feature): New.
(remote_protocol_features): Add new element.
(remote_query_supported): Call remote_notif_qsupported and
append supported notifications to qSupported feature.
(notif_client_annex_stop): Update.
gdb/doc:
2013-03-11 Yao Qi <yao@codesourcery.com>
* gdb.texinfo (General Query Packets): Document the new feature
'notifications' of 'qSupported' packet.
Document the new feature in qSupported reply.
---
gdb/Makefile.in | 9 ++-
gdb/common/common-notif.c | 186 +++++++++++++++++++++++++++++++++++++++++++++
gdb/common/common-notif.h | 15 ++++
gdb/doc/gdb.texinfo | 22 +++++
gdb/gdbserver/Makefile.in | 7 +-
gdb/gdbserver/notif.c | 21 +++++
gdb/gdbserver/notif.h | 2 +
gdb/gdbserver/server.c | 15 ++++-
gdb/remote-notif.c | 32 +++++++-
gdb/remote-notif.h | 4 +
gdb/remote.c | 22 +++++-
11 files changed, 326 insertions(+), 9 deletions(-)
create mode 100644 gdb/common/common-notif.c
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index a6ff9c3..4eb1548 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -510,7 +510,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
+ remote-notif.o common-notif.o
# This is remote-sim.o if a simulator is to be linked in.
SIM_OBS = @SIM_OBS@
@@ -736,7 +736,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 \
+ common-notif.c reverse.c \
sentinel-frame.c \
serial.c ser-base.c ser-unix.c skip.c \
solib.c solib-target.c source.c \
@@ -1925,6 +1926,10 @@ common-utils.o: ${srcdir}/common/common-utils.c
$(COMPILE) $(srcdir)/common/common-utils.c
$(POSTCOMPILE)
+common-notif.o: ${srcdir}/common/common-notif.c
+ $(COMPILE) $(srcdir)/common/common-notif.c
+ $(POSTCOMPILE)
+
gdb_vecs.o: ${srcdir}/common/gdb_vecs.c
$(COMPILE) $(srcdir)/common/gdb_vecs.c
$(POSTCOMPILE)
diff --git a/gdb/common/common-notif.c b/gdb/common/common-notif.c
new file mode 100644
index 0000000..e53729f
--- /dev/null
+++ b/gdb/common/common-notif.c
@@ -0,0 +1,186 @@
+/* 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/>. */
+
+#ifdef GDBSERVER
+#include "server.h"
+#else
+#include "defs.h"
+#endif
+#include <string.h>
+#include "common-notif.h"
+#include "gdb_assert.h"
+
+/* Return a string about the notifications in array NOTIFS. NUM is
+ the number of elements in array NOTIFS. The caller is responsible
+ to free the returned string. Suppose array NOTIFS has
+ notifications N1, N2, and N3. Only N2 has annexes A1 and A2. The
+ returned string is "N1,N2.A2.A2,N3". */
+
+char *
+notif_supported (struct notif_base *notifs[], int num)
+{
+ int i;
+ char * p = NULL;
+
+#define BUF_LEN 128
+
+ for (i = 0; i < num; i++)
+ {
+ struct notif_base *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);
+
+ if (NOTIF_HAS_ANNEX (nb))
+ {
+ int j;
+
+ NOTIF_ITER_ANNEX (nb, j)
+ {
+ xsnprintf (p + strlen (p), BUF_LEN - strlen (p),
+ ".%s", nb->annexes[j].name);
+ }
+ }
+ }
+
+ return p;
+}
+
+/* Find annex in notification NB by name NAME and length LEN.
+ If found, return annex, otherwise return NULL. */
+
+static struct notif_annex *
+notif_find_annex (struct notif_base *nb, const char *name, int len)
+{
+ if (NOTIF_HAS_ANNEX (nb))
+ {
+ int j;
+
+ NOTIF_ITER_ANNEX (nb, j)
+ if (strncmp (name, nb->annexes[j].name, len) == 0
+ && len == strlen (nb->annexes[j].name))
+ return &nb->annexes[j];
+ }
+ return NULL;
+}
+
+/* Parse the REPLY, which is about supported annexes and
+ notifications from the peer, and disable some annexes of
+ notification in array NOTIFS if the peer doesn't support. NUM is
+ the number of elements in array NOTIFS. */
+
+void
+notif_parse_supported (const char *reply,
+ struct notif_base *notifs[], int num)
+{
+ const char *p = reply;
+ int notif_num = 1;
+ char **notif_str;
+ int i;
+
+ /* Count how many notifications in REPLY. */
+ for (i = 0; reply[i] != '\0'; i++)
+ if (reply[i] == ',')
+ notif_num++;
+
+ /* Copy contents of each notification in REPLY to each slot of
+ NOTIF_STR. */
+ notif_str = xmalloc (notif_num * sizeof (char *));
+ for (i = 0; i < notif_num; i++)
+ {
+ char *end = strchr (p, ',');
+
+ if (end == NULL)
+ notif_str[i] = xstrdup (p);
+ else
+ {
+ /* Can't use xstrndup in GDBserver. */
+ notif_str[i] = strndup (p, end - p);
+ p = end + 1;
+ }
+ }
+
+ /* Iterate each element in NOTIF_STR and parse annex in it. */
+ for (i = 0; i < notif_num; i++)
+ {
+ int j;
+ struct notif_base *nb = NULL;
+
+ p = notif_str[i];
+
+ for (j = 0; j < num; j++)
+ {
+ int name_len = strlen (notifs[j]->notif_name);
+
+ if (0 == strncmp (notifs[j]->notif_name, p, name_len)
+ && (p[name_len] == '.' || p[name_len] == 0))
+ {
+ nb = notifs[j];
+ p += name_len;
+ break;
+ }
+ }
+
+ if (nb != NULL)
+ {
+ if (p[0] == 0)
+ {
+ /* No annex. */
+ gdb_assert (!NOTIF_HAS_ANNEX (nb));
+ nb->annexes[0].supported = 1;
+ }
+ else if (p[0] == '.')
+ {
+ gdb_assert (NOTIF_HAS_ANNEX (nb));
+
+ p++;
+
+ /* Parse the rest of P and look for annexes. */
+ while (p != NULL)
+ {
+ char *end = strchr (p, '.');
+ struct notif_annex *annex = NULL;
+
+ if (end != NULL)
+ {
+ annex = notif_find_annex (nb, p, end - p);
+ p = end + 1;
+ }
+ else
+ {
+ annex = notif_find_annex (nb, p, strlen (p));
+ p = end;
+ }
+
+ /* If annex is known, mark it supported, otherwise
+ skip it because the peer knows the annex but we
+ don't know. */
+ if (annex != NULL)
+ annex->supported = 1;
+ }
+ }
+ else
+ warning (_("Unknown supported notification"));
+ }
+ }
+}
diff --git a/gdb/common/common-notif.h b/gdb/common/common-notif.h
index 1ffa26c..8e0e0c1 100644
--- a/gdb/common/common-notif.h
+++ b/gdb/common/common-notif.h
@@ -32,6 +32,11 @@ struct notif_annex
notification this annex belongs to. */
const char *name;
+ /* This annex is supported by the peer (GDB or GDBserver)? A
+ notification may have multiple annexes and some of them are
+ supported. Annex is the smallest unit of support. */
+ int supported;
+
#ifdef GDBSERVER
/* Write event EVENT to OWN_BUF. */
void (*write) (struct notif_event *event, char *own_buf);
@@ -53,6 +58,10 @@ struct notif_annex
#define NOTIF_HAS_ANNEX(NOTIF) ((NOTIF)->annexes[0].name != NULL)
+/* Whether the annex of notification N is supported. */
+
+#define NOTIF_ANNEX_SUPPORTED_P(N, INDEX) \
+ ((N).annexes[INDEX].supported)
/* "Base class" of a notification. It can be extended in both GDB
and GDBserver to represent a type of notification. */
@@ -71,3 +80,9 @@ struct notif_base
of the notification. */
struct notif_annex *annexes;
};
+
+char *notif_supported (struct notif_base *notifs[], int num);
+
+void notif_parse_supported (const char *reply,
+ struct notif_base *notifs[], int num);
+
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 400c794..50520b0 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -37214,6 +37214,15 @@ 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 supported notifications,
+separated by commas, it will report notifications supported by the
+stub. Each notification in the string is composed by the name of the
+notification and the annexes, if any, which are separated by periods.
@end table
Stubs should ignore any unknown values for
@@ -37407,6 +37416,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:
@@ -37565,6 +37579,14 @@ 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{annex}@r{]}@dots{}@r{[},@var{name}@r{[}.@var{annex}@r{]}@dots{}@r{]}@dots{}
+@cindex notifications, in remote protocol
+The remote stub supports a string of notifications. @var{name} is
+the name of the notification and @var{annex} is the name of the annex,
+if the notification has the annex. Note that the notification may
+have several annexes, so here could be several @var{annex} parts
+separated by periods.
+
@end table
@item qSymbol::
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index ee2c400..fb0f604 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -155,7 +155,7 @@ SFILES= $(srcdir)/gdbreplay.c $(srcdir)/inferiors.c $(srcdir)/dll.c \
$(srcdir)/common/vec.c $(srcdir)/common/gdb_vecs.c \
$(srcdir)/common/common-utils.c $(srcdir)/common/xml-utils.c \
$(srcdir)/common/linux-osdata.c $(srcdir)/common/ptid.c \
- $(srcdir)/common/buffer.c
+ $(srcdir)/common/buffer.c $(srcdir)/common/common-notif.c
DEPFILES = @GDBSERVER_DEPFILES@
@@ -165,7 +165,7 @@ SOURCES = $(SFILES)
TAGFILES = $(SOURCES) ${HFILES} ${ALLPARAM} ${POSSLIBS}
OBS = agent.o ax.o inferiors.o regcache.o remote-utils.o server.o signals.o target.o \
- utils.o version.o vec.o gdb_vecs.o \
+ utils.o version.o vec.o gdb_vecs.o common-notif.o \
mem-break.o hostio.o event-loop.o tracepoint.o \
xml-utils.o common-utils.o ptid.o buffer.o format.o \
dll.o notif.o \
@@ -519,6 +519,9 @@ linux-ptrace.o: ../common/linux-ptrace.c
common-utils.o: ../common/common-utils.c
$(COMPILE) $<
$(POSTCOMPILE)
+common-notif.o: ../common/common-notif.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
vec.o: ../common/vec.c
$(COMPILE) $<
$(POSTCOMPILE)
diff --git a/gdb/gdbserver/notif.c b/gdb/gdbserver/notif.c
index 168f77d..e6b3756 100644
--- a/gdb/gdbserver/notif.c
+++ b/gdb/gdbserver/notif.c
@@ -182,6 +182,27 @@ 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)
+{
+ return notif_parse_supported (gdb_notifications,
+ (struct notif_base **) notifs,
+ ARRAY_SIZE (notifs));
+}
+
+/* Return a string about notifications that GDBserver supports.
+ Return NULL if no notification is supported. */
+
+char *
+notif_qsupported_reply (void)
+{
+ return notif_supported ((struct notif_base **) notifs,
+ ARRAY_SIZE (notifs));
+}
+
void
initialize_notif (void)
{
diff --git a/gdb/gdbserver/notif.h b/gdb/gdbserver/notif.h
index 5f9b6bc..72417aa 100644
--- a/gdb/gdbserver/notif.h
+++ b/gdb/gdbserver/notif.h
@@ -58,6 +58,8 @@ 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 3722ed6..be76378 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -185,7 +185,7 @@ vstop_notif_reply (struct notif_event *event, char *own_buf)
static struct notif_annex notif_annex_stop[] =
{
- { NULL, vstop_notif_reply, },
+ { NULL, 1, vstop_notif_reply, },
};
struct notif_server notif_stop =
@@ -1572,6 +1572,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);
@@ -1653,6 +1658,14 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
if (target_supports_agent ())
strcat (own_buf, ";QAgent+");
+ 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 41bcc3e..9768143 100644
--- a/gdb/remote-notif.c
+++ b/gdb/remote-notif.c
@@ -75,9 +75,16 @@ remote_notif_parse_1 (struct notif_client *nc,
contents in BUF. */
&& buf[strlen (m->name)] == ':')
{
- /* Pass BUF without annex and ':'. */
- m->parse (nc, buf + strlen (m->name) + 1, event);
- break;
+ if (m->supported)
+ {
+ /* Pass BUF without annex and ':'. */
+ m->parse (nc, buf + strlen (m->name) + 1, event);
+ break;
+ }
+ else
+ warning (_("GDB gets annex '%s' of notification '%s'"
+ "but remote stub doesn't support"),
+ base->notif_name, m->name);
}
m = NULL;
}
@@ -305,6 +312,25 @@ notif_xfree (struct notif_client *notif)
xfree (notif);
}
+/* Return a string of GDB supported features. */
+
+char *
+remote_notif_qsupported (void)
+{
+ return notif_supported ((struct notif_base **) notifs,
+ ARRAY_SIZE (notifs));
+}
+
+/* Parse the qSupported reply REPLY from the remote stub and disable
+ some notifications if the remote stub doesn't support. */
+
+void
+remote_notif_qsupported_reply (const char *reply)
+{
+ notif_parse_supported (reply, (struct notif_base **) notifs,
+ ARRAY_SIZE (notifs));
+}
+
/* -Wmissing-prototypes */
extern initialize_file_ftype _initialize_notif;
diff --git a/gdb/remote-notif.h b/gdb/remote-notif.h
index fd38ea4..088713a 100644
--- a/gdb/remote-notif.h
+++ b/gdb/remote-notif.h
@@ -69,6 +69,10 @@ void remote_notif_register_async_event_handler (void);
void remote_notif_unregister_async_event_handler (void);
void remote_notif_process (struct notif_client *except);
+
+char * remote_notif_qsupported (void);
+void remote_notif_qsupported_reply (const char *reply);
+
extern struct notif_client notif_client_stop;
extern int notif_debug;
diff --git a/gdb/remote.c b/gdb/remote.c
index 51f9726..c200d06 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -1281,6 +1281,7 @@ enum {
PACKET_QDisableRandomization,
PACKET_QAgent,
PACKET_QTBuffer_size,
+ PACKET_notifications,
PACKET_MAX
};
@@ -3925,6 +3926,15 @@ remote_string_tracing_feature (const struct protocol_feature *feature,
rs->string_tracing = (support == PACKET_ENABLE);
}
+static void
+remote_notifications_feature (const struct protocol_feature *feature,
+ enum packet_support support,
+ const char *value)
+{
+ if (support == PACKET_ENABLE)
+ remote_notif_qsupported_reply (value);
+}
+
static struct protocol_feature remote_protocol_features[] = {
{ "PacketSize", PACKET_DISABLE, remote_packet_size, -1 },
{ "qXfer:auxv:read", PACKET_DISABLE, remote_supported_packet,
@@ -3992,6 +4002,8 @@ static struct protocol_feature remote_protocol_features[] = {
{ "QAgent", PACKET_DISABLE, remote_supported_packet, PACKET_QAgent},
{ "QTBuffer:size", PACKET_DISABLE,
remote_supported_packet, PACKET_QTBuffer_size},
+ { "Notifications", PACKET_DISABLE, remote_notifications_feature,
+ -1 },
{ "tracenz", PACKET_DISABLE,
remote_string_tracing_feature, -1 },
};
@@ -4058,6 +4070,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+");
@@ -4067,6 +4080,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);
@@ -5265,7 +5282,10 @@ remote_notif_stop_alloc_reply (void)
static struct notif_annex notif_client_annex_stop[] =
{
- { NULL, remote_notif_stop_parse, },
+ /* Even the remote stub doesn't understand
+ 'qSupported:notifications=', it may still support notification
+ stop if it supports non-stop. */
+ { NULL, 1, remote_notif_stop_parse, },
};
/* A client of notification Stop. */
--
1.7.7.6
^ permalink raw reply [flat|nested] 43+ messages in thread* Re: [PATCH 2/5] Query supported notifications by qSupported
2013-03-11 9:26 ` Yao Qi
@ 2013-03-11 16:59 ` Eli Zaretskii
0 siblings, 0 replies; 43+ messages in thread
From: Eli Zaretskii @ 2013-03-11 16:59 UTC (permalink / raw)
To: Yao Qi; +Cc: gdb-patches
> Date: Mon, 11 Mar 2013 17:25:33 +0800
> From: Yao Qi <yao@codesourcery.com>
> CC: <gdb-patches@sourceware.org>
>
> On 02/16/2013 05:32 PM, Eli Zaretskii wrote:
> > See above: I think you should show here the form of the
> > "notifications=" part in more detail. In particular, the fact that
> > each notification is of the form NOTIFICATION.ANNEX1.ANNEX2... is
> > important and should be described and the meaning of the multiple
> > ANNEX parts explained.
>
> How about this below,
>
> .... supported by the
> stub. Each notification in the string is composed by the name of the
> notification and the annexes, if any, which are separated by periods.
>
> >
> >> >+@item Notifications=@var{name}@r{[}.@var{annex}@r{]}@dots{}@r{[},@var{name}@r{[}.@var{annex}@r{]}@dots{}@r{]}@dots{}
> >> >+@cindex notifications, in remote protocol
> >> >+The remote stub supports a string of notifications. @var{name} is
> >> >+the name of the notification and @var{annex} is the name of the annex,
> >> >+if the notification has the annex.
> > Here, too, we should say explicitly that there could be several
> > @var{annex} parts separated by periods.
>
> and this,
>
> if the notification has the annex. Note that the notification may
> have several annexes, so here could be several @var{annex} parts
> separated by periods.
Thanks, I'm happy now.
^ permalink raw reply [flat|nested] 43+ messages in thread
* [PATCH 3/5] async remote notification 'Trace'.
2013-02-16 4:01 ` [PATCH 0/5] MI notification on trace started/stopped (V3.1) Yao Qi
2013-02-16 4:01 ` [PATCH 1/5] Add annex in a async remote notification Yao Qi
2013-02-16 4:02 ` [PATCH 2/5] Query supported notifications by qSupported Yao Qi
@ 2013-02-16 4:02 ` Yao Qi
2013-02-16 9:34 ` Eli Zaretskii
2013-02-16 4:02 ` [PATCH 4/5] MI notification on trace started/stopped:basic Yao Qi
` (3 subsequent siblings)
6 siblings, 1 reply; 43+ messages in thread
From: Yao Qi @ 2013-02-16 4:02 UTC (permalink / raw)
To: gdb-patches
Hi,
This patch adds a new async remote notification 'Trace' to report the
trace-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
and of course, it can be used for other trace-related changes, with
different annex.
gdb/gdbserver:
* notif.c (notifs): Add "notif_trace".
* notif.h (ontif_trace): Declare.
* tracepoint.c [!IN_PROCESS_AGENT]: Include "notif.h".
(notif_reply_trace): New.
(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.
(NOTIF_ANNEX_TRACE_STATUS): New macro.
* 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 | 4 +-
gdb/doc/gdb.texinfo | 10 ++++++
gdb/gdbserver/notif.c | 1 +
gdb/gdbserver/notif.h | 1 +
gdb/gdbserver/tracepoint.c | 36 +++++++++++++++++++++
gdb/remote-notif-trace.c | 75 ++++++++++++++++++++++++++++++++++++++++++++
gdb/remote-notif.c | 1 +
gdb/remote-notif.h | 1 +
8 files changed, 127 insertions(+), 2 deletions(-)
create mode 100644 gdb/remote-notif-trace.c
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 4eb1548..3bd6333 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -510,7 +510,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 common-notif.o
+ remote-notif.o common-notif.o remote-notif-trace.o
# This is remote-sim.o if a simulator is to be linked in.
SIM_OBS = @SIM_OBS@
@@ -737,7 +737,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
proc-service.list progspace.c \
prologue-value.c psymtab.c \
regcache.c reggroups.c remote.c remote-fileio.c remote-notif.c \
- common-notif.c reverse.c \
+ common-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 c94a203..6719a05 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -36372,6 +36372,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{}}
@@ -38273,6 +38275,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.
@@ -38800,6 +38803,13 @@ 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 @code{status}
+@tab @var{reply}. The @var{reply} has the form of the reply to packet
+@samp{qTStatus}, as described in @ref{qTStatus packet}.
+@tab Report an asynchronous trace-related event.
+
@end multitable
@node Remote Non-Stop
diff --git a/gdb/gdbserver/notif.c b/gdb/gdbserver/notif.c
index e6b3756..5a533f4 100644
--- a/gdb/gdbserver/notif.c
+++ b/gdb/gdbserver/notif.c
@@ -52,6 +52,7 @@
static struct notif_server *notifs[] =
{
¬if_stop,
+ ¬if_trace,
};
/* Helper function to write EVENT of NOTIF to buffer OWN_BUF. */
diff --git a/gdb/gdbserver/notif.h b/gdb/gdbserver/notif.h
index 72417aa..52d09cc 100644
--- a/gdb/gdbserver/notif.h
+++ b/gdb/gdbserver/notif.h
@@ -55,6 +55,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 51b6a0c..8becbbf 100644
--- a/gdb/gdbserver/tracepoint.c
+++ b/gdb/gdbserver/tracepoint.c
@@ -3370,6 +3370,32 @@ 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)
+{
+ cmd_qtstatus (own_buf);
+}
+
+#define NOTIF_ANNEX_TRACE_STATUS 0
+
+static struct notif_annex notif_annex_trace[] =
+{
+ { "status", 0, notif_reply_trace, },
+ { NULL, 0, NULL, },
+};
+
+struct notif_server notif_trace =
+{
+ { "Trace", "vTraced", notif_annex_trace, }, NULL,
+};
+
+#endif
+
/* End a tracing run, filling in a stop reason to report back to GDB,
and removing the tracepoints from the code. */
@@ -3470,6 +3496,16 @@ stop_tracing (void)
}
unpause_all (1);
+
+ if (NOTIF_ANNEX_SUPPORTED_P (notif_trace.base,
+ NOTIF_ANNEX_TRACE_STATUS))
+ {
+ struct notif_annex_event *event
+ = xmalloc (sizeof (struct notif_annex_event));
+
+ event->annex_index = NOTIF_ANNEX_TRACE_STATUS;
+ notif_push (¬if_trace, (struct notif_event *) event);
+ }
}
static int
diff --git a/gdb/remote-notif-trace.c b/gdb/remote-notif-trace.c
new file mode 100644
index 0000000..a0cfa26
--- /dev/null
+++ b/gdb/remote-notif-trace.c
@@ -0,0 +1,75 @@
+/* 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_status_parse (struct notif_client *self, char *buf,
+ struct notif_event *event)
+{
+ struct trace_status *ts = current_trace_status ();
+
+ gdb_assert (buf[0] == 'T');
+ parse_trace_status (buf + 1, ts);
+}
+
+static void
+remote_notif_trace_ack (struct notif_client *self, char *buf,
+ struct notif_event *event)
+{
+ /* acknowledge */
+ putpkt ((char *) self->base.ack_name);
+}
+
+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;
+}
+
+static struct notif_annex notif_client_trace_annex[] =
+{
+ { "status", 0, remote_notif_trace_status_parse, },
+ { NULL, 0, NULL, },
+};
+
+/* A client of notification 'Trace'. */
+
+struct notif_client notif_client_trace =
+{
+ { "Trace", "vTraced", notif_client_trace_annex, },
+ remote_notif_trace_ack,
+ remote_notif_trace_can_get_pending_events,
+ remote_notif_trace_alloc_event,
+ NULL,
+};
diff --git a/gdb/remote-notif.c b/gdb/remote-notif.c
index ae05bbf..aeff038 100644
--- a/gdb/remote-notif.c
+++ b/gdb/remote-notif.c
@@ -49,6 +49,7 @@ unsigned int notif_debug = 0;
static struct notif_client *notifs[] =
{
¬if_client_stop,
+ ¬if_client_trace,
};
static void do_notif_event_xfree (void *arg);
diff --git a/gdb/remote-notif.h b/gdb/remote-notif.h
index 4859254..ce9fd07 100644
--- a/gdb/remote-notif.h
+++ b/gdb/remote-notif.h
@@ -74,6 +74,7 @@ char * remote_notif_qsupported (void);
void remote_notif_qsupported_reply (const char *reply);
extern struct notif_client notif_client_stop;
+extern struct notif_client notif_client_trace;
extern unsigned int notif_debug;
--
1.7.7.6
^ permalink raw reply [flat|nested] 43+ messages in thread* [PATCH 4/5] MI notification on trace started/stopped:basic
2013-02-16 4:01 ` [PATCH 0/5] MI notification on trace started/stopped (V3.1) Yao Qi
` (2 preceding siblings ...)
2013-02-16 4:02 ` [PATCH 3/5] async remote notification 'Trace' Yao Qi
@ 2013-02-16 4:02 ` Yao Qi
2013-02-16 9:36 ` Eli Zaretskii
2013-02-16 4:02 ` [PATCH 5/5] MI notification on trace stop: triggered by remote Yao Qi
` (2 subsequent siblings)
6 siblings, 1 reply; 43+ messages in thread
From: Yao Qi @ 2013-02-16 4:02 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?
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 38b36c2..fd9cfbe 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -150,6 +150,8 @@ show filename-display
** The response to breakpoint commands and breakpoint async records
includes an "installed" field containing a boolean state about each
non-pending tracepoint location is whether installed on target or not.
+ ** The start and stop of trace are now notified using new async records
+ "=trace-started" and "=trace-stopped".
* GDB now supports the "mini debuginfo" section, .gnu_debugdata.
You must have the LZMA library available when configuring GDB for this
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 6719a05..c8dc31d 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -28041,6 +28041,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 adb7085..17e3588 100644
--- a/gdb/doc/observer.texi
+++ b/gdb/doc/observer.texi
@@ -249,6 +249,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 df173fe..f2c037d 100644
--- a/gdb/mi/mi-cmds.c
+++ b/gdb/mi/mi-cmds.c
@@ -146,9 +146,11 @@ static struct mi_cmd mi_cmds[] =
&mi_suppress_notification.traceframe),
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 d1fe33c..f83dc6b 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -68,6 +68,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);
@@ -133,6 +134,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);
@@ -623,6 +625,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 d4b0549..b5c957a 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -1823,6 +1823,8 @@ start_tracing (char *notes)
/* Now insert traps and begin collecting data. */
target_trace_start ();
+ observer_notify_trace_changed (1);
+
/* Reset our local state. */
set_traceframe_num (-1);
set_tracepoint_num (-1);
@@ -1908,6 +1910,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] 43+ messages in thread* [PATCH 5/5] MI notification on trace stop: triggered by remote
2013-02-16 4:01 ` [PATCH 0/5] MI notification on trace started/stopped (V3.1) Yao Qi
` (3 preceding siblings ...)
2013-02-16 4:02 ` [PATCH 4/5] MI notification on trace started/stopped:basic Yao Qi
@ 2013-02-16 4:02 ` Yao Qi
2013-02-25 3:14 ` ping: [PATCH 0/5] MI notification on trace started/stopped (V3.1) Yao Qi
2013-03-04 2:34 ` ping^2 : " Yao Qi
6 siblings, 0 replies; 43+ messages in thread
From: Yao Qi @ 2013-02-16 4:02 UTC (permalink / raw)
To: gdb-patches
As a result of previous patch, GDB has a Trace rsp notification.
In this patch, GDB starts to use Trace notification, and emits MI
notification '=trace-stopped' to front-end. A test case is
added to see if MI trace-stopped notification is emitted when trace
buffer is full.
gdb:
* remote-notif-trace.c: Include "observer.h".
(remote_notif_trace_status_parse): Call
observer_notify_trace_changed.
gdb/testsuite:
* gdb.trace/mi-trace-changed.exp (test_trace_buffer_full): New.
---
gdb/remote-notif-trace.c | 11 ++++
gdb/testsuite/gdb.trace/mi-trace-changed.exp | 75 ++++++++++++++++++++++++++
2 files changed, 86 insertions(+), 0 deletions(-)
diff --git a/gdb/remote-notif-trace.c b/gdb/remote-notif-trace.c
index a0cfa26..8c1e8a8 100644
--- a/gdb/remote-notif-trace.c
+++ b/gdb/remote-notif-trace.c
@@ -22,6 +22,7 @@
#include "remote.h"
#include "tracepoint.h"
#include "remote-notif.h"
+#include "observer.h"
static void
remote_notif_trace_status_parse (struct notif_client *self, char *buf,
@@ -31,6 +32,16 @@ remote_notif_trace_status_parse (struct notif_client *self, char *buf,
gdb_assert (buf[0] == 'T');
parse_trace_status (buf + 1, ts);
+
+ /* When the tracing is stopped, there is no changes anymore in
+ the trace, so the remote stub can't send another notification.
+ We don't have to worry about notifying 'trace_changed' observer
+ with argument 1 twice.
+ The remote stub can't request tracing start and the remote stub
+ may send multiple trace notifications on various status changes,
+ we don't notify 'trace_changed' observer with argument 0. */
+ if (!ts->running)
+ observer_notify_trace_changed (0);
}
static void
diff --git a/gdb/testsuite/gdb.trace/mi-trace-changed.exp b/gdb/testsuite/gdb.trace/mi-trace-changed.exp
index fbd6fe7..9d6cfff 100644
--- a/gdb/testsuite/gdb.trace/mi-trace-changed.exp
+++ b/gdb/testsuite/gdb.trace/mi-trace-changed.exp
@@ -71,4 +71,79 @@ proc test_normal_tstart_stop { } {
test_normal_tstart_stop
+# Verify that MI notification '=trace-stopped' is emitted when trace
+# buffer is full.
+
+proc test_trace_buffer_full { } {
+ with_test_prefix "tracebuffer full" {
+ global mi_gdb_prompt
+
+ if [mi_gdb_start] {
+ return
+ }
+ mi_run_to_main
+
+ mi_gdb_test "-break-insert -a func2" {.*\^done,bkpt=.*} \
+ "insert tracepoint on func2"
+
+ send_gdb "actions\n"
+ gdb_expect {
+ -re "End with" {
+ }
+ }
+
+ send_gdb "collect buf\nend\n"
+ set test "define actions"
+ gdb_expect {
+ -re ".*${mi_gdb_prompt}$" {
+ pass $test
+ }
+ timeout {
+ fail "$test (timeout)"
+ }
+ }
+
+ # 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 "-break-insert end" {.*\^done,bkpt=.*} \
+ "insert breakpoint on end"
+
+ mi_send_resuming_command "exec-continue" \
+ "continuing execution to end"
+
+ set test "trace-stopped triggered by bufferfull"
+ gdb_expect {
+ # We don't set stop-notes.
+ -re "=trace-stopped\\\\n" {
+ pass "$test"
+ }
+ timeout {
+ fail "$test (timeout)"
+ }
+ }
+
+ global async
+ # In sync mode, eat all the output. Don't have to do so in
+ # async mode.
+ if {!$async} {
+ gdb_expect {
+ -re ".*${mi_gdb_prompt}$" {
+ }
+ }
+ }
+ # GDB has got the rsp notifcation from remote stub that trace
+ # is stopped.
+ mi_gdb_test "tstop" ".*Trace is not running.*" \
+ "tstop on stopped"
+
+ mi_gdb_test "-trace-status" ".*\\^done.*stop-reason=\"overflow\".*" \
+ "trace-status"
+
+ mi_gdb_exit
+ }
+}
+
+test_trace_buffer_full
+
return 0
--
1.7.7.6
^ permalink raw reply [flat|nested] 43+ messages in thread* ping: [PATCH 0/5] MI notification on trace started/stopped (V3.1)
2013-02-16 4:01 ` [PATCH 0/5] MI notification on trace started/stopped (V3.1) Yao Qi
` (4 preceding siblings ...)
2013-02-16 4:02 ` [PATCH 5/5] MI notification on trace stop: triggered by remote Yao Qi
@ 2013-02-25 3:14 ` Yao Qi
2013-03-04 2:34 ` ping^2 : " Yao Qi
6 siblings, 0 replies; 43+ messages in thread
From: Yao Qi @ 2013-02-25 3:14 UTC (permalink / raw)
To: gdb-patches
On 02/16/2013 12:00 PM, Yao Qi wrote:
> On 01/22/2013 03:03 PM, Yao Qi wrote:
>> This patch series is the V3 of this series. V2 was posted
>> <http://sourceware.org/ml/gdb-patches/2012-12/msg00687.html>. Here
>> are some changes in V3,
>>
>> - Introduce query mechanism on supported notifications
>> - Introduce concept "annex" into remote notification,
>> - Remove trace notes in MI notifications, suggested by Pedro in the
>> review.
>> - Combine observers 'trace-started' and 'trace-stoped' into one
>> observer 'trace-changed'.
>
> The V3 can't be applied to CVS trunk without conflicts, so I resolved
> these conflicts, rebase patches to CVS trunk, and post them again.
>
> Beside this, I also add some comments here and there in the patches.
> Regression tested them on x86_64-linux with the combination
> {unix, native-gdbserver} x {sync, async}. Is it OK?
>
> All doc bits were reviewed by Eli in V3.
>
Ping.
--
Yao (é½å°§)
^ permalink raw reply [flat|nested] 43+ messages in thread* ping^2 : [PATCH 0/5] MI notification on trace started/stopped (V3.1)
2013-02-16 4:01 ` [PATCH 0/5] MI notification on trace started/stopped (V3.1) Yao Qi
` (5 preceding siblings ...)
2013-02-25 3:14 ` ping: [PATCH 0/5] MI notification on trace started/stopped (V3.1) Yao Qi
@ 2013-03-04 2:34 ` Yao Qi
6 siblings, 0 replies; 43+ messages in thread
From: Yao Qi @ 2013-03-04 2:34 UTC (permalink / raw)
To: gdb-patches
On 02/16/2013 12:00 PM, Yao Qi wrote:
> On 01/22/2013 03:03 PM, Yao Qi wrote:
>> This patch series is the V3 of this series. V2 was posted
>> <http://sourceware.org/ml/gdb-patches/2012-12/msg00687.html>. Here
>> are some changes in V3,
>>
>> - Introduce query mechanism on supported notifications
>> - Introduce concept "annex" into remote notification,
>> - Remove trace notes in MI notifications, suggested by Pedro in the
>> review.
>> - Combine observers 'trace-started' and 'trace-stoped' into one
>> observer 'trace-changed'.
>
> The V3 can't be applied to CVS trunk without conflicts, so I resolved
> these conflicts, rebase patches to CVS trunk, and post them again.
>
> Beside this, I also add some comments here and there in the patches.
> Regression tested them on x86_64-linux with the combination
> {unix, native-gdbserver} x {sync, async}. Is it OK?
>
> All doc bits were reviewed by Eli in V3.
>
Ping^2.
--
Yao (é½å°§)
^ permalink raw reply [flat|nested] 43+ messages in thread
* [PATCH v4 0/5] MI notification on trace started/stopped
2013-01-22 7:05 [PATCH 0/5] MI notification on trace started/stopped (V3) Yao Qi
` (6 preceding siblings ...)
2013-02-16 4:01 ` [PATCH 0/5] MI notification on trace started/stopped (V3.1) Yao Qi
@ 2013-04-02 2:33 ` Yao Qi
2013-04-02 3:15 ` [PATCH 2/5] Query supported notifications by qSupported Yao Qi
` (5 more replies)
7 siblings, 6 replies; 43+ messages in thread
From: Yao Qi @ 2013-04-02 2:33 UTC (permalink / raw)
To: gdb-patches
Hi,
The V3.1 can't be applied to CVS trunk clearly, so I resolved these
conflicts and submit them again.
All doc bits were approved by Eli in V3.1. Regression tested them
on x86_64-linux with {unix, native-gdbserver} x {sync, async}. Is
it OK? Below is the introduction of this series. People who are
familiar with this series, please skip it.
This patch series adds the MI notifications of 'trace-started' and
'trace-stopped', which are emitted when
1) trace is started or stopped by commands in GDB,
2) trace is stopped due to some reasons in the remote stub, such as
trace buffer full.
With these notifications, MI front-end can show the status of trace
up to date.
Patch 4/5 is to address #1, adding new MI notifications and
notifying observers when the commands are called. #2 needs more work
here, because GDB doesn't know the trace is stopped in the remote
stub. So we need an async remote notification 'Trace' to tell GDB.
That is what patch 3/5 about. Patch 5/5 is to use this async remote
notification 'Trace' and notify trace_changed observer.
Patch 1/5 and 2/5 are the enhancement to the async remote
notification, which is needed by the rest of patches in this series.
Patch 1/5 adds "annex" for notification, which is helpful 1) to give
more information on each event of notification, 2) to query supported
notifications on "annex" level. Patch 2/5 teaches both GDB and
GDBserver to query supported notifications and annexes in the other
side so that 1) GDBserver doesn't send notifications that GDB doesn't
understand, 2) GDB doesn't have to fetch status from the GDBserver if
a certain notification is supported by GDBserver.
gdb/Makefile.in | 11 +-
gdb/NEWS | 2 +
gdb/common/common-notif.c | 186 ++++++++++++++++++++++++++
gdb/common/common-notif.h | 92 +++++++++++++
gdb/doc/gdb.texinfo | 48 ++++++-
gdb/doc/observer.texi | 6 +
gdb/gdbserver/Makefile.in | 8 +-
gdb/gdbserver/notif.c | 63 ++++++++-
gdb/gdbserver/notif.h | 23 ++--
gdb/gdbserver/server.c | 20 +++-
gdb/gdbserver/tracepoint.c | 36 +++++
gdb/mi/mi-cmds.c | 6 +-
gdb/mi/mi-interp.c | 22 +++
gdb/mi/mi-main.h | 2 +
gdb/remote-notif-trace.c | 86 ++++++++++++
gdb/remote-notif.c | 86 +++++++++++-
gdb/remote-notif.h | 18 +--
gdb/remote.c | 37 ++++-
gdb/testsuite/gdb.trace/mi-trace-changed.exp | 149 +++++++++++++++++++++
gdb/tracepoint.c | 4 +
20 files changed, 851 insertions(+), 54 deletions(-)
create mode 100644 gdb/common/common-notif.c
create mode 100644 gdb/common/common-notif.h
create mode 100644 gdb/remote-notif-trace.c
create mode 100644 gdb/testsuite/gdb.trace/mi-trace-changed.exp
--
1.7.7.6
^ permalink raw reply [flat|nested] 43+ messages in thread* [PATCH 2/5] Query supported notifications by qSupported
2013-04-02 2:33 ` [PATCH v4 0/5] MI notification on trace started/stopped Yao Qi
@ 2013-04-02 3:15 ` Yao Qi
2013-04-02 3:58 ` [PATCH 3/5] async remote notification 'Trace' Yao Qi
` (4 subsequent siblings)
5 siblings, 0 replies; 43+ messages in thread
From: Yao Qi @ 2013-04-02 3:15 UTC (permalink / raw)
To: gdb-patches
As we we adding more notifications and annexes, both GDB and GDBserver
has to know what notifications and annexes 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.A1.A2,N3
(GDB supports notification N1, N2 with annexes A1,A2, and N3)
<-- XXX;Notifications=N1,N2.A1,N4
(GDBsever supports notification N1, N2 with annex A1 and N4)
after this, GDB knows what notifications GDBserver is able to send,
and GDBservers knows what notifications GDB doesn't support.
The documentation patch was approved by Eli here
<http://sourceware.org/ml/gdb-patches/2013-03/msg00474.html>
gdb/gdbserver:
2013-04-02 Yao Qi <yao@codesourcery.com>
* Makefile.in (SFILES): Add "common-notif.c".
(OBS): Add common-notif.o.
(common-notif.o): New rule.
* notif.c (notif_qsupported_record): New.
(notif_qsupported_reply): New.
* notif.h (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:
2013-04-02 Yao Qi <yao@codesourcery.com>
* common/common-notif.c: New.
* common/common-notif.h (struct notif_annex) <supported>: New
field.
(NOTIF_ANNEX_SUPPORTED_P): New macro.
(notif_supported, notif_parse_supported): Declare.
* Makefile.in (REMOTE_OBS): Append "common-notif.o".
(SFILES): Add "common-notif.c".
* remote-notif.c (remote_notif_parse_1): Call the parser of
annex if it is supported.
(remote_notif_qsupported): New.
(remote_notif_qsupported_reply): New.
* remote-notif.h (remote_notif_qsupported): Declare.
(remote_notif_qsupported_reply): Declare.
* remote.c (PACKET_notifications): New enum.
(remote_notifications_feature): New.
(remote_protocol_features): Add new element.
(remote_query_supported): Call remote_notif_qsupported and
append supported notifications to qSupported feature.
(notif_client_annex_stop): Update.
gdb/doc:
2013-04-02 Yao Qi <yao@codesourcery.com>
* gdb.texinfo (General Query Packets): Document the new feature
'notifications' of 'qSupported' packet.
Document the new feature in qSupported reply.
---
gdb/Makefile.in | 9 ++-
gdb/common/common-notif.c | 186 +++++++++++++++++++++++++++++++++++++++++++++
gdb/common/common-notif.h | 15 ++++
gdb/doc/gdb.texinfo | 22 +++++
gdb/gdbserver/Makefile.in | 8 ++-
gdb/gdbserver/notif.c | 21 +++++
gdb/gdbserver/notif.h | 2 +
gdb/gdbserver/server.c | 15 ++++-
gdb/remote-notif.c | 32 +++++++-
gdb/remote-notif.h | 4 +
gdb/remote.c | 24 +++++-
11 files changed, 328 insertions(+), 10 deletions(-)
create mode 100644 gdb/common/common-notif.c
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index fa4c302..3fe3e34 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -511,7 +511,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 common-notif.o
# This is remote-sim.o if a simulator is to be linked in.
SIM_OBS = @SIM_OBS@
@@ -737,7 +737,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 \
+ common-notif.c reverse.c \
sentinel-frame.c \
serial.c ser-base.c ser-unix.c skip.c \
solib.c solib-target.c source.c \
@@ -1928,6 +1929,10 @@ common-utils.o: ${srcdir}/common/common-utils.c
$(COMPILE) $(srcdir)/common/common-utils.c
$(POSTCOMPILE)
+common-notif.o: ${srcdir}/common/common-notif.c
+ $(COMPILE) $(srcdir)/common/common-notif.c
+ $(POSTCOMPILE)
+
gdb_vecs.o: ${srcdir}/common/gdb_vecs.c
$(COMPILE) $(srcdir)/common/gdb_vecs.c
$(POSTCOMPILE)
diff --git a/gdb/common/common-notif.c b/gdb/common/common-notif.c
new file mode 100644
index 0000000..e53729f
--- /dev/null
+++ b/gdb/common/common-notif.c
@@ -0,0 +1,186 @@
+/* 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/>. */
+
+#ifdef GDBSERVER
+#include "server.h"
+#else
+#include "defs.h"
+#endif
+#include <string.h>
+#include "common-notif.h"
+#include "gdb_assert.h"
+
+/* Return a string about the notifications in array NOTIFS. NUM is
+ the number of elements in array NOTIFS. The caller is responsible
+ to free the returned string. Suppose array NOTIFS has
+ notifications N1, N2, and N3. Only N2 has annexes A1 and A2. The
+ returned string is "N1,N2.A2.A2,N3". */
+
+char *
+notif_supported (struct notif_base *notifs[], int num)
+{
+ int i;
+ char * p = NULL;
+
+#define BUF_LEN 128
+
+ for (i = 0; i < num; i++)
+ {
+ struct notif_base *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);
+
+ if (NOTIF_HAS_ANNEX (nb))
+ {
+ int j;
+
+ NOTIF_ITER_ANNEX (nb, j)
+ {
+ xsnprintf (p + strlen (p), BUF_LEN - strlen (p),
+ ".%s", nb->annexes[j].name);
+ }
+ }
+ }
+
+ return p;
+}
+
+/* Find annex in notification NB by name NAME and length LEN.
+ If found, return annex, otherwise return NULL. */
+
+static struct notif_annex *
+notif_find_annex (struct notif_base *nb, const char *name, int len)
+{
+ if (NOTIF_HAS_ANNEX (nb))
+ {
+ int j;
+
+ NOTIF_ITER_ANNEX (nb, j)
+ if (strncmp (name, nb->annexes[j].name, len) == 0
+ && len == strlen (nb->annexes[j].name))
+ return &nb->annexes[j];
+ }
+ return NULL;
+}
+
+/* Parse the REPLY, which is about supported annexes and
+ notifications from the peer, and disable some annexes of
+ notification in array NOTIFS if the peer doesn't support. NUM is
+ the number of elements in array NOTIFS. */
+
+void
+notif_parse_supported (const char *reply,
+ struct notif_base *notifs[], int num)
+{
+ const char *p = reply;
+ int notif_num = 1;
+ char **notif_str;
+ int i;
+
+ /* Count how many notifications in REPLY. */
+ for (i = 0; reply[i] != '\0'; i++)
+ if (reply[i] == ',')
+ notif_num++;
+
+ /* Copy contents of each notification in REPLY to each slot of
+ NOTIF_STR. */
+ notif_str = xmalloc (notif_num * sizeof (char *));
+ for (i = 0; i < notif_num; i++)
+ {
+ char *end = strchr (p, ',');
+
+ if (end == NULL)
+ notif_str[i] = xstrdup (p);
+ else
+ {
+ /* Can't use xstrndup in GDBserver. */
+ notif_str[i] = strndup (p, end - p);
+ p = end + 1;
+ }
+ }
+
+ /* Iterate each element in NOTIF_STR and parse annex in it. */
+ for (i = 0; i < notif_num; i++)
+ {
+ int j;
+ struct notif_base *nb = NULL;
+
+ p = notif_str[i];
+
+ for (j = 0; j < num; j++)
+ {
+ int name_len = strlen (notifs[j]->notif_name);
+
+ if (0 == strncmp (notifs[j]->notif_name, p, name_len)
+ && (p[name_len] == '.' || p[name_len] == 0))
+ {
+ nb = notifs[j];
+ p += name_len;
+ break;
+ }
+ }
+
+ if (nb != NULL)
+ {
+ if (p[0] == 0)
+ {
+ /* No annex. */
+ gdb_assert (!NOTIF_HAS_ANNEX (nb));
+ nb->annexes[0].supported = 1;
+ }
+ else if (p[0] == '.')
+ {
+ gdb_assert (NOTIF_HAS_ANNEX (nb));
+
+ p++;
+
+ /* Parse the rest of P and look for annexes. */
+ while (p != NULL)
+ {
+ char *end = strchr (p, '.');
+ struct notif_annex *annex = NULL;
+
+ if (end != NULL)
+ {
+ annex = notif_find_annex (nb, p, end - p);
+ p = end + 1;
+ }
+ else
+ {
+ annex = notif_find_annex (nb, p, strlen (p));
+ p = end;
+ }
+
+ /* If annex is known, mark it supported, otherwise
+ skip it because the peer knows the annex but we
+ don't know. */
+ if (annex != NULL)
+ annex->supported = 1;
+ }
+ }
+ else
+ warning (_("Unknown supported notification"));
+ }
+ }
+}
diff --git a/gdb/common/common-notif.h b/gdb/common/common-notif.h
index 5e7e9fa..9a8fb7c 100644
--- a/gdb/common/common-notif.h
+++ b/gdb/common/common-notif.h
@@ -36,6 +36,11 @@ struct notif_annex
notification. */
const char *name;
+ /* This annex is supported by the peer (GDB or GDBserver)? A
+ notification may have multiple annexes and some of them are
+ supported. Annex is the smallest unit of support. */
+ int supported;
+
#ifdef GDBSERVER
/* Write event EVENT to OWN_BUF. */
void (*write) (struct notif_event *event, char *own_buf);
@@ -57,6 +62,10 @@ struct notif_annex
#define NOTIF_HAS_ANNEX(NOTIF) ((NOTIF)->annexes[0].name != NULL)
+/* Whether the annex of notification N is supported. */
+
+#define NOTIF_ANNEX_SUPPORTED_P(N, INDEX) \
+ ((N).annexes[INDEX].supported)
/* "Base class" of a notification. It can be extended in both GDB
and GDBserver to represent a type of notification. */
@@ -75,3 +84,9 @@ struct notif_base
of the notification. */
struct notif_annex *annexes;
};
+
+char *notif_supported (struct notif_base *notifs[], int num);
+
+void notif_parse_supported (const char *reply,
+ struct notif_base *notifs[], int num);
+
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 6cbb8b5..fbf0e1a 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -37298,6 +37298,15 @@ 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 supported notifications,
+separated by commas, it will report notifications supported by the
+stub. Each notification in the string is composed by the name of the
+notification and the annexes, if any, which are separated by periods.
@end table
Stubs should ignore any unknown values for
@@ -37506,6 +37515,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:
@@ -37668,6 +37682,14 @@ 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{annex}@r{]}@dots{}@r{[},@var{name}@r{[}.@var{annex}@r{]}@dots{}@r{]}@dots{}
+@cindex notifications, in remote protocol
+The remote stub supports a string of notifications. @var{name} is
+the name of the notification and @var{annex} is the name of the annex,
+if the notification has the annex. Note that the notification may
+have several annexes, so here could be several @var{annex} parts
+separated by periods.
+
@item Qbtrace:off
The remote stub understands the @samp{Qbtrace:off} packet.
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index 08db2cc..9285bdc 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -155,7 +155,8 @@ SFILES= $(srcdir)/gdbreplay.c $(srcdir)/inferiors.c $(srcdir)/dll.c \
$(srcdir)/common/vec.c $(srcdir)/common/gdb_vecs.c \
$(srcdir)/common/common-utils.c $(srcdir)/common/xml-utils.c \
$(srcdir)/common/linux-osdata.c $(srcdir)/common/ptid.c \
- $(srcdir)/common/buffer.c $(srcdir)/common/linux-btrace.c
+ $(srcdir)/common/buffer.c $(srcdir)/common/linux-btrace.c \
+ $(srcdir)/common/common-notif.c
DEPFILES = @GDBSERVER_DEPFILES@
@@ -165,7 +166,7 @@ SOURCES = $(SFILES)
TAGFILES = $(SOURCES) ${HFILES} ${ALLPARAM} ${POSSLIBS}
OBS = agent.o ax.o inferiors.o regcache.o remote-utils.o server.o signals.o target.o \
- utils.o version.o vec.o gdb_vecs.o \
+ utils.o version.o vec.o gdb_vecs.o common-notif.o \
mem-break.o hostio.o event-loop.o tracepoint.o \
xml-utils.o common-utils.o ptid.o buffer.o format.o \
dll.o notif.o \
@@ -521,6 +522,9 @@ linux-ptrace.o: ../common/linux-ptrace.c
common-utils.o: ../common/common-utils.c
$(COMPILE) $<
$(POSTCOMPILE)
+common-notif.o: ../common/common-notif.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
vec.o: ../common/vec.c
$(COMPILE) $<
$(POSTCOMPILE)
diff --git a/gdb/gdbserver/notif.c b/gdb/gdbserver/notif.c
index 9300697..2b09078 100644
--- a/gdb/gdbserver/notif.c
+++ b/gdb/gdbserver/notif.c
@@ -183,6 +183,27 @@ 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)
+{
+ return notif_parse_supported (gdb_notifications,
+ (struct notif_base **) notifs,
+ ARRAY_SIZE (notifs));
+}
+
+/* Return a string about notifications that GDBserver supports.
+ Return NULL if no notification is supported. */
+
+char *
+notif_qsupported_reply (void)
+{
+ return notif_supported ((struct notif_base **) notifs,
+ ARRAY_SIZE (notifs));
+}
+
void
initialize_notif (void)
{
diff --git a/gdb/gdbserver/notif.h b/gdb/gdbserver/notif.h
index 9bdb299..31f135f 100644
--- a/gdb/gdbserver/notif.h
+++ b/gdb/gdbserver/notif.h
@@ -58,6 +58,8 @@ 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 8c00b7c..1f9d526 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -186,7 +186,7 @@ vstop_notif_reply (struct notif_event *event, char *own_buf)
static struct notif_annex notif_annex_stop[] =
{
- { NULL, vstop_notif_reply, },
+ { NULL, 1, vstop_notif_reply, },
};
struct notif_server notif_stop =
@@ -1734,6 +1734,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);
@@ -1821,6 +1826,14 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
strcat (own_buf, ";Qbtrace:off+");
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 335572b..c2d64f6 100644
--- a/gdb/remote-notif.c
+++ b/gdb/remote-notif.c
@@ -75,9 +75,16 @@ remote_notif_parse_1 (struct notif_client *nc,
contents in BUF. */
&& buf[strlen (m->name)] == ':')
{
- /* Pass BUF without annex and ':'. */
- m->parse (nc, buf + strlen (m->name) + 1, event);
- break;
+ if (m->supported)
+ {
+ /* Pass BUF without annex and ':'. */
+ m->parse (nc, buf + strlen (m->name) + 1, event);
+ break;
+ }
+ else
+ warning (_("GDB gets annex '%s' of notification '%s'"
+ "but remote stub doesn't support"),
+ base->notif_name, m->name);
}
m = NULL;
}
@@ -305,6 +312,25 @@ notif_xfree (struct notif_client *notif)
xfree (notif);
}
+/* Return a string of GDB supported features. */
+
+char *
+remote_notif_qsupported (void)
+{
+ return notif_supported ((struct notif_base **) notifs,
+ ARRAY_SIZE (notifs));
+}
+
+/* Parse the qSupported reply REPLY from the remote stub and disable
+ some notifications if the remote stub doesn't support. */
+
+void
+remote_notif_qsupported_reply (const char *reply)
+{
+ notif_parse_supported (reply, (struct notif_base **) notifs,
+ ARRAY_SIZE (notifs));
+}
+
/* -Wmissing-prototypes */
extern initialize_file_ftype _initialize_notif;
diff --git a/gdb/remote-notif.h b/gdb/remote-notif.h
index fd38ea4..088713a 100644
--- a/gdb/remote-notif.h
+++ b/gdb/remote-notif.h
@@ -69,6 +69,10 @@ void remote_notif_register_async_event_handler (void);
void remote_notif_unregister_async_event_handler (void);
void remote_notif_process (struct notif_client *except);
+
+char * remote_notif_qsupported (void);
+void remote_notif_qsupported_reply (const char *reply);
+
extern struct notif_client notif_client_stop;
extern int notif_debug;
diff --git a/gdb/remote.c b/gdb/remote.c
index e435354..8bd70e6 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -1284,6 +1284,7 @@ enum {
PACKET_Qbtrace_off,
PACKET_Qbtrace_bts,
PACKET_qXfer_btrace,
+ PACKET_notifications,
PACKET_MAX
};
@@ -3928,6 +3929,15 @@ remote_string_tracing_feature (const struct protocol_feature *feature,
rs->string_tracing = (support == PACKET_ENABLE);
}
+static void
+remote_notifications_feature (const struct protocol_feature *feature,
+ enum packet_support support,
+ const char *value)
+{
+ if (support == PACKET_ENABLE)
+ remote_notif_qsupported_reply (value);
+}
+
static struct protocol_feature remote_protocol_features[] = {
{ "PacketSize", PACKET_DISABLE, remote_packet_size, -1 },
{ "qXfer:auxv:read", PACKET_DISABLE, remote_supported_packet,
@@ -4000,7 +4010,9 @@ static 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;
@@ -4065,6 +4077,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+");
@@ -4074,6 +4087,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);
@@ -5268,7 +5285,10 @@ remote_notif_stop_alloc_reply (void)
static struct notif_annex notif_client_annex_stop[] =
{
- { NULL, remote_notif_stop_parse, },
+ /* Even the remote stub doesn't understand
+ 'qSupported:notifications=', it may still support notification
+ stop if it supports non-stop. */
+ { NULL, 1, remote_notif_stop_parse, },
};
/* A client of notification Stop. */
--
1.7.7.6
^ permalink raw reply [flat|nested] 43+ messages in thread* [PATCH 3/5] async remote notification 'Trace'.
2013-04-02 2:33 ` [PATCH v4 0/5] MI notification on trace started/stopped Yao Qi
2013-04-02 3:15 ` [PATCH 2/5] Query supported notifications by qSupported Yao Qi
@ 2013-04-02 3:58 ` Yao Qi
2013-04-02 12:46 ` [PATCH 5/5] MI notification on trace stop: triggered by remote Yao Qi
` (3 subsequent siblings)
5 siblings, 0 replies; 43+ messages in thread
From: Yao Qi @ 2013-04-02 3:58 UTC (permalink / raw)
To: gdb-patches
Hi,
This patch adds a new async remote notification 'Trace' to report the
trace-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
and of course, it can be used for other trace-related changes, with
different annex.
The documentation patch was approved by Eli here
<http://sourceware.org/ml/gdb-patches/2013-02/msg00440.html>
gdb/gdbserver:
* notif.c (notifs): Add "notif_trace".
* notif.h (ontif_trace): Declare.
* tracepoint.c [!IN_PROCESS_AGENT]: Include "notif.h".
(notif_reply_trace): New.
(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.
(NOTIF_ANNEX_TRACE_STATUS): New macro.
* 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 | 4 +-
gdb/doc/gdb.texinfo | 10 ++++++
gdb/gdbserver/notif.c | 1 +
gdb/gdbserver/notif.h | 1 +
gdb/gdbserver/tracepoint.c | 36 +++++++++++++++++++++
gdb/remote-notif-trace.c | 75 ++++++++++++++++++++++++++++++++++++++++++++
gdb/remote-notif.c | 1 +
gdb/remote-notif.h | 1 +
8 files changed, 127 insertions(+), 2 deletions(-)
create mode 100644 gdb/remote-notif-trace.c
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 3fe3e34..35bbd65 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -511,7 +511,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 common-notif.o
+ remote-notif.o ctf.o common-notif.o remote-notif-trace.o
# This is remote-sim.o if a simulator is to be linked in.
SIM_OBS = @SIM_OBS@
@@ -738,7 +738,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
proc-service.list progspace.c \
prologue-value.c psymtab.c \
regcache.c reggroups.c remote.c remote-fileio.c remote-notif.c \
- common-notif.c reverse.c \
+ common-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 fbf0e1a..1325012 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -36465,6 +36465,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{}}
@@ -38447,6 +38449,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.
@@ -38981,6 +38984,13 @@ 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 @code{status}
+@tab @var{reply}. The @var{reply} has the form of the reply to packet
+@samp{qTStatus}, as described in @ref{qTStatus packet}.
+@tab Report an asynchronous trace-related event.
+
@end multitable
@node Remote Non-Stop
diff --git a/gdb/gdbserver/notif.c b/gdb/gdbserver/notif.c
index 2b09078..8921ee7 100644
--- a/gdb/gdbserver/notif.c
+++ b/gdb/gdbserver/notif.c
@@ -52,6 +52,7 @@
static struct notif_server *notifs[] =
{
¬if_stop,
+ ¬if_trace,
};
/* Helper function to write EVENT of NOTIF to buffer OWN_BUF. */
diff --git a/gdb/gdbserver/notif.h b/gdb/gdbserver/notif.h
index 31f135f..0735461 100644
--- a/gdb/gdbserver/notif.h
+++ b/gdb/gdbserver/notif.h
@@ -55,6 +55,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 419765b..27b17a9 100644
--- a/gdb/gdbserver/tracepoint.c
+++ b/gdb/gdbserver/tracepoint.c
@@ -3368,6 +3368,32 @@ 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)
+{
+ cmd_qtstatus (own_buf);
+}
+
+#define NOTIF_ANNEX_TRACE_STATUS 0
+
+static struct notif_annex notif_annex_trace[] =
+{
+ { "status", 0, notif_reply_trace, },
+ { NULL, 0, NULL, },
+};
+
+struct notif_server notif_trace =
+{
+ { "Trace", "vTraced", notif_annex_trace, }, NULL,
+};
+
+#endif
+
/* End a tracing run, filling in a stop reason to report back to GDB,
and removing the tracepoints from the code. */
@@ -3468,6 +3494,16 @@ stop_tracing (void)
}
unpause_all (1);
+
+ if (NOTIF_ANNEX_SUPPORTED_P (notif_trace.base,
+ NOTIF_ANNEX_TRACE_STATUS))
+ {
+ struct notif_annex_event *event
+ = xmalloc (sizeof (struct notif_annex_event));
+
+ event->annex_index = NOTIF_ANNEX_TRACE_STATUS;
+ notif_push (¬if_trace, (struct notif_event *) event);
+ }
}
static int
diff --git a/gdb/remote-notif-trace.c b/gdb/remote-notif-trace.c
new file mode 100644
index 0000000..a0cfa26
--- /dev/null
+++ b/gdb/remote-notif-trace.c
@@ -0,0 +1,75 @@
+/* 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_status_parse (struct notif_client *self, char *buf,
+ struct notif_event *event)
+{
+ struct trace_status *ts = current_trace_status ();
+
+ gdb_assert (buf[0] == 'T');
+ parse_trace_status (buf + 1, ts);
+}
+
+static void
+remote_notif_trace_ack (struct notif_client *self, char *buf,
+ struct notif_event *event)
+{
+ /* acknowledge */
+ putpkt ((char *) self->base.ack_name);
+}
+
+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;
+}
+
+static struct notif_annex notif_client_trace_annex[] =
+{
+ { "status", 0, remote_notif_trace_status_parse, },
+ { NULL, 0, NULL, },
+};
+
+/* A client of notification 'Trace'. */
+
+struct notif_client notif_client_trace =
+{
+ { "Trace", "vTraced", notif_client_trace_annex, },
+ remote_notif_trace_ack,
+ remote_notif_trace_can_get_pending_events,
+ remote_notif_trace_alloc_event,
+ NULL,
+};
diff --git a/gdb/remote-notif.c b/gdb/remote-notif.c
index c2d64f6..31ddaab 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,
};
static void do_notif_event_xfree (void *arg);
diff --git a/gdb/remote-notif.h b/gdb/remote-notif.h
index 088713a..b413342 100644
--- a/gdb/remote-notif.h
+++ b/gdb/remote-notif.h
@@ -74,6 +74,7 @@ char * remote_notif_qsupported (void);
void remote_notif_qsupported_reply (const char *reply);
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] 43+ messages in thread* [PATCH 5/5] MI notification on trace stop: triggered by remote
2013-04-02 2:33 ` [PATCH v4 0/5] MI notification on trace started/stopped Yao Qi
2013-04-02 3:15 ` [PATCH 2/5] Query supported notifications by qSupported Yao Qi
2013-04-02 3:58 ` [PATCH 3/5] async remote notification 'Trace' Yao Qi
@ 2013-04-02 12:46 ` Yao Qi
2013-04-02 13:07 ` [PATCH 4/5] MI notification on trace started/stopped:basic Yao Qi
` (2 subsequent siblings)
5 siblings, 0 replies; 43+ messages in thread
From: Yao Qi @ 2013-04-02 12:46 UTC (permalink / raw)
To: gdb-patches
As a result of previous patch, GDB has a Trace rsp notification.
In this patch, GDB starts to use Trace notification, and emits MI
notification '=trace-stopped' to front-end. A test case is
added to see if MI trace-stopped notification is emitted when trace
buffer is full.
gdb:
* remote-notif-trace.c: Include "observer.h".
(remote_notif_trace_status_parse): Call
observer_notify_trace_changed.
gdb/testsuite:
* gdb.trace/mi-trace-changed.exp (test_trace_buffer_full): New.
---
gdb/remote-notif-trace.c | 11 ++++
gdb/testsuite/gdb.trace/mi-trace-changed.exp | 75 ++++++++++++++++++++++++++
2 files changed, 86 insertions(+), 0 deletions(-)
diff --git a/gdb/remote-notif-trace.c b/gdb/remote-notif-trace.c
index a0cfa26..8c1e8a8 100644
--- a/gdb/remote-notif-trace.c
+++ b/gdb/remote-notif-trace.c
@@ -22,6 +22,7 @@
#include "remote.h"
#include "tracepoint.h"
#include "remote-notif.h"
+#include "observer.h"
static void
remote_notif_trace_status_parse (struct notif_client *self, char *buf,
@@ -31,6 +32,16 @@ remote_notif_trace_status_parse (struct notif_client *self, char *buf,
gdb_assert (buf[0] == 'T');
parse_trace_status (buf + 1, ts);
+
+ /* When the tracing is stopped, there is no changes anymore in
+ the trace, so the remote stub can't send another notification.
+ We don't have to worry about notifying 'trace_changed' observer
+ with argument 1 twice.
+ The remote stub can't request tracing start and the remote stub
+ may send multiple trace notifications on various status changes,
+ we don't notify 'trace_changed' observer with argument 0. */
+ if (!ts->running)
+ observer_notify_trace_changed (0);
}
static void
diff --git a/gdb/testsuite/gdb.trace/mi-trace-changed.exp b/gdb/testsuite/gdb.trace/mi-trace-changed.exp
index fbd6fe7..9d6cfff 100644
--- a/gdb/testsuite/gdb.trace/mi-trace-changed.exp
+++ b/gdb/testsuite/gdb.trace/mi-trace-changed.exp
@@ -71,4 +71,79 @@ proc test_normal_tstart_stop { } {
test_normal_tstart_stop
+# Verify that MI notification '=trace-stopped' is emitted when trace
+# buffer is full.
+
+proc test_trace_buffer_full { } {
+ with_test_prefix "tracebuffer full" {
+ global mi_gdb_prompt
+
+ if [mi_gdb_start] {
+ return
+ }
+ mi_run_to_main
+
+ mi_gdb_test "-break-insert -a func2" {.*\^done,bkpt=.*} \
+ "insert tracepoint on func2"
+
+ send_gdb "actions\n"
+ gdb_expect {
+ -re "End with" {
+ }
+ }
+
+ send_gdb "collect buf\nend\n"
+ set test "define actions"
+ gdb_expect {
+ -re ".*${mi_gdb_prompt}$" {
+ pass $test
+ }
+ timeout {
+ fail "$test (timeout)"
+ }
+ }
+
+ # 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 "-break-insert end" {.*\^done,bkpt=.*} \
+ "insert breakpoint on end"
+
+ mi_send_resuming_command "exec-continue" \
+ "continuing execution to end"
+
+ set test "trace-stopped triggered by bufferfull"
+ gdb_expect {
+ # We don't set stop-notes.
+ -re "=trace-stopped\\\\n" {
+ pass "$test"
+ }
+ timeout {
+ fail "$test (timeout)"
+ }
+ }
+
+ global async
+ # In sync mode, eat all the output. Don't have to do so in
+ # async mode.
+ if {!$async} {
+ gdb_expect {
+ -re ".*${mi_gdb_prompt}$" {
+ }
+ }
+ }
+ # GDB has got the rsp notifcation from remote stub that trace
+ # is stopped.
+ mi_gdb_test "tstop" ".*Trace is not running.*" \
+ "tstop on stopped"
+
+ mi_gdb_test "-trace-status" ".*\\^done.*stop-reason=\"overflow\".*" \
+ "trace-status"
+
+ mi_gdb_exit
+ }
+}
+
+test_trace_buffer_full
+
return 0
--
1.7.7.6
^ permalink raw reply [flat|nested] 43+ messages in thread* [PATCH 4/5] MI notification on trace started/stopped:basic
2013-04-02 2:33 ` [PATCH v4 0/5] MI notification on trace started/stopped Yao Qi
` (2 preceding siblings ...)
2013-04-02 12:46 ` [PATCH 5/5] MI notification on trace stop: triggered by remote Yao Qi
@ 2013-04-02 13:07 ` Yao Qi
2013-04-02 13:30 ` [PATCH 1/5] Add annex in a async remote notification Yao Qi
2013-04-10 15:46 ` [PATCH v4 0/5] MI notification on trace started/stopped Yao Qi
5 siblings, 0 replies; 43+ messages in thread
From: Yao Qi @ 2013-04-02 13:07 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 56b68d8..f635f9f 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -23,6 +23,8 @@ show remote trace-status-packet
** 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".
*** Changes in GDB 7.6
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 1325012..d9b2bc0 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -28090,6 +28090,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 adb7085..17e3588 100644
--- a/gdb/doc/observer.texi
+++ b/gdb/doc/observer.texi
@@ -249,6 +249,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 df173fe..f2c037d 100644
--- a/gdb/mi/mi-cmds.c
+++ b/gdb/mi/mi-cmds.c
@@ -146,9 +146,11 @@ static struct mi_cmd mi_cmds[] =
&mi_suppress_notification.traceframe),
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 2702f4f..ba2277a 100644
--- a/gdb/mi/mi-interp.c
+++ b/gdb/mi/mi-interp.c
@@ -68,6 +68,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);
@@ -133,6 +134,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);
@@ -620,6 +622,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 009db82..feeb618 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -1850,6 +1850,8 @@ start_tracing (char *notes)
/* Now insert traps and begin collecting data. */
target_trace_start ();
+ observer_notify_trace_changed (1);
+
/* Reset our local state. */
set_traceframe_num (-1);
set_tracepoint_num (-1);
@@ -1935,6 +1937,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] 43+ messages in thread* [PATCH 1/5] Add annex in a async remote notification.
2013-04-02 2:33 ` [PATCH v4 0/5] MI notification on trace started/stopped Yao Qi
` (3 preceding siblings ...)
2013-04-02 13:07 ` [PATCH 4/5] MI notification on trace started/stopped:basic Yao Qi
@ 2013-04-02 13:30 ` Yao Qi
2013-04-10 15:46 ` [PATCH v4 0/5] MI notification on trace started/stopped Yao Qi
5 siblings, 0 replies; 43+ messages in thread
From: Yao Qi @ 2013-04-02 13:30 UTC (permalink / raw)
To: gdb-patches
In order to support "Trace:status" notification and other similar
usage (such as "Point:modified", about a tracepoint is modified), we
introduce "annex" in the async remote notification, which is helpful
to give us more details what the contents about in the async remote
notification. The annex in each notification is optional. In the
RSP:
<-- %name:annex1:event
--> vAck
<-- annex2:event
--> vAck
<-- annex1:event
--> OK
As we can see above, three events of two annexes (annex1 and annex2)
are sent.
The parsing (receiving rsp packet) and writing (sending rsp packet)
can be done on the annex level. Each annex has its own routines to
send and parse packet, which is more OO.
Also, annex, instead of notification, is the unit of support and they
(GDB and GDBserver) can exchange their supported annexes by means of
qSupported mechanism, which is done in the next patch.
This patch adds "annex" to both GDB and GDBserver. I find 'struct
notif_client' and 'struct notif_server' have three fields which can be
shared, so additionally, we move some shared struct to
common/common-notif.h.
The documentation patch was approved by Eli here
<http://sourceware.org/ml/gdb-patches/2013-02/msg00438.html>
gdb:
2013-04-02 Yao Qi <yao@codesourcery.com>
* common/common-notif.h: New.
* Makefile.in (HFILES_NO_SRCDIR): Add "common/common-notif.h".
* remote-notif.h: Include "common-notif.h".
(struct notif_client) <name, ack_command, parse>: Remove.
<base>: New.
Caller update.
* remote-notif.c (remote_notif_parse_1): New.
(remote_notif_ack): Call remote_notif_parse_1.
(remote_notif_parse): Likewise.
(struct notif_client_annex): New.
* remote.c (notif_client_annex_stop): New.
gdb/gdbserver:
2013-04-02 Yao Qi <yao@codesourcery.com>
* notif.h: Include "common-notif.h".
(struct notif_server) <write, ack_name, notif_name>: Remove.
<base>: New field.
Caller update.
(struct notif_annex_event): New.
* notif.c (notif_write_event_1): New.
(notif_write_event): Call notif_write_event_1 to write event.
(notif_push): Likewise.
* server.c (notif_annex_stop): New.
(notif_stop): Update.
gdb/doc:
2013-04-02 Yao Qi <yao@codesourcery.com>
* gdb.texinfo (Notification Packets): Document 'annex'.
---
gdb/Makefile.in | 2 +-
gdb/common/common-notif.h | 77 +++++++++++++++++++++++++++++++++++++++++++++
gdb/doc/gdb.texinfo | 12 +++++--
gdb/gdbserver/notif.c | 41 ++++++++++++++++++++----
gdb/gdbserver/notif.h | 20 ++++++-----
gdb/gdbserver/server.c | 7 +++-
gdb/remote-notif.c | 59 +++++++++++++++++++++++++++++-----
gdb/remote-notif.h | 13 +------
gdb/remote.c | 15 +++++---
9 files changed, 199 insertions(+), 47 deletions(-)
create mode 100644 gdb/common/common-notif.h
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 9bab01c..fa4c302 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -838,7 +838,7 @@ common/common-utils.h common/xml-utils.h common/buffer.h common/ptid.h \
common/format.h common/host-defs.h utils.h common/queue.h \
common/linux-osdata.h gdb-dlfcn.h auto-load.h probe.h stap-probe.h \
gdb_bfd.h sparc-ravenscar-thread.h ppc-ravenscar-thread.h common/linux-btrace.h \
-ctf.h
+ctf.h common/common-notif.h
# Header files that already have srcdir in them, or which are in objdir.
diff --git a/gdb/common/common-notif.h b/gdb/common/common-notif.h
new file mode 100644
index 0000000..5e7e9fa
--- /dev/null
+++ b/gdb/common/common-notif.h
@@ -0,0 +1,77 @@
+/* Shared structs of asynchronous remote notification.
+
+ 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/>. */
+
+struct notif_event;
+#ifndef GDBSERVER
+struct notif_client;
+#endif
+
+/* An annex of a notification. A notification may or may not have
+ annexes. */
+
+struct notif_annex
+{
+ /* Name of this annex. If it is NULL, the notification doesn't have
+ annex, and the field PARSE and SUPPORTED is about the
+ notification this annex belongs to. For example, notification
+ event "N1:event" doesn't have an annex in the packet, but the
+ notification object still has one instance of 'notif_annex', and
+ its field <name> is NULL. The field <supported> is about the
+ notification. */
+ const char *name;
+
+#ifdef GDBSERVER
+ /* Write event EVENT to OWN_BUF. */
+ void (*write) (struct notif_event *event, char *own_buf);
+#else
+ /* Parse BUF to get the expected event and update EVENT. This
+ function may throw exception if contents in BUF is not the
+ expected event. */
+ void (*parse) (struct notif_client *self, char *buf,
+ struct notif_event *event);
+#endif
+};
+
+/* Iterate over annexes in *NOTIF by increasing INDEX from zero. */
+
+#define NOTIF_ITER_ANNEX(NOTIF, INDEX) \
+ for (INDEX = 0; (NOTIF)->annexes[INDEX].name != NULL; INDEX++)
+
+/* Notification *NOTIF has annex or not. */
+
+#define NOTIF_HAS_ANNEX(NOTIF) ((NOTIF)->annexes[0].name != NULL)
+
+
+/* "Base class" of a notification. It can be extended in both GDB
+ and GDBserver to represent a type of notification. */
+
+struct notif_base
+{
+ /* The notification packet, for example, '%Stop'. Note that '%' is
+ not in 'notif_name'. */
+ const char *notif_name;
+ /* The name of ack packet, for example, 'vStopped'. */
+ const char *ack_name;
+
+ /* Annexes the notification has. The notification may or not have
+ annexes. Macro 'NOTIF_HAS_ANNEX' is to check notification has
+ annexes, and macro 'NOTIF_ITER_ANNEX' is to iterate over annexes
+ of the notification. */
+ struct notif_annex *annexes;
+};
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 3b63d01..6cbb8b5 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -38871,13 +38871,15 @@ transmit notifications without fear of confusing older clients. There
are no notifications defined for @value{GDBN} to send at the moment, but we
assume that most older stubs would ignore them, as well.)
-Each notification is comprised of three parts:
+Each notification is comprised of four parts:
@table @samp
-@item @var{name}:@var{event}
+@item @var{name}[:@var{annex}]:@var{event}
The notification packet is sent by the side that initiates the
exchange (currently, only the stub does that), with @var{event}
carrying the specific information about the notification.
-@var{name} is the name of the notification.
+@var{name} is the name of the notification. The @var{annex} is
+specific to @var{name}; it can supply additional details about
+@var{event}.
@item @var{ack}
The acknowledge sent by the other side, usually @value{GDBN}, to
acknowledge the exchange and request the event.
@@ -38940,15 +38942,17 @@ following example:
@end smallexample
The following notifications are defined:
-@multitable @columnfractions 0.12 0.12 0.38 0.38
+@multitable @columnfractions 0.10 0.10 0.10 0.35 0.35
@item Notification
@tab Ack
+@tab Annex
@tab Event
@tab Description
@item Stop
@tab vStopped
+@tab
@tab @var{reply}. The @var{reply} has the form of a stop reply, as
described in @ref{Stop Reply Packets}. Refer to @ref{Remote Non-Stop},
for information on how these notifications are acknowledged by
diff --git a/gdb/gdbserver/notif.c b/gdb/gdbserver/notif.c
index e27746e..9300697 100644
--- a/gdb/gdbserver/notif.c
+++ b/gdb/gdbserver/notif.c
@@ -54,6 +54,30 @@ static struct notif_server *notifs[] =
¬if_stop,
};
+/* Helper function to write EVENT of NOTIF to buffer OWN_BUF. */
+
+static void
+notif_write_event_1 (struct notif_base *notif,
+ struct notif_event *event,
+ char *own_buf)
+{
+ int annex_index = 0;
+
+ /* If the NOTIF has annexes, extract the annex index from the
+ EVENT and append annex name to OWN_BUF; otherwise, NOTIF
+ doesn't have annex and use slot 0 of annexes for the
+ notification itself. */
+ if (NOTIF_HAS_ANNEX (notif))
+ {
+ annex_index
+ = ((struct notif_annex_event *) event)->annex_index;
+ sprintf (own_buf, "%s:", notif->annexes[annex_index].name);
+ own_buf += strlen (notif->annexes[annex_index].name) + 1;
+ }
+
+ notif->annexes[annex_index].write (event, own_buf);
+}
+
/* Write another event or an OK, if there are no more left, to
OWN_BUF. */
@@ -65,7 +89,8 @@ notif_write_event (struct notif_server *notif, char *own_buf)
struct notif_event *event
= QUEUE_peek (notif_event_p, notif->queue);
- notif->write (event, own_buf);
+ notif_write_event_1 ((struct notif_base *) notif, event,
+ own_buf);
}
else
write_ok (own_buf);
@@ -84,8 +109,9 @@ handle_notif_ack (char *own_buf, int packet_len)
for (i = 0; i < ARRAY_SIZE (notifs); i++)
{
np = notifs[i];
- if (strncmp (own_buf, np->ack_name, strlen (np->ack_name)) == 0
- && packet_len == strlen (np->ack_name))
+ if (0 == strncmp (own_buf, np->base.ack_name,
+ strlen (np->base.ack_name))
+ && packet_len == strlen (np->base.ack_name))
break;
}
@@ -100,7 +126,7 @@ handle_notif_ack (char *own_buf, int packet_len)
= QUEUE_deque (notif_event_p, np->queue);
if (remote_debug)
- fprintf (stderr, "%s: acking %d\n", np->ack_name,
+ fprintf (stderr, "%s: acking %d\n", np->base.ack_name,
QUEUE_length (notif_event_p, np->queue));
xfree (head);
@@ -120,7 +146,8 @@ notif_event_enque (struct notif_server *notif,
QUEUE_enque (notif_event_p, notif->queue, event);
if (remote_debug)
- fprintf (stderr, "pending events: %s %d\n", notif->notif_name,
+ fprintf (stderr, "pending events: %s %d\n",
+ notif->base.notif_name,
QUEUE_length (notif_event_p, notif->queue));
}
@@ -142,10 +169,10 @@ notif_push (struct notif_server *np, struct notif_event *new_event)
char buf[PBUFSIZ];
char *p = buf;
- xsnprintf (p, PBUFSIZ, "%s:", np->notif_name);
+ xsnprintf (p, PBUFSIZ, "%s:", np->base.notif_name);
p += strlen (p);
- np->write (new_event, p);
+ notif_write_event_1 ((struct notif_base *) np, new_event, p);
putpkt_notif (buf);
}
}
diff --git a/gdb/gdbserver/notif.h b/gdb/gdbserver/notif.h
index 608b763..9bdb299 100644
--- a/gdb/gdbserver/notif.h
+++ b/gdb/gdbserver/notif.h
@@ -20,6 +20,7 @@
#include "server.h"
#include "target.h"
#include "queue.h"
+#include "common-notif.h"
/* Structure holding information related to a single event. We
keep a queue of these to push to GDB. It can be extended if
@@ -31,25 +32,26 @@ typedef struct notif_event
DECLARE_QUEUE_P (notif_event_p);
+/* An event of a notification which has an annex. */
+
+struct notif_annex_event
+{
+ struct notif_event base;
+ /* The index of the annex in field 'annexes' in 'notif_server'. */
+ int annex_index;
+};
+
/* A type notification to GDB. An object of 'struct notif_server'
represents a type of notification. */
typedef struct notif_server
{
- /* The name of ack packet, for example, 'vStopped'. */
- const char *ack_name;
-
- /* The notification packet, for example, '%Stop'. Note that '%' is
- not in 'notif_name'. */
- const char *notif_name;
+ struct notif_base base;
/* A queue of events to GDB. A new notif_event can be enque'ed
into QUEUE at any appropriate time, and the notif_reply is
deque'ed only when the ack from GDB arrives. */
QUEUE (notif_event_p) *queue;
-
- /* Write event EVENT to OWN_BUF. */
- void (*write) (struct notif_event *event, char *own_buf);
} *notif_server_p;
extern struct notif_server notif_stop;
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index 6bb36d8..8c00b7c 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -184,9 +184,14 @@ vstop_notif_reply (struct notif_event *event, char *own_buf)
prepare_resume_reply (own_buf, vstop->ptid, &vstop->status);
}
+static struct notif_annex notif_annex_stop[] =
+{
+ { NULL, vstop_notif_reply, },
+};
+
struct notif_server notif_stop =
{
- "vStopped", "Stop", NULL, vstop_notif_reply,
+ { "Stop", "vStopped", notif_annex_stop, }, NULL,
};
static int
diff --git a/gdb/remote-notif.c b/gdb/remote-notif.c
index c4bfd8d..335572b 100644
--- a/gdb/remote-notif.c
+++ b/gdb/remote-notif.c
@@ -53,6 +53,46 @@ static struct notif_client *notifs[] =
static void do_notif_event_xfree (void *arg);
+/* Iterate over annexes in NC to match annex in BUF. */
+
+static void
+remote_notif_parse_1 (struct notif_client *nc,
+ struct notif_event *event, char *buf)
+{
+ const struct notif_annex *m = NULL;
+ const struct notif_base *base = (struct notif_base *) nc;
+
+ if (NOTIF_HAS_ANNEX (base))
+ {
+ int i;
+
+ NOTIF_ITER_ANNEX (base, i)
+ {
+ m = &base->annexes[i];
+
+ if (strncmp (m->name, buf, strlen (base->notif_name)) == 0
+ /* The annex is separated by ':' for the rest of
+ contents in BUF. */
+ && buf[strlen (m->name)] == ':')
+ {
+ /* Pass BUF without annex and ':'. */
+ m->parse (nc, buf + strlen (m->name) + 1, event);
+ break;
+ }
+ m = NULL;
+ }
+ }
+ else
+ {
+ m = &base->annexes[0];
+ m->parse (nc, buf, event);
+ }
+
+ if (m == NULL)
+ error (_("Can't parse '%s' for notif '%s'"), buf,
+ base->notif_name);
+}
+
/* Parse the BUF for the expected notification NC, and send packet to
acknowledge. */
@@ -65,9 +105,9 @@ remote_notif_ack (struct notif_client *nc, char *buf)
if (notif_debug)
fprintf_unfiltered (gdb_stdlog, "notif: ack '%s'\n",
- nc->ack_command);
+ nc->base.ack_name);
- nc->parse (nc, buf, event);
+ remote_notif_parse_1 (nc, event, buf);
nc->ack (nc, buf, event);
discard_cleanups (old_chain);
@@ -83,9 +123,10 @@ remote_notif_parse (struct notif_client *nc, char *buf)
= make_cleanup (do_notif_event_xfree, event);
if (notif_debug)
- fprintf_unfiltered (gdb_stdlog, "notif: parse '%s'\n", nc->name);
+ fprintf_unfiltered (gdb_stdlog, "notif: parse '%s'\n",
+ nc->base.notif_name);
- nc->parse (nc, buf, event);
+ remote_notif_parse_1 (nc, event, buf);
discard_cleanups (old_chain);
return event;
@@ -158,8 +199,9 @@ handle_notification (char *buf)
for (i = 0; i < ARRAY_SIZE (notifs); i++)
{
nc = notifs[i];
- if (strncmp (buf, nc->name, strlen (nc->name)) == 0
- && buf[strlen (nc->name)] == ':')
+ if (0 == strncmp (buf, nc->base.notif_name,
+ strlen (nc->base.notif_name))
+ && buf[strlen (nc->base.notif_name)] == ':')
break;
nc = NULL;
}
@@ -181,7 +223,8 @@ handle_notification (char *buf)
else
{
struct notif_event *event
- = remote_notif_parse (nc, buf + strlen (nc->name) + 1);
+ = remote_notif_parse (nc,
+ buf + strlen (nc->base.notif_name) + 1);
/* Be careful to only set it after parsing, since an error
may be thrown then. */
@@ -234,7 +277,7 @@ handle_notification (char *buf)
if (notif_debug)
fprintf_unfiltered (gdb_stdlog,
"notif: Notification '%s' captured\n",
- nc->name);
+ nc->base.notif_name);
}
}
diff --git a/gdb/remote-notif.h b/gdb/remote-notif.h
index da4fdea..fd38ea4 100644
--- a/gdb/remote-notif.h
+++ b/gdb/remote-notif.h
@@ -21,6 +21,7 @@
#define REMOTE_NOTIF_H
#include "queue.h"
+#include "common-notif.h"
/* An event of a type of async remote notification. */
@@ -35,17 +36,7 @@ struct notif_event
typedef struct notif_client
{
- /* The name of notification packet. */
- const char *name;
-
- /* The packet to acknowledge a previous reply. */
- const char *ack_command;
-
- /* Parse BUF to get the expected event and update EVENT. This
- function may throw exception if contents in BUF is not the
- expected event. */
- void (*parse) (struct notif_client *self, char *buf,
- struct notif_event *event);
+ struct notif_base base;
/* Send field <ack_command> to remote, and do some checking. If
something wrong, throw an exception. */
diff --git a/gdb/remote.c b/gdb/remote.c
index b8a7a1a..e435354 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -5226,7 +5226,7 @@ remote_notif_stop_ack (struct notif_client *self, char *buf,
struct stop_reply *stop_reply = (struct stop_reply *) event;
/* acknowledge */
- putpkt ((char *) self->ack_command);
+ putpkt ((char *) self->base.ack_name);
if (stop_reply->ws.kind == TARGET_WAITKIND_IGNORE)
/* We got an unknown stop reply. */
@@ -5266,13 +5266,16 @@ remote_notif_stop_alloc_reply (void)
return r;
}
+static struct notif_annex notif_client_annex_stop[] =
+{
+ { NULL, remote_notif_stop_parse, },
+};
+
/* A client of notification Stop. */
struct notif_client notif_client_stop =
{
- "Stop",
- "vStopped",
- remote_notif_stop_parse,
+ { "Stop", "vStopped", notif_client_annex_stop, },
remote_notif_stop_ack,
remote_notif_stop_can_get_pending_events,
remote_notif_stop_alloc_reply,
@@ -5699,7 +5702,7 @@ remote_notif_get_pending_events (struct notif_client *nc)
if (notif_debug)
fprintf_unfiltered (gdb_stdlog,
"notif: process: '%s' ack pending event\n",
- nc->name);
+ nc->base.notif_name);
/* acknowledge */
nc->ack (nc, rs->buf, nc->pending_event);
@@ -5719,7 +5722,7 @@ remote_notif_get_pending_events (struct notif_client *nc)
if (notif_debug)
fprintf_unfiltered (gdb_stdlog,
"notif: process: '%s' no pending reply\n",
- nc->name);
+ nc->base.notif_name);
}
}
--
1.7.7.6
^ permalink raw reply [flat|nested] 43+ messages in thread* Re: [PATCH v4 0/5] MI notification on trace started/stopped
2013-04-02 2:33 ` [PATCH v4 0/5] MI notification on trace started/stopped Yao Qi
` (4 preceding siblings ...)
2013-04-02 13:30 ` [PATCH 1/5] Add annex in a async remote notification Yao Qi
@ 2013-04-10 15:46 ` Yao Qi
2013-04-17 14:37 ` [ping 2]: " Yao Qi
5 siblings, 1 reply; 43+ messages in thread
From: Yao Qi @ 2013-04-10 15:46 UTC (permalink / raw)
To: gdb-patches
On 04/02/2013 10:31 AM, Yao Qi wrote:
> Hi,
> The V3.1 can't be applied to CVS trunk clearly, so I resolved these
> conflicts and submit them again.
>
> All doc bits were approved by Eli in V3.1. Regression tested them
> on x86_64-linux with {unix, native-gdbserver} x {sync, async}. Is
> it OK? Below is the introduction of this series. People who are
> familiar with this series, please skip it.
>
> This patch series adds the MI notifications of 'trace-started' and
> 'trace-stopped', which are emitted when
>
> 1) trace is started or stopped by commands in GDB,
> 2) trace is stopped due to some reasons in the remote stub, such as
> trace buffer full.
>
> With these notifications, MI front-end can show the status of trace
> up to date.
>
> Patch 4/5 is to address #1, adding new MI notifications and
> notifying observers when the commands are called. #2 needs more work
> here, because GDB doesn't know the trace is stopped in the remote
> stub. So we need an async remote notification 'Trace' to tell GDB.
> That is what patch 3/5 about. Patch 5/5 is to use this async remote
> notification 'Trace' and notify trace_changed observer.
>
> Patch 1/5 and 2/5 are the enhancement to the async remote
> notification, which is needed by the rest of patches in this series.
> Patch 1/5 adds "annex" for notification, which is helpful 1) to give
> more information on each event of notification, 2) to query supported
> notifications on "annex" level. Patch 2/5 teaches both GDB and
> GDBserver to query supported notifications and annexes in the other
> side so that 1) GDBserver doesn't send notifications that GDB doesn't
> understand, 2) GDB doesn't have to fetch status from the GDBserver if
> a certain notification is supported by GDBserver.
Ping. http://sourceware.org/ml/gdb-patches/2013-04/msg00019.html
--
Yao (é½å°§)
^ permalink raw reply [flat|nested] 43+ messages in thread* [ping 2]: [PATCH v4 0/5] MI notification on trace started/stopped
2013-04-10 15:46 ` [PATCH v4 0/5] MI notification on trace started/stopped Yao Qi
@ 2013-04-17 14:37 ` Yao Qi
2013-04-18 15:16 ` Pedro Alves
0 siblings, 1 reply; 43+ messages in thread
From: Yao Qi @ 2013-04-17 14:37 UTC (permalink / raw)
To: gdb-patches; +Cc: Pedro Alves
On 04/10/2013 10:50 AM, Yao Qi wrote:
> On 04/02/2013 10:31 AM, Yao Qi wrote:
>> Hi,
>> The V3.1 can't be applied to CVS trunk clearly, so I resolved these
>> conflicts and submit them again.
>>
>> All doc bits were approved by Eli in V3.1. Regression tested them
>> on x86_64-linux with {unix, native-gdbserver} x {sync, async}. Is
>> it OK? Below is the introduction of this series. People who are
>> familiar with this series, please skip it.
>>
>> This patch series adds the MI notifications of 'trace-started' and
>> 'trace-stopped', which are emitted when
>>
>> 1) trace is started or stopped by commands in GDB,
>> 2) trace is stopped due to some reasons in the remote stub, such as
>> trace buffer full.
>>
>> With these notifications, MI front-end can show the status of trace
>> up to date.
>>
>> Patch 4/5 is to address #1, adding new MI notifications and
>> notifying observers when the commands are called. #2 needs more work
>> here, because GDB doesn't know the trace is stopped in the remote
>> stub. So we need an async remote notification 'Trace' to tell GDB.
>> That is what patch 3/5 about. Patch 5/5 is to use this async remote
>> notification 'Trace' and notify trace_changed observer.
>>
>> Patch 1/5 and 2/5 are the enhancement to the async remote
>> notification, which is needed by the rest of patches in this series.
>> Patch 1/5 adds "annex" for notification, which is helpful 1) to give
>> more information on each event of notification, 2) to query supported
>> notifications on "annex" level. Patch 2/5 teaches both GDB and
>> GDBserver to query supported notifications and annexes in the other
>> side so that 1) GDBserver doesn't send notifications that GDB doesn't
>> understand, 2) GDB doesn't have to fetch status from the GDBserver if
>> a certain notification is supported by GDBserver.
>
> Ping. http://sourceware.org/ml/gdb-patches/2013-04/msg00019.html
>
Ping^2.
Pedro,
If you are unable to review this series in a reasonable time frame,
please shout. Then, other maintainers would help to review. I didn't
copy you in my previous pings because I thought other maintainers would
probably review this patch series. After several pings and patch
updating, I presume other maintainers leave this patch to you.
--
Yao (é½å°§)
P.S. I hate to push people in this way here, because we have multiple
maintainers and people have different schedules, but the review is
stalled this time.
^ permalink raw reply [flat|nested] 43+ messages in thread* Re: [ping 2]: [PATCH v4 0/5] MI notification on trace started/stopped
2013-04-17 14:37 ` [ping 2]: " Yao Qi
@ 2013-04-18 15:16 ` Pedro Alves
2013-04-18 16:14 ` Yao Qi
2013-06-04 9:20 ` Yao Qi
0 siblings, 2 replies; 43+ messages in thread
From: Pedro Alves @ 2013-04-18 15:16 UTC (permalink / raw)
To: Yao Qi; +Cc: gdb-patches
I do my best to review as much as possible. In fact, my main
projects keep getting delayed for months as I can't ever find enough time/energy
to focus on them. Unfortunately it tends to happen that I end up needing to
spend a very significant amount of time and energy through the patches/proposals.
The past weeks were a set back, as as you know, 7.6 had issues that needed
addressing. It'd be great if patches/designs and submissions come up perfect
from the get go, or that I was smarter and could review faster, but that's
unfortunately not frequently the case. The bigger the patch/series, the more
likely it is that it needs iteration. I know you have several series waiting to
get in. Please be patient. If you look at CS submissions as a whole, you'll
notice that I'm usually reviewing/iterating over at least one at a
given time. It's just that bigger ones require more energy, so they
take more to get through. Next up, as I said before, is the range stepping
series. Please let me focus on it and get it to completion, and context
switch to the async notifications afterwards.
Thanks,
--
Pedro Alves
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [ping 2]: [PATCH v4 0/5] MI notification on trace started/stopped
2013-04-18 15:16 ` Pedro Alves
@ 2013-04-18 16:14 ` Yao Qi
2013-06-04 9:20 ` Yao Qi
1 sibling, 0 replies; 43+ messages in thread
From: Yao Qi @ 2013-04-18 16:14 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches
On 04/18/2013 08:19 AM, Pedro Alves wrote:
> I do my best to review as much as possible. In fact, my main
Pedro,
I appreciate your reviews and comments greatly. They are very helpful.
> projects keep getting delayed for months as I can't ever find enough time/energy
> to focus on them. Unfortunately it tends to happen that I end up needing to
> spend a very significant amount of time and energy through the patches/proposals.
I fully agree with you that patch review is quite time-consuming.
> The past weeks were a set back, as as you know, 7.6 had issues that needed
> addressing. It'd be great if patches/designs and submissions come up perfect
> from the get go, or that I was smarter and could review faster, but that's
> unfortunately not frequently the case. The bigger the patch/series, the more
> likely it is that it needs iteration. I know you have several series waiting to
The V3 of this series was posted in Jan 22th, and there was no review on
non-doc part since then. I kept doing self-review and resolving
conflicts against trunk, to facilitate reviewers to review. There was
no response, unfortunately.
--
Yao (é½å°§)
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [ping 2]: [PATCH v4 0/5] MI notification on trace started/stopped
2013-04-18 15:16 ` Pedro Alves
2013-04-18 16:14 ` Yao Qi
@ 2013-06-04 9:20 ` Yao Qi
1 sibling, 0 replies; 43+ messages in thread
From: Yao Qi @ 2013-06-04 9:20 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches
On 04/18/2013 08:19 AM, Pedro Alves wrote:
> Next up, as I said before, is the range stepping
> series. Please let me focus on it and get it to completion, and context
> switch to the async notifications afterwards.
Hi, Pedro,
Could you review the async notification patch series recently? The V4
still applies to FSF GDB trunk (as of May 30th) and regression test on
x86_64-linux shows no regression.
--
Yao (é½å°§)
^ permalink raw reply [flat|nested] 43+ messages in thread