]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdb/remote.c
import gdb-1999-10-25 snapshot
[thirdparty/binutils-gdb.git] / gdb / remote.c
index 5f1a3efc0521f9f11551e8cb0581efd962b51682..cd4eda0a08325244f4fc4dee050eddbcc1b2d8fc 100644 (file)
@@ -60,12 +60,11 @@ static void initialize_sigint_signal_handler (void);
 static void handle_remote_sigint PARAMS ((int));
 static void handle_remote_sigint_twice PARAMS ((int));
 static void async_remote_interrupt PARAMS ((gdb_client_data));
-static void async_remote_interrupt_twice PARAMS ((gdb_client_data));
+void async_remote_interrupt_twice PARAMS ((gdb_client_data));
 
 static void build_remote_gdbarch_data PARAMS ((void));
 
-static int remote_write_bytes PARAMS ((CORE_ADDR memaddr,
-                                      char *myaddr, int len));
+static int remote_write_bytes (CORE_ADDR memaddr, char *myaddr, int len);
 
 static int remote_read_bytes PARAMS ((CORE_ADDR memaddr,
                                      char *myaddr, int len));
@@ -166,6 +165,8 @@ static int remote_query PARAMS ((int /*char */ , char *, char *, int *));
 
 static int hexnumstr PARAMS ((char *, ULONGEST));
 
+static int hexnumnstr PARAMS ((char *, ULONGEST, int));
+
 static CORE_ADDR remote_address_masked PARAMS ((CORE_ADDR));
 
 static void print_packet PARAMS ((char *));
@@ -2106,7 +2107,7 @@ handle_remote_sigint_twice (sig)
 {
   signal (sig, handle_sigint);
   sigint_remote_twice_token =
-    create_async_signal_handler (async_remote_interrupt_twice, NULL);
+    create_async_signal_handler (inferior_event_handler_wrapper, NULL);
   mark_async_signal_handler_wrapper (sigint_remote_twice_token);
 }
 
@@ -2124,10 +2125,12 @@ async_remote_interrupt (arg)
 
 /* Perform interrupt, if the first attempt did not succeed. Just give
    up on the target alltogether. */
-static void
+void
 async_remote_interrupt_twice (arg)
      gdb_client_data arg;
 {
+  if (remote_debug)
+    fprintf_unfiltered (gdb_stdlog, "remote_interrupt_twice called\n");
   /* Do something only if the target was not killed by the previous
      cntl-C. */
   if (target_executing)
@@ -2265,8 +2268,7 @@ remote_async_terminal_ours (void)
 int kill_kludge;
 
 void
-remote_console_output (msg)
-     char *msg;
+remote_console_output (char *msg)
 {
   char *p;
 
@@ -2278,6 +2280,7 @@ remote_console_output (msg)
       tb[1] = 0;
       fputs_unfiltered (tb, gdb_stdtarg);
     }
+  gdb_flush (gdb_stdtarg);
 }
 
 /* Wait until the remote machine stops, then return,
@@ -2962,25 +2965,37 @@ hexnumlen (num)
   return max (i, 1);
 }
 
-/* Set BUF to the hex digits representing NUM.  */
+/* Set BUF to the minimum number of hex digits representing NUM.  */
 
 static int
 hexnumstr (buf, num)
      char *buf;
      ULONGEST num;
 {
-  int i;
   int len = hexnumlen (num);
+  return hexnumnstr (buf, num, len);
+}
+
+
+/* Set BUF to the hex digits representing NUM, padded to WIDTH characters.  */
+
+static int
+hexnumnstr (buf, num, width)
+     char *buf;
+     ULONGEST num;
+     int width;
+{
+  int i;
 
-  buf[len] = '\0';
+  buf[width] = '\0';
 
-  for (i = len - 1; i >= 0; i--)
+  for (i = width - 1; i >= 0; i--)
     {
       buf[i] = "0123456789abcdef"[(num & 0xf)];
       num >>= 4;
     }
 
-  return len;
+  return width;
 }
 
 /* Mask all but the least significant REMOTE_ADDRESS_SIZE bits. */
@@ -3062,139 +3077,134 @@ check_binary_download (addr)
    MYADDR is the address of the buffer in our space.
    LEN is the number of bytes.
 
-   Returns number of bytes transferred, or 0 for error.  */
+   Returns number of bytes transferred, or 0 (setting errno) for
+   error.  Only transfer a single packet. */
 
 static int
-remote_write_bytes (memaddr, myaddr, len)
-     CORE_ADDR memaddr;
-     char *myaddr;
-     int len;
+remote_write_bytes (CORE_ADDR memaddr, char *myaddr, int len)
 {
-  unsigned char *buf = alloca (PBUFSIZ);
+  unsigned char *buf;
   int max_buf_size;            /* Max size of packet output buffer */
-  int origlen;
+  unsigned char *p;
+  unsigned char *plen;
+  int plenlen;
+  int todo;
+  int nr_bytes;
 
   /* Verify that the target can support a binary download */
   check_binary_download (memaddr);
 
-  /* Chop the transfer down if necessary */
-
+  /* Determine the max packet size. */
   max_buf_size = min (remote_write_size, PBUFSIZ);
   if (remote_register_buf_size != 0)
     max_buf_size = min (max_buf_size, remote_register_buf_size);
+  buf = alloca (max_buf_size + 1);
 
   /* Subtract header overhead from max payload size -  $M<memaddr>,<len>:#nn */
   max_buf_size -= 2 + hexnumlen (memaddr + len - 1) + 1 + hexnumlen (len) + 4;
 
-  origlen = len;
-  while (len > 0)
-    {
-      unsigned char *p, *plen;
-      int todo;
-      int i;
+  /* construct "M"<memaddr>","<len>":" */
+  /* sprintf (buf, "M%lx,%x:", (unsigned long) memaddr, todo); */
+  p = buf;
 
-      /* construct "M"<memaddr>","<len>":" */
-      /* sprintf (buf, "M%lx,%x:", (unsigned long) memaddr, todo); */
-      memaddr = remote_address_masked (memaddr);
-      p = buf;
-      switch (remote_protocol_binary_download.support)
+  /* Append [XM].  Compute a best guess of the number of bytes
+     actually transfered. */
+  switch (remote_protocol_binary_download.support)
+    {
+    case PACKET_ENABLE:
+      *p++ = 'X';
+      /* Best guess at number of bytes that will fit. */
+      todo = min (len, max_buf_size);
+      break;
+    case PACKET_DISABLE:
+      *p++ = 'M';
+      /* num bytes that will fit */
+      todo = min (len, max_buf_size / 2);
+      break;
+    case PACKET_SUPPORT_UNKNOWN:
+      internal_error ("remote_write_bytes: bad switch");
+    }
+  
+  /* Append <memaddr> */
+  memaddr = remote_address_masked (memaddr);
+  p += hexnumstr (p, (ULONGEST) memaddr);
+  *p++ = ',';
+  
+  /* Append <len>.  Retain the location/size of <len>.  It may
+     need to be adjusted once the packet body has been created. */
+  plen = p;
+  plenlen = hexnumstr (p, (ULONGEST) todo);
+  p += plenlen;
+  *p++ = ':';
+  *p = '\0';
+  
+  /* Append the packet body. */
+  switch (remote_protocol_binary_download.support)
+    {
+    case PACKET_ENABLE:
+      /* Binary mode.  Send target system values byte by byte, in
+        increasing byte addresses.  Only escape certain critical
+        characters.  */
+      for (nr_bytes = 0;
+          (nr_bytes < todo) && (p - buf) < (max_buf_size - 2);
+          nr_bytes++)
        {
-       case PACKET_ENABLE:
-         *p++ = 'X';
-         todo = min (len, max_buf_size);
-         break;
-       case PACKET_DISABLE:
-         *p++ = 'M';
-         todo = min (len, max_buf_size / 2);   /* num bytes that will fit */
-         break;
-       case PACKET_SUPPORT_UNKNOWN:
-         internal_error ("remote_write_bytes: bad switch");
+         switch (myaddr[nr_bytes] & 0xff)
+           {
+           case '$':
+           case '#':
+           case 0x7d:
+             /* These must be escaped */
+             *p++ = 0x7d;
+             *p++ = (myaddr[nr_bytes] & 0xff) ^ 0x20;
+             break;
+           default:
+             *p++ = myaddr[nr_bytes] & 0xff;
+             break;
+           }
        }
-
-      p += hexnumstr (p, (ULONGEST) memaddr);
-      *p++ = ',';
-
-      plen = p;                        /* remember where len field goes */
-      p += hexnumstr (p, (ULONGEST) todo);
-      *p++ = ':';
-      *p = '\0';
-
-      /* We send target system values byte by byte, in increasing byte
-         addresses, each byte encoded as two hex characters (or one
-         binary character).  */
-      switch (remote_protocol_binary_download.support)
+      if (nr_bytes < todo)
        {
-       case PACKET_ENABLE:
-         {
-           int escaped = 0;
-           for (i = 0;
-                (i < todo) && (i + escaped) < (max_buf_size - 2);
-                i++)
-             {
-               switch (myaddr[i] & 0xff)
-                 {
-                 case '$':
-                 case '#':
-                 case 0x7d:
-                   /* These must be escaped */
-                   escaped++;
-                   *p++ = 0x7d;
-                   *p++ = (myaddr[i] & 0xff) ^ 0x20;
-                   break;
-                 default:
-                   *p++ = myaddr[i] & 0xff;
-                   break;
-                 }
-             }
-           
-           if (i < todo)
-             {
-               /* Escape chars have filled up the buffer prematurely, 
-                  and we have actually sent fewer bytes than planned.
-                  Fix-up the length field of the packet.  */
-               
-               /* FIXME: will fail if new len is a shorter string than 
-                  old len.  */
-               
-               plen += hexnumstr (plen, (ULONGEST) i);
-               *plen++ = ':';
-             }
-           break;
-         }
-       case PACKET_DISABLE:
-         {
-           for (i = 0; i < todo; i++)
-             {
-               *p++ = tohex ((myaddr[i] >> 4) & 0xf);
-               *p++ = tohex (myaddr[i] & 0xf);
-             }
-           *p = '\0';
-           break;
-         }
-       case PACKET_SUPPORT_UNKNOWN:
-         internal_error ("remote_write_bytes: bad switch");
+         /* Escape chars have filled up the buffer prematurely, 
+            and we have actually sent fewer bytes than planned.
+            Fix-up the length field of the packet.  Use the same
+            number of characters as before.  */
+         
+         plen += hexnumnstr (plen, (ULONGEST) nr_bytes, plenlen);
+         *plen = ':';  /* overwrite \0 from hexnumnstr() */
        }
-
-      putpkt_binary (buf, (int) (p - buf));
-      getpkt (buf, 0);
-
-      if (buf[0] == 'E')
+      break;
+    case PACKET_DISABLE:
+      /* Normal mode: Send target system values byte by byte, in
+        increasing byte addresses.  Each byte is encoded as a two hex
+        value.  */
+      for (nr_bytes = 0; nr_bytes < todo; nr_bytes++)
        {
-         /* There is no correspondance between what the remote protocol uses
-            for errors and errno codes.  We would like a cleaner way of
-            representing errors (big enough to include errno codes, bfd_error
-            codes, and others).  But for now just return EIO.  */
-         errno = EIO;
-         return 0;
+         *p++ = tohex ((myaddr[nr_bytes] >> 4) & 0xf);
+         *p++ = tohex (myaddr[nr_bytes] & 0xf);
        }
-
-      /* Increment by i, not by todo, in case escape chars 
-         caused us to send fewer bytes than we'd planned.  */
-      myaddr += i;
-      memaddr += i;
-      len -= i;
+      *p = '\0';
+      break;
+    case PACKET_SUPPORT_UNKNOWN:
+      internal_error ("remote_write_bytes: bad switch");
     }
-  return origlen;
+  
+  putpkt_binary (buf, (int) (p - buf));
+  getpkt (buf, 0);
+  
+  if (buf[0] == 'E')
+    {
+      /* There is no correspondance between what the remote protocol
+        uses for errors and errno codes.  We would like a cleaner way
+        of representing errors (big enough to include errno codes,
+        bfd_error codes, and others).  But for now just return EIO.  */
+      errno = EIO;
+      return 0;
+    }
+  
+  /* Return NR_BYTES, not TODO, in case escape chars caused us to send fewer
+     bytes than we'd planned.  */
+  return nr_bytes;
 }
 
 /* Read memory data directly from the remote machine.
@@ -3205,6 +3215,13 @@ remote_write_bytes (memaddr, myaddr, len)
 
    Returns number of bytes transferred, or 0 for error.  */
 
+/* NOTE: cagney/1999-10-18: This function (and its siblings in other
+   remote targets) shouldn't attempt to read the entire buffer.
+   Instead it should read a single packet worth of data and then
+   return the byte size of that packet to the caller.  The caller (its
+   caller and its callers caller ;-) already contains code for
+   handling partial reads. */
+
 static int
 remote_read_bytes (memaddr, myaddr, len)
      CORE_ADDR memaddr;
@@ -3960,7 +3977,8 @@ remote_insert_breakpoint (addr, contents_cache)
   if ((remote_protocol_Z.support == PACKET_ENABLE)
       || (remote_protocol_Z.support == PACKET_SUPPORT_UNKNOWN)) 
     {
-      char buf[PBUFSIZ], *p = buf;
+      char *buf = alloca (PBUFSIZ);
+      char *p = buf;
       
       addr = remote_address_masked (addr);
       *(p++) = 'Z';
@@ -4023,7 +4041,8 @@ remote_remove_breakpoint (addr, contents_cache)
   if ((remote_protocol_Z.support == PACKET_ENABLE)
       || (remote_protocol_Z.support == PACKET_SUPPORT_UNKNOWN))
     {
-      char buf[PBUFSIZ], *p = buf;
+      char *buf = alloca (PBUFSIZ);
+      char *p = buf;
       
       *(p++) = 'z';
       *(p++) = '0';
@@ -4054,7 +4073,8 @@ remote_insert_watchpoint (addr, len, type)
      int len;
      int type;
 {
-  char buf[PBUFSIZ], *p;
+  char *buf = alloca (PBUFSIZ);
+  char *p;
 
   if (remote_protocol_Z.support == PACKET_DISABLE)
     error ("Can't set hardware watchpoints without the 'Z' packet\n");
@@ -4080,7 +4100,8 @@ remote_remove_watchpoint (addr, len, type)
      int len;
      int type;
 {
-  char buf[PBUFSIZ], *p;
+  char *buf = alloca (PBUFSIZ);
+  char *p;
   
   sprintf (buf, "z%x,", type + 2 );
   p = strchr (buf, '\0');
@@ -4101,7 +4122,8 @@ remote_insert_hw_breakpoint (addr, len)
      CORE_ADDR addr;
      int len;
 {
-  char buf[PBUFSIZ], *p = buf;
+  char *buf = alloca (PBUFSIZ);
+  char *p = buf;
       
   if (remote_protocol_Z.support == PACKET_DISABLE)
     error ("Can't set hardware breakpoints without the 'Z' packet\n");
@@ -4128,7 +4150,8 @@ remote_remove_hw_breakpoint (addr, len)
      CORE_ADDR addr;
      int len;
 {
-  char buf[PBUFSIZ], *p = buf;
+  char *buf = alloca (PBUFSIZ);
+  char *p = buf;
   
   *(p++) = 'z';
   *(p++) = '1';
@@ -4222,6 +4245,11 @@ crc32 (buf, len, crc)
    Useful for verifying the image on the target against the exec file.
    Depends on the target understanding the new "qCRC:" request.  */
 
+/* FIXME: cagney/1999-10-26: This command should be broken down into a
+   target method (target verify memory) and generic version of the
+   actual command.  This will allow other high-level code (especially
+   generic_load()) to make use of this target functionality. */
+
 static void
 compare_sections_command (args, from_tty)
      char *args;