from Mat Hostetter <mat@lcs.mit.edu>
[deliverable/binutils-gdb.git] / gdb / gdbserver / remote-utils.c
index 8da223f7e3b2dc8018fa6015fdad7dedea51558f..b9a0733067b173778d17f9b64848e6d563ef0461 100644 (file)
@@ -1,7 +1,6 @@
 /* Remote utility routines for the remote server for GDB.
-   Copyright (C) 1986, 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-   2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
+   Copyright (C) 1986, 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+   2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -21,9 +20,7 @@
    Boston, MA 02110-1301, USA.  */
 
 #include "server.h"
-#if HAVE_TERMINAL_H
 #include "terminal.h"
-#endif
 #include <stdio.h>
 #include <string.h>
 #if HAVE_SYS_IOCTL_H
@@ -52,6 +49,8 @@
 #if HAVE_ARPA_INET_H
 #include <arpa/inet.h>
 #endif
+#include <sys/stat.h>
+#include <errno.h>
 
 #if USE_WIN32API
 #include <winsock.h>
@@ -85,6 +84,11 @@ static int remote_desc;
 extern int using_threads;
 extern int debug_threads;
 
+#ifdef USE_WIN32API
+# define read(fd, buf, len) recv (fd, buf, len, 0)
+# define write(fd, buf, len) send (fd, buf, len, 0)
+#endif
+
 /* Open a connection to a remote debugger.
    NAME is the filename used for communication.  */
 
@@ -94,13 +98,25 @@ remote_open (char *name)
 #if defined(F_SETFL) && defined (FASYNC)
   int save_fcntl_flags;
 #endif
-  
-  if (!strchr (name, ':'))
+  char *port_str;
+
+  port_str = strchr (name, ':');
+  if (port_str == NULL)
     {
 #ifdef USE_WIN32API
       error ("Only <host>:<port> is supported on this platform.");
 #else
-      remote_desc = open (name, O_RDWR);
+      struct stat statbuf;
+
+      if (stat (name, &statbuf) == 0
+         && (S_ISCHR (statbuf.st_mode) || S_ISFIFO (statbuf.st_mode)))
+       remote_desc = open (name, O_RDWR);
+      else
+       {
+         errno = EINVAL;
+         remote_desc = -1;
+       }
+
       if (remote_desc < 0)
        perror_with_name ("Could not open remote device");
 
@@ -193,6 +209,17 @@ remote_open (char *name)
          || listen (tmp_desc, 1))
        perror_with_name ("Can't bind address");
 
+      /* If port is zero, a random port will be selected, and the
+        fprintf below needs to know what port was selected.  */
+      if (port == 0)
+       {
+         socklen_t len = sizeof (sockaddr);
+         if (getsockname (tmp_desc, (struct sockaddr *) &sockaddr, &len) < 0
+             || len < sizeof (sockaddr))
+           perror_with_name ("Can't determine port");
+         port = ntohs (sockaddr.sin_port);
+       }
+
       fprintf (stderr, "Listening on port %d\n", port);
       fflush (stderr);
 
@@ -279,7 +306,7 @@ unhexify (char *bin, const char *hex, int count)
   return i;
 }
 
-static void
+void
 decode_address (CORE_ADDR *addrp, const char *start, int len)
 {
   CORE_ADDR addr;
@@ -296,6 +323,22 @@ decode_address (CORE_ADDR *addrp, const char *start, int len)
   *addrp = addr;
 }
 
+const char *
+decode_address_to_semicolon (CORE_ADDR *addrp, const char *start)
+{
+  const char *end;
+
+  end = start;
+  while (*end != '\0' && *end != ';')
+    end++;
+
+  decode_address (addrp, start, end - start);
+
+  if (*end == ';')
+    end++;
+  return end;
+}
+
 /* Convert number NIB to a hex digit.  */
 
 static int
@@ -406,6 +449,50 @@ remote_unescape_input (const gdb_byte *buffer, int len,
   return output_index;
 }
 
+/* Look for a sequence of characters which can be run-length encoded.
+   If there are any, update *CSUM and *P.  Otherwise, output the
+   single character.  Return the number of characters consumed.  */
+
+static int
+try_rle (char *buf, int remaining, unsigned char *csum, char **p)
+{
+  int n;
+
+  /* Always output the character.  */
+  *csum += buf[0];
+  *(*p)++ = buf[0];
+
+  /* Don't go past '~'.  */
+  if (remaining > 97)
+    remaining = 97;
+
+  for (n = 1; n < remaining; n++)
+    if (buf[n] != buf[0])
+      break;
+
+  /* N is the index of the first character not the same as buf[0].
+     buf[0] is counted twice, so by decrementing N, we get the number
+     of characters the RLE sequence will replace.  */
+  n--;
+
+  if (n < 3)
+    return 1;
+
+  /* Skip the frame characters.  The manual says to skip '+' and '-'
+     also, but there's no reason to.  Unfortunately these two unusable
+     characters double the encoded length of a four byte zero
+     value.  */
+  while (n + 29 == '$' || n + 29 == '#')
+    n--;
+
+  *csum += '*';
+  *(*p)++ = '*';
+  *csum += n + 29;
+  *(*p)++ = n + 29;
+
+  return n + 1;
+}
+
 /* Send a packet to the remote machine, with error checking.
    The data of the packet is in BUF, and the length of the
    packet is in CNT.  Returns >= 0 on success, -1 otherwise.  */
@@ -427,11 +514,9 @@ putpkt_binary (char *buf, int cnt)
   p = buf2;
   *p++ = '$';
 
-  for (i = 0; i < cnt; i++)
-    {
-      csum += buf[i];
-      *p++ = buf[i];
-    }
+  for (i = 0; i < cnt;)
+    i += try_rle (buf + i, cnt - i, &csum, &p);
+
   *p++ = '#';
   *p++ = tohex ((csum >> 4) & 0xf);
   *p++ = tohex (csum & 0xf);
@@ -444,7 +529,7 @@ putpkt_binary (char *buf, int cnt)
     {
       int cc;
 
-      if (send (remote_desc, buf2, p - buf2, 0) != p - buf2)
+      if (write (remote_desc, buf2, p - buf2) != p - buf2)
        {
          perror ("putpkt(write)");
          return -1;
@@ -455,7 +540,7 @@ putpkt_binary (char *buf, int cnt)
          fprintf (stderr, "putpkt (\"%s\"); [looking for ack]\n", buf2);
          fflush (stderr);
        }
-      cc = recv (remote_desc, buf3, 1, 0);
+      cc = read (remote_desc, buf3, 1);
       if (remote_debug)
        {
          fprintf (stderr, "[received '%c' (0x%x)]\n", buf3[0], buf3[0]);
@@ -475,7 +560,7 @@ putpkt_binary (char *buf, int cnt)
 
       /* Check for an input interrupt while we're here.  */
       if (buf3[0] == '\003')
-       (*the_target->send_signal) (SIGINT);
+       (*the_target->request_interrupt) ();
     }
   while (buf3[0] != '+');
 
@@ -498,7 +583,7 @@ putpkt (char *buf)
 /* Come here when we get an input interrupt from the remote side.  This
    interrupt should only be active while we are waiting for the child to do
    something.  About the only thing that should come through is a ^C, which
-   will cause us to send a SIGINT to the child.  */
+   will cause us to request child interruption.  */
 
 static void
 input_interrupt (int unused)
@@ -516,7 +601,7 @@ input_interrupt (int unused)
       int cc;
       char c = 0;
       
-      cc = recv (remote_desc, &c, 1, 0);
+      cc = read (remote_desc, &c, 1);
 
       if (cc != 1 || c != '\003')
        {
@@ -525,7 +610,7 @@ input_interrupt (int unused)
          return;
        }
       
-      (*the_target->send_signal) (SIGINT);
+      (*the_target->request_interrupt) ();
     }
 }
 #endif
@@ -597,7 +682,7 @@ readchar (void)
   if (bufcnt-- > 0)
     return *bufp++;
 
-  bufcnt = recv (remote_desc, buf, sizeof (buf), 0);
+  bufcnt = read (remote_desc, buf, sizeof (buf));
 
   if (bufcnt <= 0)
     {
@@ -664,7 +749,7 @@ getpkt (char *buf)
 
       fprintf (stderr, "Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s\n",
               (c1 << 4) + c2, csum, buf);
-      send (remote_desc, "-", 1, 0);
+      write (remote_desc, "-", 1);
     }
 
   if (remote_debug)
@@ -673,7 +758,7 @@ getpkt (char *buf)
       fflush (stderr);
     }
 
-  send (remote_desc, "+", 1, 0);
+  write (remote_desc, "+", 1);
 
   if (remote_debug)
     {
@@ -1000,3 +1085,15 @@ look_up_one_symbol (const char *name, CORE_ADDR *addrp)
 
   return 1;
 }
+
+void
+monitor_output (char *msg)
+{
+  char *buf = malloc (strlen (msg) * 2 + 2);
+
+  buf[0] = 'O';
+  hexify (buf + 1, msg, 0);
+
+  putpkt (buf);
+  free (buf);
+}
This page took 0.033516 seconds and 4 git commands to generate.