[PATCH] Add autoload-breakpoints [1/7] ReportAsync

Hui Zhu hui_zhu@mentor.com
Sat Mar 17 08:52:00 GMT 2012


Hi,

To make the remote stub control the autoload-breakpoints in GDB part.  I 
add ReportAsync function.
I think there must somebody ask me how different ReportAsync Packets and 
Notification Packets. There are some introduce:

1. The Notification should happen when GDB RSP package just send to the 
stub.
But ReportAsync should not.  ReportAsync need do a shake hands with GDB 
first.  So when this is not the right time to handle the control packat 
from the stub (for example: when gdb just send a packet to remote, do a 
another control maybe affect gdb).  GDB can ignore this shake hands 
directly.  Then the stub can give up this operation and wait for the 
another time try again.
With this support, we can let the stub use ReportAsync do some spcial 
operation to GDB.

2. Because after shake hands, another package will translate with ack, 
it will be more safe in some remote infterface then Notification.

Thanks,
Hui

2012-03-17  Hui Zhu  <hui_zhu@mentor.com>

	* remote.c (inside_reportasync_handler): New variable.
	(remote_reportasync_handler): New function.
	(async_client_callback): Move to the top.
	(async_client_context): Ditto.
	(remote_async_serial_handler): Ditto.
	(PACKET_ReportAsync): new enum.
	(remote_pr): Add PACKET_ReportAsync.
	(remote_open_1): Call serial_async.
	(readchar_buffer_ch): New variable.
	(readchar): If need, return the value of readchar_buffer_ch.
	(readchar_buffer_put): New function.
	(putpkt_binary): Add check for inside_reportasync_handler.
	Add handle for '^'.
	(getpkt_or_notif_sane_1): Add handle for '^'.
	(remote_is_async_p): Add check for PACKET_ReportAsync.
	(remote_reportasync_check): New function.
	(remote_async_serial_handler): Call remote_reportasync_check.
	(remote_async): Add check for PACKET_ReportAsync.
	(_initialize_remote): Add PACKET_ReportAsync.

-------------- next part --------------
---
 remote.c |  144 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 131 insertions(+), 13 deletions(-)

--- a/remote.c
+++ b/remote.c
@@ -219,6 +219,18 @@ static void remote_query_supported (void
 
 static void remote_check_symbols (struct objfile *objfile);
 
+/* This is a flag.
+   It will be true when GDB inside ReportAsync handle mode. */
+
+static int inside_reportasync_handler = 0;
+
+static void remote_reportasync_handler (struct remote_state *rs);
+
+static void (*async_client_callback) (enum inferior_event_type event_type,
+				      void *context) = NULL;
+static void *async_client_context;
+static serial_event_ftype remote_async_serial_handler;
+
 void _initialize_remote (void);
 
 struct stop_reply;
@@ -1284,6 +1296,7 @@ enum {
   PACKET_qXfer_fdpic,
   PACKET_QDisableRandomization,
   PACKET_QAgent,
+  PACKET_ReportAsync,
   PACKET_MAX
 };
 
@@ -3923,6 +3936,8 @@ static struct protocol_feature remote_pr
   { "QAgent", PACKET_DISABLE, remote_supported_packet, PACKET_QAgent},
   { "tracenz", PACKET_DISABLE,
     remote_string_tracing_feature, -1 },
+  { "ReportAsync", PACKET_DISABLE, remote_supported_packet,
+    PACKET_ReportAsync },
 };
 
 static char *remote_support_xml;
@@ -4280,6 +4295,9 @@ remote_open_1 (char *name, int from_tty,
 
   if (target_async_permitted)
     wait_forever_enabled_p = 1;
+
+  if (remote_protocol_packets[PACKET_ReportAsync].support != PACKET_DISABLE)
+    serial_async (remote_desc, remote_async_serial_handler, NULL);
 }
 
 /* This takes a program previously attached to and detaches it.  After
@@ -6879,11 +6897,20 @@ remote_files_info (struct target_ops *ig
 
 /* Read a single character from the remote end.  */
 
+static int readchar_buffer_ch = -1;
+
 static int
 readchar (int timeout)
 {
   int ch;
 
+  if (readchar_buffer_ch != -1)
+    {
+      ch = readchar_buffer_ch;
+      readchar_buffer_ch = -1;
+      return ch;
+    }
+
   ch = serial_readchar (remote_desc, timeout);
 
   if (ch >= 0)
@@ -6906,6 +6933,17 @@ readchar (int timeout)
   return ch;
 }
 
+/* When the function that call the readchar got a char is not for it
+   and other function need this char??????call this function to put
+   this char back.  Then when other function call readchar, it will
+   got this char first. */
+
+static void
+readchar_buffer_put (int ch)
+{
+  readchar_buffer_ch = ch;
+}
+
 /* Send the command in *BUF to the remote machine, and read the reply
    into *BUF.  Report an error if we get an error reply.  Resize
    *BUF using xrealloc if necessary to hold the result, and update
@@ -6985,7 +7023,8 @@ putpkt_binary (char *buf, int cnt)
      case it's not possible to issue a command while the target is
      running.  This is not a problem in non-stop mode, because in that
      case, the stub is always ready to process serial input.  */
-  if (!non_stop && target_can_async_p () && rs->waiting_for_stop_reply)
+  if (!non_stop && target_can_async_p () && rs->waiting_for_stop_reply
+      && !inside_reportasync_handler)
     error (_("Cannot execute this command while the target is running."));
 
   /* We're sending out a new packet.  Make sure we don't look at a
@@ -7085,6 +7124,17 @@ putpkt_binary (char *buf, int cnt)
 		continue;	/* Now, go look for +.  */
 	      }
 
+	    case '^':
+	      /* This ReportAsync shake hands happen when GDB just send
+		 a package to GDBserver.
+		 GDBsrver will got the package from GDB first, it will
+		 give up this shake hands.
+		 So we can ignore this shake hands package.  */
+	      if (remote_debug)
+		  fprintf_unfiltered (gdb_stdlog, "\n\
+Ignore a ReportAsync shake hands package because waiting a ack.\n");
+	      continue;
+
 	    case '%':
 	      {
 		int val;
@@ -7406,7 +7456,7 @@ getpkt_or_notif_sane_1 (char **buf, long
 	     show up within remote_timeout intervals.  */
 	  do
 	    c = readchar (timeout);
-	  while (c != SERIAL_TIMEOUT && c != '$' && c != '%');
+	  while (c != SERIAL_TIMEOUT && c != '$' && c != '%' && c != '^');
 
 	  if (c == SERIAL_TIMEOUT)
 	    {
@@ -7423,6 +7473,22 @@ getpkt_or_notif_sane_1 (char **buf, long
 	      if (remote_debug)
 		fputs_filtered ("Timed out.\n", gdb_stdlog);
 	    }
+	  else if (c == '^')
+	    {
+	      if (forever)
+		remote_reportasync_handler (rs);
+	      else
+		{
+		  /* Because GDB is waitting a response.
+		     Ignore this shake hands package and
+		     send a "+" to let GDBserver stop wait. */
+		  serial_write (remote_desc, "+", 1);
+		  if (remote_debug)
+		    fprintf_unfiltered (gdb_stdlog, "\n\
+Ignore a ReportAsync shake hands package because waiting a response.\n");
+		}
+	      continue;
+	    }
 	  else
 	    {
 	      /* We've found the start of a packet or notification.
@@ -11057,25 +11123,69 @@ remote_is_async_p (void)
     /* We only enable async when the user specifically asks for it.  */
     return 0;
 
+  if (remote_protocol_packets[PACKET_ReportAsync].support != PACKET_DISABLE)
+    return async_client_callback != NULL;
+
   /* We're async whenever the serial device is.  */
   return serial_is_async_p (remote_desc);
 }
 
+static int
+remote_reportasync_check (void)
+{
+  int c = readchar (-1);
+
+  if (c == '^')
+    return 1;
+
+  readchar_buffer_put (c);
+  return 0;
+}
+
+/* This is the handler of ReportAsync.
+   When GDB got a shake hands package '^' and it is not putting a package to GDBserver,
+   waiting a ack or waiting a response from GDBserver (except it is waiting forever),
+   GDB will call this function.  */
+
+static void
+remote_reportasync_handler (struct remote_state *rs)
+{
+  int len;
+  struct cleanup *old_chain
+    = make_cleanup_restore_integer (&inside_reportasync_handler);
+
+  /* Shake hands with remote part.  */
+  serial_write (remote_desc, "^", 1);
+
+  inside_reportasync_handler = 1;
+
+  if (getpkt_sane (&rs->buf, &rs->buf_size, 0) < 0)
+    return;
+
+  if (remote_debug)
+    fprintf_unfiltered (gdb_stdlog, "ReportAsync: %s\n", rs->buf);
+
+  putpkt ("");
+
+  do_cleanups (old_chain);
+}
+
 /* Pass the SERIAL event on and up to the client.  One day this code
    will be able to delay notifying the client of an event until the
    point where an entire packet has been received.  */
-
-static void (*async_client_callback) (enum inferior_event_type event_type,
-				      void *context);
-static void *async_client_context;
-static serial_event_ftype remote_async_serial_handler;
-
 static void
 remote_async_serial_handler (struct serial *scb, void *context)
 {
-  /* Don't propogate error information up to the client.  Instead let
-     the client find out about the error by querying the target.  */
-  async_client_callback (INF_REG_EVENT, async_client_context);
+  /* Check if this is ReportAsync.  */
+  if (remote_reportasync_check ())
+    remote_reportasync_handler (get_remote_state ());
+  else
+    {
+      /* Don't propogate error information up to the client.  Instead let
+         the client find out about the error by querying the target.  */
+      if (async_client_callback)
+	async_client_callback (INF_REG_EVENT, async_client_context);
+    }
 }
 
 static void
@@ -11096,12 +11206,17 @@ remote_async (void (*callback) (enum inf
 {
   if (callback != NULL)
     {
-      serial_async (remote_desc, remote_async_serial_handler, NULL);
+      if (remote_protocol_packets[PACKET_ReportAsync].support == PACKET_DISABLE)
+        serial_async (remote_desc, remote_async_serial_handler, NULL);
       async_client_callback = callback;
       async_client_context = context;
     }
   else
-    serial_async (remote_desc, NULL, NULL);
+    {
+      if (remote_protocol_packets[PACKET_ReportAsync].support == PACKET_DISABLE)
+	serial_async (remote_desc, NULL, NULL);
+      async_client_callback = NULL;
+    }
 }
 
 static void
@@ -11535,6 +11650,9 @@ Show the maximum size of the address (in
   add_packet_config_cmd (&remote_protocol_packets[PACKET_QAgent],
 			 "QAgent", "agent", 0);
 
+  add_packet_config_cmd (&remote_protocol_packets[PACKET_ReportAsync],
+			 "ReportAsync", "report-async", 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



More information about the Gdb-patches mailing list