Init current_directory.
[deliverable/binutils-gdb.git] / gdb / remote.c
index 43d0f3327ff716abc9a525faeb2a55e87661b78d..40536ef5f4464366493a6b2126697d1a9dabb6e2 100644 (file)
@@ -1,5 +1,5 @@
 /* Remote target communications for serial-line targets in custom GDB protocol
-   Copyright 1988, 1991, 1992, 1993 Free Software Foundation, Inc.
+   Copyright 1988, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
 
 This file is part of GDB.
 
@@ -25,7 +25,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
        $ <data> # CSUM1 CSUM2
 
        <data> must be ASCII alphanumeric and cannot include characters
-       '$' or '#'
+       '$' or '#'.  If <data> starts with two characters followed by
+       ':', then the existing stubs interpret this as a sequence number.
 
        CSUM1 and CSUM2 are ascii hex representation of an 8-bit 
        checksum of <data>, the most significant nibble is sent first.
@@ -54,6 +55,14 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
        reply           OK              for success
                        ENN             for an error
 
+        write reg      Pn...=r...      Write register n... with value r...,
+                                       which contains two hex digits for each
+                                       byte in the register (target byte
+                                       order).
+       reply           OK              for success
+                       ENN             for an error
+       (not supported by all stubs).
+
        read mem        mAA..AA,LLLL    AA..AA is address, LLLL is length.
        reply           XX..XX          XX..XX is mem contents
                                        Can be fewer bytes than requested
@@ -90,7 +99,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
                                        AA = signal number
                                        n... = register number
                                        r... = register contents
-
+       or...           WAA             The process exited, and AA is
+                                       the exit status.  This is only
+                                       applicable for certains sorts of
+                                       targets.
        kill request    k
 
        toggle debug    d               toggle debug flag (see 386 & 68k stubs)
@@ -101,7 +113,21 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
                                        we can extend the protocol and GDB
                                        can tell whether the stub it is
                                        talking to uses the old or the new.
-*/
+       search          tAA:PP,MM       Search backwards starting at address
+                                       AA for a match with pattern PP and
+                                       mask MM.  PP and MM are 4 bytes.
+                                       Not supported by all stubs.
+
+       general query   qXXXX           Request info about XXXX.
+       general set     QXXXX=yyyy      Set value of XXXX to yyyy.
+       query sect offs qOffsets        Get section offsets.  Reply is
+                                       Text=xxx;Data=yyy;Bss=zzz
+
+       Responses can be run-length encoded to save space.  A '*' means that
+       the next two characters are hex digits giving a repeat count which
+       stands for that many repititions of the character preceding the '*'.
+       Note that this means that responses cannot contain '*'.  Example:
+       "0*03" means the same as "0000".  */
 
 #include "defs.h"
 #include <string.h>
@@ -114,6 +140,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "wait.h"
 #include "terminal.h"
 #include "gdbcmd.h"
+#include "objfiles.h"
+#include "gdb-stabs.h"
 
 #include "dcache.h"
 
@@ -147,7 +175,7 @@ static void
 remote_fetch_registers PARAMS ((int regno));
 
 static void
-remote_resume PARAMS ((int pid, int step, int siggnal));
+remote_resume PARAMS ((int pid, int step, enum target_signal siggnal));
 
 static int
 remote_start_remote PARAMS ((char *dummy));
@@ -173,8 +201,7 @@ remote_send PARAMS ((char *buf));
 static int
 readchar PARAMS ((void));
 
-static int
-remote_wait PARAMS ((WAITTYPE *status));
+static int remote_wait PARAMS ((int pid, struct target_waitstatus *status));
 
 static int
 tohex PARAMS ((int nib));
@@ -191,6 +218,9 @@ remote_interrupt PARAMS ((int signo));
 static void
 remote_interrupt_twice PARAMS ((int signo));
 
+static void
+interrupt_query PARAMS ((void));
+
 extern struct target_ops remote_ops;   /* Forward decl */
 
 /* This was 5 seconds, which is a long time to sit and wait.
@@ -208,17 +238,30 @@ int icache;
    starts.  */
 serial_t remote_desc = NULL;
 
-#define        PBUFSIZ 1024
+/* Having this larger than 400 causes us to be incompatible with m68k-stub.c
+   and i386-stub.c.  Normally, no one would notice because it only matters
+   for writing large chunks of memory (e.g. in downloads).  Also, this needs
+   to be more than 400 if required to hold the registers (see below, where
+   we round it up based on REGISTER_BYTES).  */
+#define        PBUFSIZ 400
 
 /* Maximum number of bytes to read/write at once.  The value here
    is chosen to fill up a packet (the headers account for the 32).  */
 #define MAXBUFBYTES ((PBUFSIZ-32)/2)
 
 /* Round up PBUFSIZ to hold all the registers, at least.  */
+/* The blank line after the #if seems to be required to work around a
+   bug in HP's PA compiler.  */
 #if REGISTER_BYTES > MAXBUFBYTES
-#undef PBUFSIZ
+
+#undef PBUFSIZ
 #define        PBUFSIZ (REGISTER_BYTES * 2 + 32)
 #endif
+
+/* Should we try the 'P' request?  If this is set to one when the stub
+   doesn't support 'P', the only consequence is some unnecessary traffic.  */
+static int stub_supports_P = 1;
+
 \f
 /* Clean up connection to a remote debugger.  */
 
@@ -232,19 +275,82 @@ remote_close (quitting)
   remote_desc = NULL;
 }
 
+/* Query the remote side for the text, data and bss offsets. */
+
+static void
+get_offsets ()
+{
+  unsigned char buf[PBUFSIZ];
+  int nvals;
+  CORE_ADDR text_addr, data_addr, bss_addr;
+  struct section_offsets *offs;
+
+  putpkt ("qOffsets");
+
+  getpkt (buf, 0);
+
+  if (buf[0] == '\000')
+    return;                    /* Return silently.  Stub doesn't support this
+                                  command. */
+  if (buf[0] == 'E')
+    {
+      warning ("Remote failure reply: %s", buf);
+      return;
+    }
+
+  nvals = sscanf (buf, "Text=%lx;Data=%lx;Bss=%lx", &text_addr, &data_addr,
+                 &bss_addr);
+  if (nvals != 3)
+    error ("Malformed response to offset query, %s", buf);
+
+  if (symfile_objfile == NULL)
+    return;
+
+  offs = (struct section_offsets *) alloca (sizeof (struct section_offsets)
+                                           + symfile_objfile->num_sections
+                                           * sizeof (offs->offsets));
+  memcpy (offs, symfile_objfile->section_offsets,
+         sizeof (struct section_offsets)
+         + symfile_objfile->num_sections
+         * sizeof (offs->offsets));
+
+  /* FIXME: This code assumes gdb-stabs.h is being used; it's broken
+     for xcoff, dwarf, sdb-coff, etc.  But there is no simple
+     canonical representation for this stuff.  (Just what does "text"
+     as seen by the stub mean, anyway?  I think it means all sections
+     with SEC_CODE set, but we currently have no way to deal with that).  */
+
+  ANOFFSET (offs, SECT_OFF_TEXT) = text_addr;
+
+  /* This is a temporary kludge to force data and bss to use the same offsets
+     because that's what nlmconv does now.  The real solution requires changes
+     to the stub and remote.c that I don't have time to do right now.  */
+
+  ANOFFSET (offs, SECT_OFF_DATA) = data_addr;
+  ANOFFSET (offs, SECT_OFF_BSS) = data_addr;
+
+  objfile_relocate (symfile_objfile, offs);
+}
+
 /* Stub for catch_errors.  */
 
 static int
 remote_start_remote (dummy)
      char *dummy;
 {
+  immediate_quit = 1;          /* Allow user to interrupt it */
+
   /* Ack any packet which the remote side has already sent.  */
-  /* I'm not sure this \r is needed; we don't use it any other time we
-     send an ack.  */
-  SERIAL_WRITE (remote_desc, "+\r", 2);
+
+  SERIAL_WRITE (remote_desc, "+", 1);
+
+  get_offsets ();              /* Get text, data & bss offsets */
+
   putpkt ("?");                        /* initiate a query from remote machine */
+  immediate_quit = 0;
 
   start_remote ();             /* Initialize gdb process mechanisms */
+
   return 1;
 }
 
@@ -273,20 +379,21 @@ device is attached to the remote system (e.g. /dev/ttya).");
   if (!remote_desc)
     perror_with_name (name);
 
-  if (baud_rate)
+  if (baud_rate != -1)
     {
-      int rate;
-
-      if (sscanf (baud_rate, "%d", &rate) == 1)
-       if (SERIAL_SETBAUDRATE (remote_desc, rate))
-         {
-           SERIAL_CLOSE (remote_desc);
-           perror_with_name (name);
-         }
+      if (SERIAL_SETBAUDRATE (remote_desc, baud_rate))
+       {
+         SERIAL_CLOSE (remote_desc);
+         perror_with_name (name);
+       }
     }
 
   SERIAL_RAW (remote_desc);
 
+  /* If there is something sitting in the buffer we might take it as a
+     response to a command, which would be bad.  */
+  SERIAL_FLUSH_INPUT (remote_desc);
+
   if (from_tty)
     {
       puts_filtered ("Remote debugging using ");
@@ -295,8 +402,14 @@ device is attached to the remote system (e.g. /dev/ttya).");
     }
   push_target (&remote_ops);   /* Switch to using remote target now */
 
-  /* Start the remote connection; if error (0), discard this target. */
-  immediate_quit++;            /* Allow user to interrupt it */
+  /* Start out by trying the 'P' request to set registers.  We set this each
+     time that we open a new target so that if the user switches from one
+     stub to another, we can (if the target is closed and reopened) cope.  */
+  stub_supports_P = 1;
+
+  /* Start the remote connection; if error (0), discard this target.
+     In particular, if the user quits, be sure to discard it
+     (we'd be in an inconsistent state otherwise).  */
   if (!catch_errors (remote_start_remote, (char *)0, 
        "Couldn't establish connection to remote target\n", RETURN_MASK_ALL))
     pop_target();
@@ -354,21 +467,17 @@ tohex (nib)
 
 static void
 remote_resume (pid, step, siggnal)
-     int pid, step, siggnal;
+     int pid, step;
+     enum target_signal siggnal;
 {
   char buf[PBUFSIZ];
 
   if (siggnal)
     {
-      char *name;
       target_terminal_ours_for_output ();
-      printf_filtered ("Can't send signals to a remote system.  ");
-      name = strsigno (siggnal);
-      if (name)
-       printf_filtered (name);
-      else
-       printf_filtered ("Signal %d", siggnal);
-      printf_filtered (" not sent.\n");
+      printf_filtered
+       ("Can't send signals to a remote system.  %s not sent.\n",
+        target_signal_to_name (siggnal));
       target_terminal_inferior ();
     }
 
@@ -390,7 +499,7 @@ remote_interrupt (signo)
   signal (signo, remote_interrupt_twice);
   
   if (remote_debug)
-    printf ("remote_interrupt called\n");
+    printf_unfiltered ("remote_interrupt called\n");
 
   SERIAL_WRITE (remote_desc, "\003", 1); /* Send a ^C */
 }
@@ -404,18 +513,26 @@ remote_interrupt_twice (signo)
 {
   signal (signo, ofunc);
   
+  interrupt_query ();
+
+  signal (signo, remote_interrupt);
+}
+
+/* Ask the user what to do when an interrupt is received.  */
+
+static void
+interrupt_query ()
+{
   target_terminal_ours ();
+
   if (query ("Interrupted while waiting for the program.\n\
 Give up (and stop debugging it)? "))
     {
       target_mourn_inferior ();
       return_to_top_level (RETURN_QUIT);
     }
-  else
-    {
-      signal (signo, remote_interrupt);
-      target_terminal_inferior ();
-    }
+
+  target_terminal_inferior ();
 }
 
 /* Wait until the remote machine stops, then return,
@@ -424,76 +541,98 @@ Give up (and stop debugging it)? "))
    means in the case of this target).  */
 
 static int
-remote_wait (status)
-     WAITTYPE *status;
+remote_wait (pid, status)
+     int pid;
+     struct target_waitstatus *status;
 {
   unsigned char buf[PBUFSIZ];
-  unsigned char *p;
-  int i;
-  long regno;
-  char regs[MAX_REGISTER_RAW_SIZE];
-
-  WSETEXIT ((*status), 0);
 
-  ofunc = (void (*)()) signal (SIGINT, remote_interrupt);
-  getpkt ((char *) buf, 1);
-  signal (SIGINT, ofunc);
+  status->kind = TARGET_WAITKIND_EXITED;
+  status->value.integer = 0;
 
-  if (buf[0] == 'E')
-    error ("Remote failure reply: %s", buf);
-  if (buf[0] == 'T')
+  while (1)
     {
-      /* Expedited reply, containing Signal, {regno, reg} repeat */
-      /*  format is:  'Tssn...:r...;n...:r...;n...:r...;#cc', where
-         ss = signal number
-         n... = register number
-         r... = register contents
-         */
+      unsigned char *p;
 
-      p = &buf[3];             /* after Txx */
+      ofunc = (void (*)()) signal (SIGINT, remote_interrupt);
+      getpkt ((char *) buf, 1);
+      signal (SIGINT, ofunc);
 
-      while (*p)
+      if (buf[0] == 'E')
+       warning ("Remote failure reply: %s", buf);
+      else if (buf[0] == 'T')
        {
-         unsigned char *p1;
+         int i;
+         long regno;
+         char regs[MAX_REGISTER_RAW_SIZE];
 
-         regno = strtol (p, &p1, 16); /* Read the register number */
+         /* Expedited reply, containing Signal, {regno, reg} repeat */
+         /*  format is:  'Tssn...:r...;n...:r...;n...:r...;#cc', where
+             ss = signal number
+             n... = register number
+             r... = register contents
+             */
 
-         if (p1 == p)
-           error ("Remote sent badly formed register number: %s\nPacket: '%s'\n",
-                  p1, buf);
+         p = &buf[3];          /* after Txx */
 
-         p = p1;
+         while (*p)
+           {
+             unsigned char *p1;
 
-         if (*p++ != ':')
-           error ("Malformed packet (missing colon): %s\nPacket: '%s'\n",
-                  p, buf);
+             regno = strtol (p, &p1, 16); /* Read the register number */
 
-         if (regno >= NUM_REGS)
-           error ("Remote sent bad register number %d: %s\nPacket: '%s'\n",
-                  regno, p, buf);
+             if (p1 == p)
+               warning ("Remote sent badly formed register number: %s\nPacket: '%s'\n",
+                        p1, buf);
 
-         for (i = 0; i < REGISTER_RAW_SIZE (regno); i++)
-           {
-             if (p[0] == 0 || p[1] == 0)
-               error ("Remote reply is too short: %s", buf);
-             regs[i] = fromhex (p[0]) * 16 + fromhex (p[1]);
-             p += 2;
-           }
+             p = p1;
+
+             if (*p++ != ':')
+               warning ("Malformed packet (missing colon): %s\nPacket: '%s'\n",
+                        p, buf);
+
+             if (regno >= NUM_REGS)
+               warning ("Remote sent bad register number %d: %s\nPacket: '%s'\n",
+                        regno, p, buf);
 
-         if (*p++ != ';')
-           error("Remote register badly formatted: %s", buf);
+             for (i = 0; i < REGISTER_RAW_SIZE (regno); i++)
+               {
+                 if (p[0] == 0 || p[1] == 0)
+                   warning ("Remote reply is too short: %s", buf);
+                 regs[i] = fromhex (p[0]) * 16 + fromhex (p[1]);
+                 p += 2;
+               }
 
-         supply_register (regno, regs);
+             if (*p++ != ';')
+               warning ("Remote register badly formatted: %s", buf);
+
+             supply_register (regno, regs);
+           }
+         break;
+       }
+      else if (buf[0] == 'W')
+       {
+         /* The remote process exited.  */
+         status->kind = TARGET_WAITKIND_EXITED;
+         status->value.integer = (fromhex (buf[1]) << 4) + fromhex (buf[2]);
+         return 0;
        }
+      else if (buf[0] == 'S')
+       break;
+      else
+       warning ("Invalid remote reply: %s", buf);
     }
-  else if (buf[0] != 'S')
-    error ("Invalid remote reply: %s", buf);
 
-  WSETSTOP ((*status), (((fromhex (buf[1])) << 4) + (fromhex (buf[2]))));
+  status->kind = TARGET_WAITKIND_STOPPED;
+  status->value.sig = (enum target_signal)
+    (((fromhex (buf[1])) << 4) + (fromhex (buf[2])));
 
   return 0;
 }
 
+/* Number of bytes of registers this stub implements.  */
+static int register_bytes_found;
+
 /* Read the remote registers into the block REGS.  */
 /* Currently we just read all the registers, so we don't use regno.  */
 /* ARGSUSED */
@@ -509,6 +648,20 @@ remote_fetch_registers (regno)
   sprintf (buf, "g");
   remote_send (buf);
 
+  /* Unimplemented registers read as all bits zero.  */
+  memset (regs, 0, REGISTER_BYTES);
+
+  /* We can get out of synch in various cases.  If the first character
+     in the buffer is not a hex character, assume that has happened
+     and try to fetch another packet to read.  */
+  while ((buf[0] < '0' || buf[0] > '9')
+        && (buf[0] < 'a' || buf[0] > 'f'))
+    {
+      if (remote_debug)
+       printf_unfiltered ("Bad register packet; fetching a new packet\n");
+      getpkt (buf, 0);
+    }
+
   /* Reply describes registers byte by byte, each byte encoded as two
      hex characters.  Suck them all up, then supply them to the
      register cacheing/storage mechanism.  */
@@ -516,17 +669,36 @@ remote_fetch_registers (regno)
   p = buf;
   for (i = 0; i < REGISTER_BYTES; i++)
     {
-      if (p[0] == 0 || p[1] == 0)
-       error ("Remote reply is too short: %s", buf);
+      if (p[0] == 0)
+       break;
+      if (p[1] == 0)
+       {
+         warning ("Remote reply is of odd length: %s", buf);
+         /* Don't change register_bytes_found in this case, and don't
+            print a second warning.  */
+         goto supply_them;
+       }
       regs[i] = fromhex (p[0]) * 16 + fromhex (p[1]);
       p += 2;
     }
+
+  if (i != register_bytes_found)
+    {
+      register_bytes_found = i;
+#ifdef REGISTER_BYTES_OK
+      if (!REGISTER_BYTES_OK (i))
+       warning ("Remote reply is too short: %s", buf);
+#endif
+    }
+
+ supply_them:
   for (i = 0; i < NUM_REGS; i++)
     supply_register (i, &regs[REGISTER_BYTE(i)]);
 }
 
-/* Prepare to store registers.  Since we send them all, we have to
-   read out the ones we don't want to change first.  */
+/* Prepare to store registers.  Since we may send them all (using a
+   'G' request), we have to read out the ones we don't want to change
+   first.  */
 
 static void 
 remote_prepare_to_store ()
@@ -535,10 +707,9 @@ remote_prepare_to_store ()
   read_register_bytes (0, (char *)NULL, REGISTER_BYTES);
 }
 
-/* Store the remote registers from the contents of the block REGISTERS. 
-   FIXME, eventually just store one register if that's all that is needed.  */
+/* Store register REGNO, or all registers if REGNO == -1, from the contents
+   of REGISTERS.  FIXME: ignores errors.  */
 
-/* ARGSUSED */
 static void
 remote_store_registers (regno)
      int regno;
@@ -547,13 +718,41 @@ remote_store_registers (regno)
   int i;
   char *p;
 
+  if (regno >= 0 && stub_supports_P)
+    {
+      /* Try storing a single register.  */
+      char *regp;
+
+      sprintf (buf, "P%x=", regno);
+      p = buf + strlen (buf);
+      regp = &registers[REGISTER_BYTE (regno)];
+      for (i = 0; i < REGISTER_RAW_SIZE (regno); ++i)
+       {
+         *p++ = tohex ((regp[i] >> 4) & 0xf);
+         *p++ = tohex (regp[i] & 0xf);
+       }
+      *p = '\0';
+      remote_send (buf);
+      if (buf[0] != '\0')
+       {
+         /* The stub understands the 'P' request.  We are done.  */
+         return;
+       }
+
+      /* The stub does not support the 'P' request.  Use 'G' instead,
+        and don't try using 'P' in the future (it will just waste our
+        time).  */
+      stub_supports_P = 0;
+    }
+
   buf[0] = 'G';
-  
+
   /* Command describes registers byte by byte,
      each byte encoded as two hex characters.  */
 
   p = buf + 1;
-  for (i = 0; i < REGISTER_BYTES; i++)
+  /* remote_prepare_to_store insures that register_bytes_found gets set.  */
+  for (i = 0; i < register_bytes_found; i++)
     {
       *p++ = tohex ((registers[i] >> 4) & 0xf);
       *p++ = tohex (registers[i] & 0xf);
@@ -563,10 +762,21 @@ remote_store_registers (regno)
   remote_send (buf);
 }
 
+#if 0
+
+/* Use of the data cache is disabled because it loses for looking at
+   and changing hardware I/O ports and the like.  Accepting `volatile'
+   would perhaps be one way to fix it, but a better way which would
+   win for more cases would be to use the executable file for the text
+   segment, like the `icache' code below but done cleanly (in some
+   target-independent place, perhaps in target_xfer_memory, perhaps
+   based on assigning each target a speed or perhaps by some simpler
+   mechanism).  */
+
 /* Read a word from remote address ADDR and return it.
    This goes through the data cache.  */
 
-int
+static int
 remote_fetch_word (addr)
      CORE_ADDR addr;
 {
@@ -589,14 +799,14 @@ remote_fetch_word (addr)
 /* Write a word WORD into remote address ADDR.
    This goes through the data cache.  */
 
-void
+static void
 remote_store_word (addr, word)
      CORE_ADDR addr;
      int word;
 {
   dcache_poke (remote_dcache, addr, word);
 }
-
+#endif /* 0 */
 \f
 /* Write memory data directly to the remote machine.
    This does not inform the data cache; the data cache uses this.
@@ -616,10 +826,9 @@ remote_write_bytes (memaddr, myaddr, len)
   int i;
   char *p;
 
-  if (len > PBUFSIZ / 2 - 20)
-    abort ();
-
-  sprintf (buf, "M%x,%x:", memaddr, len);
+  /* FIXME-32x64: Need a version of print_address_numeric which puts the
+     result in a buffer like sprintf.  */
+  sprintf (buf, "M%lx,%x:", (unsigned long) memaddr, len);
 
   /* We send target system values byte by byte, in increasing byte addresses,
      each byte encoded as two hex characters.  */
@@ -668,7 +877,9 @@ remote_read_bytes (memaddr, myaddr, len)
   if (len > PBUFSIZ / 2 - 1)
     abort ();
 
-  sprintf (buf, "m%x,%x", memaddr, len);
+  /* FIXME-32x64: Need a version of print_address_numeric which puts the
+     result in a buffer like sprintf.  */
+  sprintf (buf, "m%lx,%x", (unsigned long) memaddr, len);
   putpkt (buf);
   getpkt (buf, 0);
 
@@ -723,9 +934,11 @@ remote_xfer_memory(memaddr, myaddr, len, should_write, target)
        xfersize = len;
 
       if (should_write)
-        bytes_xferred = remote_write_bytes (memaddr, myaddr, xfersize);
+        bytes_xferred = remote_write_bytes (memaddr,
+                                           (unsigned char *)myaddr, xfersize);
       else
-       bytes_xferred = remote_read_bytes (memaddr, myaddr, xfersize);
+       bytes_xferred = remote_read_bytes (memaddr,
+                                          (unsigned char *)myaddr, xfersize);
 
       /* If we get an error, we are done xferring.  */
       if (bytes_xferred == 0)
@@ -739,6 +952,80 @@ remote_xfer_memory(memaddr, myaddr, len, should_write, target)
   return total_xferred;
 }
 
+#if 0
+/* Enable after 4.12.  */
+
+void
+remote_search (len, data, mask, startaddr, increment, lorange, hirange
+              addr_found, data_found)
+     int len;
+     char *data;
+     char *mask;
+     CORE_ADDR startaddr;
+     int increment;
+     CORE_ADDR lorange;
+     CORE_ADDR hirange;
+     CORE_ADDR *addr_found;
+     char *data_found;
+{
+  if (increment == -4 && len == 4)
+    {
+      long mask_long, data_long;
+      long data_found_long;
+      CORE_ADDR addr_we_found;
+      char buf[PBUFSIZ];
+      long returned_long[2];
+      char *p;
+
+      mask_long = extract_unsigned_integer (mask, len);
+      data_long = extract_unsigned_integer (data, len);
+      sprintf (buf, "t%x:%x,%x", startaddr, data_long, mask_long);
+      putpkt (buf);
+      getpkt (buf, 0);
+      if (buf[0] == '\0')
+       {
+         /* The stub doesn't support the 't' request.  We might want to
+            remember this fact, but on the other hand the stub could be
+            switched on us.  Maybe we should remember it only until
+            the next "target remote".  */
+         generic_search (len, data, mask, startaddr, increment, lorange,
+                         hirange, addr_found, data_found);
+         return;
+       }
+
+      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 use EIO.  */
+       memory_error (EIO, startaddr);
+      p = buf;
+      addr_we_found = 0;
+      while (*p != '\0' && *p != ',')
+       addr_we_found = (addr_we_found << 4) + fromhex (*p++);
+      if (*p == '\0')
+       error ("Protocol error: short return for search");
+
+      data_found_long = 0;
+      while (*p != '\0' && *p != ',')
+       data_found_long = (data_found_long << 4) + fromhex (*p++);
+      /* Ignore anything after this comma, for future extensions.  */
+
+      if (addr_we_found < lorange || addr_we_found >= hirange)
+       {
+         *addr_found = 0;
+         return;
+       }
+
+      *addr_found = addr_we_found;
+      *data_found = store_unsigned_integer (data_we_found, len);
+      return;
+    }
+  generic_search (len, data, mask, startaddr, increment, lorange,
+                 hirange, addr_found, data_found);
+}
+#endif /* 0 */
+\f
 static void
 remote_files_info (ignore)
      struct target_ops *ignore;
@@ -816,10 +1103,13 @@ putpkt (buf)
 
   while (1)
     {
+      int started_error_output = 0;
+
       if (remote_debug)
        {
          *p = '\0';
-         printf ("Sending packet: %s...", buf2);  fflush(stdout);
+         printf_unfiltered ("Sending packet: %s...", buf2);
+         gdb_flush(gdb_stdout);
        }
       if (SERIAL_WRITE (remote_desc, buf2, p - buf2))
        perror_with_name ("putpkt: write failed");
@@ -829,11 +1119,28 @@ putpkt (buf)
        {
          ch = readchar ();
 
+         if (remote_debug)
+           {
+             switch (ch)
+               {
+               case '+':
+               case SERIAL_TIMEOUT:
+               case SERIAL_ERROR:
+               case SERIAL_EOF:
+               case '$':
+                 if (started_error_output)
+                   {
+                     putc_unfiltered ('\n');
+                     started_error_output = 0;
+                   }
+               }
+           }
+
          switch (ch)
            {
            case '+':
              if (remote_debug)
-               printf("Ack\n");
+               printf_unfiltered("Ack\n");
              return;
            case SERIAL_TIMEOUT:
              break;            /* Retransmit buffer */
@@ -841,13 +1148,42 @@ putpkt (buf)
              perror_with_name ("putpkt: couldn't read ACK");
            case SERIAL_EOF:
              error ("putpkt: EOF while trying to read ACK");
+           case '$':
+             {
+               unsigned char junkbuf[PBUFSIZ];
+
+             /* It's probably an old response, and we're out of sync.  Just
+                gobble up the packet and ignore it.  */
+               getpkt (junkbuf, 0);
+               continue;               /* Now, go look for + */
+             }
            default:
              if (remote_debug)
-               printf ("%02X %c ", ch&0xFF, ch);
+               {
+                 if (!started_error_output)
+                   {
+                     started_error_output = 1;
+                     printf_unfiltered ("putpkt: Junk: ");
+                   }
+                 putc_unfiltered (ch & 0177);
+               }
              continue;
            }
          break;                /* Here to retransmit */
        }
+
+#if 0
+      /* This is wrong.  If doing a long backtrace, the user should be
+        able to get out next time we call QUIT, without anything as violent
+        as interrupt_query.  If we want to provide a way out of here
+        without getting to the next QUIT, it should be based on hitting
+        ^C twice as in remote_wait.  */
+      if (quit_flag)
+       {
+         quit_flag = 0;
+         interrupt_query ();
+       }
+#endif
     }
 }
 
@@ -857,8 +1193,8 @@ putpkt (buf)
    while the target is executing user code.  */
 
 static void
-getpkt (buf, forever)
-     char *buf;
+getpkt (retbuf, forever)
+     char *retbuf;
      int forever;
 {
   char *bp;
@@ -866,10 +1202,25 @@ getpkt (buf, forever)
   int c = 0;
   unsigned char c1, c2;
   int retries = 0;
+  char buf[PBUFSIZ];
+
 #define MAX_RETRIES    10
 
   while (1)
     {
+#if 0
+      /* This is wrong.  If doing a long backtrace, the user should be
+        able to get out time next we call QUIT, without anything as violent
+        as interrupt_query.  If we want to provide a way out of here
+        without getting to the next QUIT, it should be based on hitting
+        ^C twice as in remote_wait.  */
+      if (quit_flag)
+       {
+         quit_flag = 0;
+         interrupt_query ();
+       }
+#endif
+
       /* This can loop forever if the remote side sends us characters
         continuously, but if it pauses, we'll get a zero from readchar
         because of timeout.  Then we'll count that as a retry.  */
@@ -882,9 +1233,9 @@ getpkt (buf, forever)
        {
          if (forever)
            continue;
-         if (++retries >= MAX_RETRIES)
-           if (remote_debug) puts_filtered ("Timed out.\n");
-         goto out;
+         if (remote_debug)
+           puts_filtered ("Timed out.\n");
+         goto whole;
        }
 
       if (c == SERIAL_EOF)
@@ -943,17 +1294,44 @@ whole:
        }
       else
        {
-         printf ("Ignoring packet error, continuing...\n");
+         printf_unfiltered ("Ignoring packet error, continuing...\n");
          break;
        }
     }
 
-out:
+  /* Deal with run-length encoding.  */
+  {
+    char *src = buf;
+    char *dest = retbuf;
+    int i;
+    int repeat;
+    do {
+      if (*src == '*')
+       {
+         if (src[1] == '\0' || src[2] == '\0')
+           {
+             if (remote_debug)
+               puts_filtered ("Packet too short, retrying\n");
+             goto whole;
+           }
+         repeat = (fromhex (src[1]) << 4) + fromhex (src[2]);
+         for (i = 0; i < repeat; ++i)
+           {
+             *dest++ = src[-1];
+           }
+         src += 2;
+       }
+      else
+       {
+         *dest++ = *src;
+       }
+    } while (*src++ != '\0');
+  }
 
   SERIAL_WRITE (remote_desc, "+", 1);
 
   if (remote_debug)
-    fprintf (stderr,"Packet received: %s\n", buf);
+    fprintf_unfiltered (gdb_stderr,"Packet received: %s\n", buf);
 }
 \f
 static void
@@ -1065,10 +1443,12 @@ Specify the serial device it is connected to (e.g. /dev/ttya).",  /* to_doc */
   NULL,                                /* sections_end */
   OPS_MAGIC                    /* to_magic */
 };
+#endif /* Use remote.  */
 
 void
 _initialize_remote ()
 {
+#if !defined(DONT_USE_REMOTE)
   add_target (&remote_ops);
-}
 #endif
+}
This page took 0.03502 seconds and 4 git commands to generate.