This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 3/6] Query supported notifications by qSupported


V5: the supported flag of each annex of notification is saved in
'struct remote_notif_state' in GDB.  In GDBserver, the supported flag
is still associated with each annex.

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:

	* Makefile.in (SFILES): Add "notif-base.c".
	(OBS): Add notif-base.o.
	(notif-base.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:

	* common/notif-base.c: New.
	* common/notif-base.h (struct notif_annex) [GDBSERVER] <supported>:
	New field.
	(struct notif_annex) [!GDBSERVER] <id>: New field.
	(NOTIF_ANNEX_SUPPORTED_P): New macro.
	(notif_supported, notif_parse_supported): Declare.
	* Makefile.in (REMOTE_OBS): Append "notif-base.o".
	(SFILES): Add "notif-base.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:

	* 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/notif-base.c   |  198 +++++++++++++++++++++++++++++++++++++++++++++
 gdb/common/notif-base.h   |   32 +++++++
 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        |  108 +++++++++++++++++++++++--
 gdb/remote-notif.h        |   14 +++-
 gdb/remote.c              |   31 ++++++-
 11 files changed, 440 insertions(+), 19 deletions(-)
 create mode 100644 gdb/common/notif-base.c

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 2dc3ac0..3f83122 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -521,7 +521,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 notif-base.o
 
 # This is remote-sim.o if a simulator is to be linked in.
 SIM_OBS = @SIM_OBS@
@@ -751,7 +751,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 \
+	notif-base.c reverse.c \
 	sentinel-frame.c \
 	serial.c ser-base.c ser-unix.c skip.c \
 	solib.c solib-target.c source.c \
@@ -1975,6 +1976,10 @@ common-utils.o: ${srcdir}/common/common-utils.c
 	$(COMPILE) $(srcdir)/common/common-utils.c
 	$(POSTCOMPILE)
 
+notif-base.o: ${srcdir}/common/notif-base.c
+	$(COMPILE) $(srcdir)/common/notif-base.c
+	$(POSTCOMPILE)
+
 gdb_vecs.o: ${srcdir}/common/gdb_vecs.c
 	$(COMPILE) $(srcdir)/common/gdb_vecs.c
 	$(POSTCOMPILE)
diff --git a/gdb/common/notif-base.c b/gdb/common/notif-base.c
new file mode 100644
index 0000000..3d0a5f7
--- /dev/null
+++ b/gdb/common/notif-base.c
@@ -0,0 +1,198 @@
+/* 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"
+#include "remote-notif.h"
+#endif
+#include <string.h>
+#include "notif-base.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;
+	  struct notif_annex *annex;
+
+	  NOTIF_ITER_ANNEX (nb, j, annex)
+	    {
+	      xsnprintf (p + strlen (p), BUF_LEN - strlen (p),
+			 ".%s", annex->name);
+	    }
+	}
+    }
+
+  return p;
+}
+
+/* Find annex in notification NB by name NAME and length LEN.
+   If found, return its index in NB, otherwise return -1.  */
+
+static int
+notif_find_annex (struct notif_base *nb, const char *name, int len)
+{
+  if (NOTIF_HAS_ANNEX (nb))
+    {
+      int j;
+      struct notif_annex *annex;
+
+      NOTIF_ITER_ANNEX (nb, j, annex)
+	if (strncmp (name, annex->name, len) == 0
+	    && len == strlen (annex->name))
+	  return j;
+    }
+  return -1;
+}
+
+/* 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[],
+#ifdef GDBSERVER
+		       int num)
+#else
+		       int num, struct remote_notif_state *state)
+#endif
+{
+  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));
+	      NOTIF_ANNEX_SUPPORTED (state, nb, 0) = 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, '.');
+		  int index;
+
+		  if (end != NULL)
+		    {
+		      index = notif_find_annex (nb, p, end - p);
+		      p = end + 1;
+		    }
+		  else
+		    {
+		      index = 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 (index >= 0)
+		    NOTIF_ANNEX_SUPPORTED (state, nb, index) = 1;
+		}
+	    }
+	  else
+	    warning (_("Unknown supported notification"));
+	}
+    }
+
+  for (i = 0; i < notif_num; i++)
+    xfree (notif_str[i]);
+
+  xfree (notif_str);
+}
diff --git a/gdb/common/notif-base.h b/gdb/common/notif-base.h
index 0a3a4ed..ddc9293 100644
--- a/gdb/common/notif-base.h
+++ b/gdb/common/notif-base.h
@@ -37,9 +37,18 @@ struct notif_annex
   const char *name;
 
 #ifdef GDBSERVER
+  /* This annex is supported by GDB or not.  A notification may have
+     multiple annexes and some of them are supported.  Annex is the
+     smallest unit of support.  */
+  int supported;
+
   /* Write event EVENT to OWN_BUF.  */
   void (*write) (struct notif_event *event, char *own_buf);
 #else
+  /* The id of the annex.  In GDB, we use this field as an index to
+     access the state of this annex.  */
+  int id;
+
   /* Parse BUF to get the expected event and update EVENT.  This
      function may throw exception if contents in BUF is not the
      expected event.  */
@@ -57,6 +66,15 @@ struct notif_annex
 
 #define NOTIF_HAS_ANNEX(NOTIF) ((NOTIF)->annexes[0].name != NULL)
 
+/* Whether the annex of notification N is supported.  */
+
+#ifdef GDBSERVER
+#define NOTIF_ANNEX_SUPPORTED(STATE, N, INDEX) \
+  ((N)->annexes[INDEX].supported)
+#else
+#define NOTIF_ANNEX_SUPPORTED(STATE, N, INDEX)	\
+  ((STATE)->supported[(N)->annexes[INDEX].id])
+#endif
 
 /* "Base class" of a notification.  It can be extended in both GDB
    and GDBserver to represent a type of notification.  */
@@ -76,4 +94,18 @@ struct notif_base
   struct notif_annex *annexes;
 };
 
+char *notif_supported (struct notif_base *notifs[], int num);
+
+#ifndef GDBSERVER
+struct remote_notif_state;
+#endif
+
+void notif_parse_supported (const char *reply,
+			    struct notif_base *notifs[],
+#ifdef GDBSERVER
+			    int num);
+#else
+			    int num, struct remote_notif_state *state);
+#endif
+
 #endif /* NOTIF_BASE_H */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 375f988..946e132 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -38655,6 +38655,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
@@ -38873,6 +38882,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:
@@ -39040,6 +39054,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 e541497..7c6db6f 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -158,7 +158,7 @@ SFILES=	$(srcdir)/gdbreplay.c $(srcdir)/inferiors.c $(srcdir)/dll.c \
 	$(srcdir)/common/linux-osdata.c $(srcdir)/common/ptid.c \
 	$(srcdir)/common/buffer.c $(srcdir)/common/linux-btrace.c \
 	$(srcdir)/common/filestuff.c $(srcdir)/common/target-common.c \
-    $(srcdir)/common/mips-linux-watch.c
+    $(srcdir)/common/mips-linux-watch.c $(srcdir)/common/notif-base.c
 
 DEPFILES = @GDBSERVER_DEPFILES@
 
@@ -168,7 +168,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 target-common.o utils.o version.o vec.o gdb_vecs.o \
+      target.o target-common.o utils.o version.o vec.o gdb_vecs.o notif-base.o \
       mem-break.o hostio.o event-loop.o tracepoint.o xml-utils.o \
       common-utils.o ptid.o buffer.o format.o filestuff.o dll.o notif.o \
       tdesc.o $(XML_BUILTIN) $(DEPFILES) $(LIBOBJS)
@@ -523,6 +523,9 @@ linux-ptrace.o: ../common/linux-ptrace.c
 common-utils.o: ../common/common-utils.c
 	$(COMPILE) $<
 	$(POSTCOMPILE)
+notif-base.o: ../common/notif-base.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 037f1b0..f33fd04 100644
--- a/gdb/gdbserver/notif.h
+++ b/gdb/gdbserver/notif.h
@@ -60,6 +60,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 71b860d..ce221fc 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -183,7 +183,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 =
@@ -1731,6 +1731,11 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
 		  /* GDB supports relocate instruction requests.  */
 		  gdb_supports_qRelocInsn = 1;
 		}
+	      else if (strncmp (p, "notifications=", 14) == 0)
+		{
+		  /* Record what notifications GDB supports.  */
+		  notif_qsupported_record (&p[14]);
+		}
 	      else
 		target_process_qsupported (p);
 
@@ -1819,6 +1824,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 d901a51..b83ea7e 100644
--- a/gdb/remote-notif.c
+++ b/gdb/remote-notif.c
@@ -57,6 +57,7 @@ static void do_notif_event_xfree (void *arg);
 
 static void
 remote_notif_parse_1 (struct notif_client *nc,
+		      struct remote_notif_state *state,
 		      struct notif_event *event, char *buf)
 {
   const struct notif_annex *m = NULL;
@@ -73,9 +74,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 (state->supported[m->id])
+		{
+		  /* 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;
 	}
@@ -95,7 +103,8 @@ remote_notif_parse_1 (struct notif_client *nc,
    acknowledge.  */
 
 void
-remote_notif_ack (struct notif_client *nc, char *buf)
+remote_notif_ack (struct notif_client *nc,
+		  struct remote_notif_state *state, char *buf)
 {
   struct notif_event *event = nc->alloc_event ();
   struct cleanup *old_chain
@@ -105,7 +114,7 @@ remote_notif_ack (struct notif_client *nc, char *buf)
     fprintf_unfiltered (gdb_stdlog, "notif: ack '%s'\n",
 			nc->base.ack_name);
 
-  remote_notif_parse_1 (nc, event, buf);
+  remote_notif_parse_1 (nc, state, event, buf);
   nc->ack (nc, buf, event);
 
   discard_cleanups (old_chain);
@@ -114,7 +123,8 @@ remote_notif_ack (struct notif_client *nc, char *buf)
 /* Parse the BUF for the expected notification NC.  */
 
 struct notif_event *
-remote_notif_parse (struct notif_client *nc, char *buf)
+remote_notif_parse (struct notif_client *nc,
+		    struct remote_notif_state *state, char *buf)
 {
   struct notif_event *event = nc->alloc_event ();
   struct cleanup *old_chain
@@ -124,7 +134,7 @@ remote_notif_parse (struct notif_client *nc, char *buf)
     fprintf_unfiltered (gdb_stdlog, "notif: parse '%s'\n",
 			nc->base.notif_name);
 
-  remote_notif_parse_1 (nc, event, buf);
+  remote_notif_parse_1 (nc, state, event, buf);
 
   discard_cleanups (old_chain);
   return event;
@@ -220,7 +230,7 @@ handle_notification (struct remote_notif_state *state, char *buf)
   else
     {
       struct notif_event *event
-	= remote_notif_parse (nc,
+	= remote_notif_parse (nc, state,
 			      buf + strlen (nc->base.notif_name) + 1);
 
       /* Be careful to only set it after parsing, since an error
@@ -302,6 +312,60 @@ 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,
+			       struct remote_notif_state *state)
+{
+  notif_parse_supported (reply, (struct notif_base **) notifs,
+			 ARRAY_SIZE (notifs), state);
+
+  if (notif_debug)
+    {
+      int i;
+
+      fprintf_unfiltered (gdb_stdlog,
+			  "notif: stub supported notifications '%s'\n",
+			  reply);
+      fprintf_unfiltered (gdb_stdlog, "notif annexes:\n");
+      for (i = 0; i < ARRAY_SIZE (notifs); i++)
+	{
+	  struct notif_base *nb  = (struct notif_base *) notifs[i];
+
+	  fprintf_unfiltered (gdb_stdlog, "%-10s ", nb->notif_name);
+	  if (NOTIF_HAS_ANNEX (nb))
+	    {
+	      int j;
+	      struct notif_annex *annex;
+
+	      NOTIF_ITER_ANNEX (nb, j, annex)
+		fprintf_unfiltered (gdb_stdlog, "\n %-10s %d", annex->name,
+				    NOTIF_ANNEX_SUPPORTED (state, nb, j));
+	    }
+	  else
+	    fprintf_unfiltered (gdb_stdlog, " %d",
+				NOTIF_ANNEX_SUPPORTED (state, nb, 0));
+
+	  fprintf_unfiltered (gdb_stdlog, "\n");
+	}
+    }
+}
+
+/* Total number of annexes.  */
+
+static int notif_annex_number = 0;
+
 /* Return an allocated remote_notif_state.  */
 
 struct remote_notif_state *
@@ -310,6 +374,14 @@ remote_notif_state (void)
   struct remote_notif_state *notif_state = xmalloc (sizeof (*notif_state));
 
   notif_state->notif_queue = QUEUE_alloc (notif_client_p, notif_xfree);
+  notif_state->supported = xmalloc (notif_annex_number * sizeof (int));
+  memset (notif_state->supported, 0, notif_annex_number * sizeof (int));
+
+  /* Even the remote stub doesn't understand
+     'qSupported:notifications=', it may still support notification
+     stop if it supports non-stop.  */
+  NOTIF_ANNEX_SUPPORTED (notif_state, &notif_client_stop.base, 0) = 1;
+
   return notif_state;
 }
 
@@ -319,6 +391,26 @@ extern initialize_file_ftype _initialize_notif;
 void
 _initialize_notif (void)
 {
+  int i;
+
+  /* Initialize the field of 'struct notif_annex' which is the index
+     of array which is about whether the annex is supported or not.  */
+  for (i = 0; i < ARRAY_SIZE (notifs); i++)
+    {
+      struct notif_base *nb  = (struct notif_base *) notifs[i];
+
+      if (NOTIF_HAS_ANNEX (nb))
+	{
+	  int j;
+	  struct notif_annex *annex;
+
+	  NOTIF_ITER_ANNEX (nb, j, annex)
+	    annex->id = notif_annex_number++;
+	}
+      else
+	nb->annexes[0].id = notif_annex_number++;
+    }
+
   add_setshow_boolean_cmd ("notification", no_class, &notif_debug,
 			   _("\
 Set debugging of async remote notification."), _("\
diff --git a/gdb/remote-notif.h b/gdb/remote-notif.h
index 454dce8..9a68779 100644
--- a/gdb/remote-notif.h
+++ b/gdb/remote-notif.h
@@ -67,10 +67,17 @@ struct remote_notif_state
 {
   /* Notification queue.  */
   QUEUE(notif_client_p) *notif_queue;
+
+  /* Each element indicates the annex is supported by the remote
+     stub or not.  The index is the field 'id' in
+     'struct notif_annex'.  */
+  int *supported;
 };
 
-void remote_notif_ack (struct notif_client *nc, char *buf);
+void remote_notif_ack (struct notif_client *nc,
+		       struct remote_notif_state *state, char *buf);
 struct notif_event *remote_notif_parse (struct notif_client *nc,
+					struct remote_notif_state *state,
 					char *buf);
 
 void handle_notification (struct remote_notif_state *notif_state,
@@ -83,6 +90,11 @@ void remote_notif_process (struct remote_notif_state *state,
 			   struct notif_client *except);
 struct remote_notif_state *remote_notif_state (void);
 
+
+char * remote_notif_qsupported (void);
+void remote_notif_qsupported_reply (const char *reply,
+				    struct remote_notif_state *state);
+
 extern struct notif_client notif_client_stop;
 
 extern int notif_debug;
diff --git a/gdb/remote.c b/gdb/remote.c
index 9700a8e..2877c7c6 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -1369,6 +1369,7 @@ enum {
   PACKET_Qbtrace_off,
   PACKET_Qbtrace_bts,
   PACKET_qXfer_btrace,
+  PACKET_notifications,
   PACKET_MAX
 };
 
@@ -3573,7 +3574,7 @@ remote_start_remote (int from_tty, struct target_ops *target, int extended_p)
 	  /* remote_notif_get_pending_replies acks this one, and gets
 	     the rest out.  */
 	  notif_client_stop.pending_event
-	    = remote_notif_parse (notif, rs->buf);
+	    = remote_notif_parse (notif, rs->notif_state, rs->buf);
 	  remote_notif_get_pending_events (notif);
 
 	  /* Make sure that threads that were stopped remain
@@ -3993,6 +3994,17 @@ remote_augmented_libraries_svr4_read_feature
   rs->augmented_libraries_svr4_read = (support == PACKET_ENABLE);
 }
 
+static void
+remote_notifications_feature (const struct protocol_feature *feature,
+			      enum packet_support support,
+			      const char *value)
+{
+  struct remote_state *rs = get_remote_state ();
+
+  if (support == PACKET_ENABLE)
+    remote_notif_qsupported_reply (value, rs->notif_state);
+}
+
 static const struct protocol_feature remote_protocol_features[] = {
   { "PacketSize", PACKET_DISABLE, remote_packet_size, -1 },
   { "qXfer:auxv:read", PACKET_DISABLE, remote_supported_packet,
@@ -4067,7 +4079,9 @@ static const struct protocol_feature remote_protocol_features[] = {
   { "Qbtrace:off", PACKET_DISABLE, remote_supported_packet, PACKET_Qbtrace_off },
   { "Qbtrace:bts", PACKET_DISABLE, remote_supported_packet, PACKET_Qbtrace_bts },
   { "qXfer:btrace:read", PACKET_DISABLE, remote_supported_packet,
-    PACKET_qXfer_btrace }
+    PACKET_qXfer_btrace },
+  { "Notifications", PACKET_DISABLE, remote_notifications_feature,
+    -1 },
 };
 
 static char *remote_support_xml;
@@ -4132,6 +4146,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+");
@@ -4141,6 +4156,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);
 
@@ -4597,7 +4616,8 @@ extended_remote_attach_1 (struct target_ops *target, char *args, int from_tty)
       if (target_can_async_p ())
 	{
 	  struct notif_event *reply
-	    =  remote_notif_parse (&notif_client_stop, wait_status);
+	    =  remote_notif_parse (&notif_client_stop, rs->notif_state,
+				   wait_status);
 
 	  push_stop_reply ((struct stop_reply *) reply);
 
@@ -5371,7 +5391,7 @@ remote_notif_stop_alloc_reply (void)
 
 static struct notif_annex notif_client_annex_stop[] =
 {
-  { NULL, remote_notif_stop_parse, },
+  { NULL, -1, remote_notif_stop_parse, },
 };
 
 /* A client of notification Stop.  */
@@ -5817,7 +5837,7 @@ remote_notif_get_pending_events (struct notif_client *nc)
 	  if (strcmp (rs->buf, "OK") == 0)
 	    break;
 	  else
-	    remote_notif_ack (nc, rs->buf);
+	    remote_notif_ack (nc, rs->notif_state, rs->buf);
 	}
     }
   else
@@ -6021,6 +6041,7 @@ remote_wait_as (ptid_t ptid, struct target_waitstatus *status, int options)
       {
 	struct stop_reply *stop_reply
 	  = (struct stop_reply *) remote_notif_parse (&notif_client_stop,
+						      rs->notif_state,
 						      rs->buf);
 
 	event_ptid = process_stop_reply (stop_reply, status);
-- 
1.7.7.6


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]