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 1/4] Query supported notifications by qSupported


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

As we we adding more notifications, both GDB and GDBserver
has to know what notifications are supported in the other
side.  This is what this patch does.  When GDB connects to GDBserver,
it will happen:

  --> qSupported:XXX;notifications=N1,N2.N3
      (GDB supports notification N1, N2 and N3)
  <-- XXX;Notifications=N1,N2,N4
      (GDBsever supports notification N1, N2 and N4)

after this, GDB knows what notifications GDBserver is able to send,
and GDBservers knows what notifications GDB doesn't support.

gdb/gdbserver:

	* notif.c (notif_qsupported_record): New function.
	(notif_qsupported_reply): New function.
	* notif.h (struct notif_server) <supported>: New field.
	(notif_qsupported_reply): Declare.
	(notif_qsupported_record): Declare.
	* server.c (notif_annex_stop): Update.
	(handle_query): Call notif_qsupported_record and
	notif_qsupported_reply.

gdb:

	* remote-notif.c (remote_notif_ack): Add argument 'state'.
	Callers update.
	(remote_notif_parse): Likewise.
	(remote_notif_qsupported): New function.
	(remote_notif_qsupported_reply): New function.
	(remote_notif_state_allocate): Initialize field 'supported'.
	(remote_notif_state_xfree): Free field 'supported'.
	* remote-notif.h (struct remote_notif_state) <supported>: New
	field.
	(remote_notif_ack, remote_notif_parse): Update declarations.
	(remote_notif_qsupported): Declare.
	(remote_notif_qsupported_reply): Declare.
	* remote.c (PACKET_notifications): New enum.
	(remote_notifications_feature): New function.
	(remote_protocol_features): Add new element.
	(remote_query_supported): Call remote_notif_qsupported and
	append supported notifications to qSupported feature.

gdb/doc:

	* gdb.texinfo (General Query Packets): Document the new feature
	'notifications' of 'qSupported' packet.
	Document the new feature in qSupported reply.
---
 gdb/doc/gdb.texinfo    |   18 ++++++++
 gdb/gdbserver/notif.c  |   83 ++++++++++++++++++++++++++++++++++++
 gdb/gdbserver/notif.h  |    5 ++
 gdb/gdbserver/server.c |   16 +++++++-
 gdb/remote-notif.c     |  109 ++++++++++++++++++++++++++++++++++++++++++++++-
 gdb/remote-notif.h     |   14 ++++++-
 gdb/remote.c           |   29 +++++++++++--
 7 files changed, 265 insertions(+), 9 deletions(-)

diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 7dfa9f6..e76f73b 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -39383,6 +39383,14 @@ description.
 This feature indicates whether @value{GDBN} supports the
 @samp{qRelocInsn} packet (@pxref{Tracepoint Packets,,Relocate
 instruction reply packet}).
+
+@item notifications
+@anchor{notifications feature}
+This feature indicates that @value{GDBN} supports the async remote
+notifications (@pxref{Notification Packets}).  If the stub sees
+@samp{notifications=} with a string of name of supported
+notifications, separated by commas, it will report notifications
+supported by the stub.
 @end table
 
 Stubs should ignore any unknown values for
@@ -39601,6 +39609,11 @@ These are the currently defined stub features and their properties:
 @tab @samp{-}
 @tab No
 
+@item @samp{Notifications}
+@tab Yes
+@tab @samp{-}
+@tab No
+
 @end multitable
 
 These are the currently defined stub features, in more detail:
@@ -39768,6 +39781,11 @@ See @ref{Bytecode Descriptions} for details about the bytecode.
 The remote stub supports running a breakpoint's command list itself,
 rather than reporting the hit to @value{GDBN}.
 
+@item Notifications=@var{name}@r{[},@var{name}@r{]}@dots{}
+@cindex notifications, in remote protocol
+The remote stub supports a string of notifications.  @var{name} is
+the name of the notification.
+
 @item Qbtrace:off
 The remote stub understands the @samp{Qbtrace:off} packet.
 
diff --git a/gdb/gdbserver/notif.c b/gdb/gdbserver/notif.c
index 6da2c5c..4766bba 100644
--- a/gdb/gdbserver/notif.c
+++ b/gdb/gdbserver/notif.c
@@ -159,6 +159,89 @@ notif_event_xfree (struct notif_event *event)
   xfree (event);
 }
 
+/* Record the notifications supported by GDB.  GDB_NOTIFICATIONS is a
+   string about notifications GDB supports.  */
+
+void
+notif_qsupported_record (char *gdb_notifications)
+{
+  const char *p = gdb_notifications;
+
+  while (1)
+    {
+      char *end = strchr (p, ',');
+      struct notif_server *nc = NULL;
+
+      if (end == NULL)
+	{
+	  int i;
+
+	  for (i = 0; i < ARRAY_SIZE (notifs); i++)
+	    {
+	      if (strcmp (p, notifs[i]->notif_name) == 0)
+		{
+		  nc = notifs[i];
+		  break;
+		}
+	    }
+	}
+      else
+	{
+	  int i;
+
+	  for (i = 0; i < ARRAY_SIZE (notifs); i++)
+	    {
+	      if (strncmp (p, notifs[i]->notif_name, end - p) == 0
+		  && strlen (notifs[i]->notif_name) == (end - p))
+		{
+		  nc = notifs[i];
+		  break;
+		}
+	    }
+
+	  p = end + 1;
+	}
+
+      /* Notification NC is supported.  */
+      if (nc != NULL)
+	nc->supported = 1;
+
+      if (end == NULL)
+	break;
+    }
+}
+
+/* Return a string about notifications that GDBserver supports.
+   Return NULL if no notification is supported.  The caller is
+   responsible to free the returned string.  Suppose GDBserver
+   supports notifications N1, N2, and N3.  The returned string is
+   "N1,N2,N3".  */
+
+char *
+notif_qsupported_reply (void)
+{
+  int i;
+  char * p = NULL;
+
+#define BUF_LEN 128
+
+  for (i = 0; i < ARRAY_SIZE (notifs); i++)
+    {
+      struct notif_server *nb = notifs[i];
+
+      if (p == NULL)
+	{
+	  p = xmalloc (BUF_LEN);
+	  strcpy (p, nb->notif_name);
+	}
+      else
+	xsnprintf (p + strlen (p), BUF_LEN - strlen (p), ",%s",
+		   nb->notif_name);
+    }
+
+  return p;
+}
+
 void
 initialize_notif (void)
 {
diff --git a/gdb/gdbserver/notif.h b/gdb/gdbserver/notif.h
index c714e7b..80e084e 100644
--- a/gdb/gdbserver/notif.h
+++ b/gdb/gdbserver/notif.h
@@ -52,12 +52,17 @@ typedef struct notif_server
 
   /* Write event EVENT to OWN_BUF.  */
   void (*write) (struct notif_event *event, char *own_buf);
+
+  /* This notification is supported by GDB or not.  */
+  int supported;
 } *notif_server_p;
 
 extern struct notif_server notif_stop;
 
 int handle_notif_ack (char *own_buf, int packet_len);
 void notif_write_event (struct notif_server *notif, char *own_buf);
+char* notif_qsupported_reply (void);
+void notif_qsupported_record (char *gdb_notifications);
 
 void notif_push (struct notif_server *np, struct notif_event *event);
 void notif_event_enque (struct notif_server *notif,
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index e0af785..d79c8db 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -187,7 +187,7 @@ vstop_notif_reply (struct notif_event *event, char *own_buf)
 
 struct notif_server notif_stop =
 {
-  "vStopped", "Stop", NULL, vstop_notif_reply,
+  "vStopped", "Stop", NULL, vstop_notif_reply, 1,
 };
 
 static int
@@ -1731,6 +1731,11 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
 		  /* GDB supports relocate instruction requests.  */
 		  gdb_supports_qRelocInsn = 1;
 		}
+	      else if (strncmp (p, "notifications=", 14) == 0)
+		{
+		  /* Record what notifications GDB supports.  */
+		  notif_qsupported_record (&p[14]);
+		}
 	      else
 		target_process_qsupported (p);
 
@@ -1820,6 +1825,15 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
 	  strcat (own_buf, ";qXfer:btrace:read+");
 	}
 
+      p = notif_qsupported_reply ();
+
+      if (p != NULL)
+	{
+	  strcat (own_buf, ";Notifications=");
+	  strcat (own_buf, p);
+	  xfree (p);
+	}
+
       return;
     }
 
diff --git a/gdb/remote-notif.c b/gdb/remote-notif.c
index 163979d..4685d30 100644
--- a/gdb/remote-notif.c
+++ b/gdb/remote-notif.c
@@ -59,7 +59,8 @@ static void do_notif_event_xfree (void *arg);
    acknowledge.  */
 
 void
-remote_notif_ack (struct notif_client *nc, char *buf)
+remote_notif_ack (struct notif_client *nc,
+		  struct remote_notif_state *state, char *buf)
 {
   struct notif_event *event = nc->alloc_event ();
   struct cleanup *old_chain
@@ -78,7 +79,8 @@ remote_notif_ack (struct notif_client *nc, char *buf)
 /* Parse the BUF for the expected notification NC.  */
 
 struct notif_event *
-remote_notif_parse (struct notif_client *nc, char *buf)
+remote_notif_parse (struct notif_client *nc,
+		    struct remote_notif_state *state, char *buf)
 {
   struct notif_event *event = nc->alloc_event ();
   struct cleanup *old_chain
@@ -158,7 +160,7 @@ handle_notification (struct remote_notif_state *state, char *buf)
   else
     {
       struct notif_event *event
-	= remote_notif_parse (nc, buf + strlen (nc->name) + 1);
+	= remote_notif_parse (nc, state, buf + strlen (nc->name) + 1);
 
       /* Be careful to only set it after parsing, since an error
 	 may be thrown then.  */
@@ -234,6 +236,99 @@ do_notif_event_xfree (void *arg)
   notif_event_xfree (arg);
 }
 
+/* Return a string about notifications that GDB supports.  The caller
+   is responsible to free the returned string.  Suppose GDB supports
+   notifications N1, N2, and N3.  The returned string is
+   "N1,N2,N3".  */
+
+char *
+remote_notif_qsupported (void)
+{
+  int i;
+  char * p = NULL;
+
+#define BUF_LEN 128
+
+  for (i = 0; i < ARRAY_SIZE (notifs); i++)
+    {
+      struct notif_client *nb = notifs[i];
+
+      if (p == NULL)
+	{
+	  p = xmalloc (BUF_LEN);
+	  strcpy (p, nb->name);
+	}
+      else
+	xsnprintf (p + strlen (p), BUF_LEN - strlen (p), ",%s",
+		   nb->name);
+    }
+
+  return p;
+}
+
+/* Parse the qSupported reply REPLY from the remote stub and enable
+   notifications if the remote stub supports.  */
+
+void
+remote_notif_qsupported_reply (const char *reply,
+			       struct remote_notif_state *state)
+{
+  const char *p = reply;
+
+  if (notif_debug)
+    fprintf_unfiltered (gdb_stdlog,
+			"notif: stub supported notifications '%s'\n",
+			reply);
+
+  while (1)
+    {
+      char *end = strchr (p, ',');
+      struct notif_client *nc = NULL;
+
+      if (end == NULL)
+	{
+	  int i;
+
+	  for (i = 0; i < ARRAY_SIZE (notifs); i++)
+	    {
+	      if (strcmp (p, notifs[i]->name) == 0)
+		{
+		  nc = notifs[i];
+		  break;
+		}
+	    }
+	}
+      else
+	{
+	  int i;
+
+	  for (i = 0; i < ARRAY_SIZE (notifs); i++)
+	    {
+	      if (strncmp (p, notifs[i]->name, end - p) == 0
+		  && strlen (notifs[i]->name) == (end - p))
+		{
+		  nc = notifs[i];
+		  break;
+		}
+	    }
+
+	  p = end + 1;
+	}
+
+      if (nc != NULL)
+	{
+	  /* Notification NC is supported.  */
+	  state->supported[nc->id] = 1;
+	  if (notif_debug)
+	    fprintf_unfiltered (gdb_stdlog, "notif: '%s' is supported\n",
+				nc->name);
+	}
+
+      if (end == NULL)
+	break;
+    }
+}
+
 /* Return an allocated remote_notif_state.  */
 
 struct remote_notif_state *
@@ -249,6 +344,12 @@ remote_notif_state_allocate (void)
     = create_async_event_handler (remote_async_get_pending_events_handler,
 				  notif_state);
 
+  notif_state->supported = xcalloc (ARRAY_SIZE (notifs), sizeof (int));
+
+  /* Even the remote stub doesn't understand
+    'qSupported:notifications=', it may still support notification
+     stop if it supports non-stop.  */
+  notif_state->supported[notif_client_stop.id] = 1;
   return notif_state;
 }
 
@@ -268,6 +369,8 @@ remote_notif_state_xfree (struct remote_notif_state *state)
   for (i = 0; i < REMOTE_NOTIF_LAST; i++)
     notif_event_xfree (state->pending_event[i]);
 
+  xfree (state->supported);
+
   xfree (state);
 }
 
diff --git a/gdb/remote-notif.h b/gdb/remote-notif.h
index e5ebbc7..14984b4 100644
--- a/gdb/remote-notif.h
+++ b/gdb/remote-notif.h
@@ -96,10 +96,17 @@ struct remote_notif_state
    remote.c:remote_notif_pending_replies).  */
 
   struct notif_event *pending_event[REMOTE_NOTIF_LAST];
+
+  /* Each element indicates the notification is supported by the
+     remote  stub or not.  The index is the field 'id' in
+     'struct notif_client'.  */
+  int *supported;
 };
 
-void remote_notif_ack (struct notif_client *nc, char *buf);
+void remote_notif_ack (struct notif_client *nc,
+		       struct remote_notif_state *state, char *buf);
 struct notif_event *remote_notif_parse (struct notif_client *nc,
+					struct remote_notif_state *state,
 					char *buf);
 
 void notif_event_xfree (struct notif_event *event);
@@ -112,6 +119,11 @@ void remote_notif_process (struct remote_notif_state *state,
 struct remote_notif_state *remote_notif_state_allocate (void);
 void remote_notif_state_xfree (struct remote_notif_state *state);
 
+
+char * remote_notif_qsupported (void);
+void remote_notif_qsupported_reply (const char *reply,
+				    struct remote_notif_state *state);
+
 extern struct notif_client notif_client_stop;
 
 extern int notif_debug;
diff --git a/gdb/remote.c b/gdb/remote.c
index 2ac8c36..82dce9c 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -1367,6 +1367,7 @@ enum {
   PACKET_Qbtrace_off,
   PACKET_Qbtrace_bts,
   PACKET_qXfer_btrace,
+  PACKET_notifications,
   PACKET_MAX
 };
 
@@ -3569,7 +3570,7 @@ remote_start_remote (int from_tty, struct target_ops *target, int extended_p)
 	  /* remote_notif_get_pending_replies acks this one, and gets
 	     the rest out.  */
 	  rs->notif_state->pending_event[notif_client_stop.id]
-	    = remote_notif_parse (notif, rs->buf);
+	    = remote_notif_parse (notif, rs->notif_state, rs->buf);
 	  remote_notif_get_pending_events (notif);
 
 	  /* Make sure that threads that were stopped remain
@@ -3989,6 +3990,17 @@ remote_augmented_libraries_svr4_read_feature
   rs->augmented_libraries_svr4_read = (support == PACKET_ENABLE);
 }
 
+static void
+remote_notifications_feature (const struct protocol_feature *feature,
+			      enum packet_support support,
+			      const char *value)
+{
+  struct remote_state *rs = get_remote_state ();
+
+  if (support == PACKET_ENABLE)
+    remote_notif_qsupported_reply (value, rs->notif_state);
+}
+
 static const struct protocol_feature remote_protocol_features[] = {
   { "PacketSize", PACKET_DISABLE, remote_packet_size, -1 },
   { "qXfer:auxv:read", PACKET_DISABLE, remote_supported_packet,
@@ -4063,7 +4075,9 @@ static const struct protocol_feature remote_protocol_features[] = {
   { "Qbtrace:off", PACKET_DISABLE, remote_supported_packet, PACKET_Qbtrace_off },
   { "Qbtrace:bts", PACKET_DISABLE, remote_supported_packet, PACKET_Qbtrace_bts },
   { "qXfer:btrace:read", PACKET_DISABLE, remote_supported_packet,
-    PACKET_qXfer_btrace }
+    PACKET_qXfer_btrace },
+  { "Notifications", PACKET_DISABLE, remote_notifications_feature,
+    -1 },
 };
 
 static char *remote_support_xml;
@@ -4128,6 +4142,7 @@ remote_query_supported (void)
   if (remote_protocol_packets[PACKET_qSupported].support != PACKET_DISABLE)
     {
       char *q = NULL;
+      char *notifications = remote_notif_qsupported ();
       struct cleanup *old_chain = make_cleanup (free_current_contents, &q);
 
       q = remote_query_supported_append (q, "multiprocess+");
@@ -4137,6 +4152,10 @@ remote_query_supported (void)
 
       q = remote_query_supported_append (q, "qRelocInsn+");
 
+      q = reconcat (q, q, ";notifications=", notifications,
+		    (char *) NULL);
+      xfree (notifications);
+
       q = reconcat (q, "qSupported:", q, (char *) NULL);
       putpkt (q);
 
@@ -4592,7 +4611,8 @@ extended_remote_attach_1 (struct target_ops *target, char *args, int from_tty)
       if (target_can_async_p ())
 	{
 	  struct notif_event *reply
-	    =  remote_notif_parse (&notif_client_stop, wait_status);
+	    =  remote_notif_parse (&notif_client_stop, rs->notif_state,
+				   wait_status);
 
 	  push_stop_reply ((struct stop_reply *) reply);
 
@@ -5854,7 +5874,7 @@ remote_notif_get_pending_events (struct notif_client *nc)
 	  if (strcmp (rs->buf, "OK") == 0)
 	    break;
 	  else
-	    remote_notif_ack (nc, rs->buf);
+	    remote_notif_ack (nc, rs->notif_state, rs->buf);
 	}
     }
   else
@@ -6058,6 +6078,7 @@ remote_wait_as (ptid_t ptid, struct target_waitstatus *status, int options)
       {
 	struct stop_reply *stop_reply
 	  = (struct stop_reply *) remote_notif_parse (&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]