Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / u-boot / tools / gdb / remote.c
diff --git a/qemu/roms/u-boot/tools/gdb/remote.c b/qemu/roms/u-boot/tools/gdb/remote.c
new file mode 100644 (file)
index 0000000..f368104
--- /dev/null
@@ -0,0 +1,916 @@
+/*
+ * taken from gdb/remote.c
+ *
+ * I am only interested in the write to memory stuff - everything else
+ * has been ripped out
+ *
+ * all the copyright notices etc have been left in
+ */
+
+/* enough so that it will compile */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+/*nicked from gcc..*/
+
+#ifndef alloca
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else /* not GNU C.  */
+#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi)
+#include <alloca.h>
+#else /* not sparc */
+#if defined (MSDOS) && !defined (__TURBOC__)
+#include <malloc.h>
+#else /* not MSDOS, or __TURBOC__ */
+#if defined(_AIX)
+#include <malloc.h>
+ #pragma alloca
+#else /* not MSDOS, __TURBOC__, or _AIX */
+#ifdef __hpux
+#endif /* __hpux */
+#endif /* not _AIX */
+#endif /* not MSDOS, or __TURBOC__ */
+#endif /* not sparc.  */
+#endif /* not GNU C.  */
+#ifdef __cplusplus
+extern "C" {
+#endif
+    void* alloca(size_t);
+#ifdef __cplusplus
+}
+#endif
+#endif /* alloca not defined.  */
+
+
+#include "serial.h"
+#include "error.h"
+#include "remote.h"
+#define REGISTER_BYTES 0
+#define fprintf_unfiltered fprintf
+#define fprintf_filtered fprintf
+#define fputs_unfiltered fputs
+#define fputs_filtered fputs
+#define fputc_unfiltered fputc
+#define fputc_filtered fputc
+#define printf_unfiltered printf
+#define printf_filtered printf
+#define puts_unfiltered puts
+#define puts_filtered puts
+#define putchar_unfiltered putchar
+#define putchar_filtered putchar
+#define fputstr_unfiltered(a,b,c) fputs((a), (c))
+#define gdb_stdlog stderr
+#define SERIAL_READCHAR(fd,timo)       serialreadchar((fd), (timo))
+#define SERIAL_WRITE(fd, addr, len)    serialwrite((fd), (addr), (len))
+#define error Error
+#define perror_with_name Perror
+#define gdb_flush fflush
+#define max(a,b) (((a)>(b))?(a):(b))
+#define min(a,b) (((a)<(b))?(a):(b))
+#define target_mourn_inferior() {}
+#define ULONGEST unsigned long
+#define CORE_ADDR unsigned long
+
+static int putpkt (char *);
+static int putpkt_binary(char *, int);
+static void getpkt (char *, int);
+
+static int remote_debug = 0, remote_register_buf_size = 0, watchdog = 0;
+
+int remote_desc = -1, remote_timeout = 10;
+
+static void
+fputstrn_unfiltered(char *s, int n, int x, FILE *fp)
+{
+    while (n-- > 0)
+       fputc(*s++, fp);
+}
+
+void
+remote_reset(void)
+{
+    SERIAL_WRITE(remote_desc, "+", 1);
+}
+
+void
+remote_continue(void)
+{
+    putpkt("c");
+}
+
+/* Remote target communications for serial-line targets in custom GDB protocol
+   Copyright 1988, 91, 92, 93, 94, 95, 96, 97, 98, 1999
+   Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+/* *INDENT-OFF* */
+/* Remote communication protocol.
+
+   A debug packet whose contents are <data>
+   is encapsulated for transmission in the form:
+
+       $ <data> # CSUM1 CSUM2
+
+       <data> must be ASCII alphanumeric and cannot include characters
+       '$' 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.
+       the hex digits 0-9,a-f are used.
+
+   Receiver responds with:
+
+       +       - if CSUM is correct and ready for next packet
+       -       - if CSUM is incorrect
+
+   <data> is as follows:
+   Most values are encoded in ascii hex digits.  Signal numbers are according
+   to the numbering in target.h.
+
+       Request         Packet
+
+       set thread      Hct...          Set thread for subsequent operations.
+                                       c = 'c' for thread used in step and
+                                       continue; t... can be -1 for all
+                                       threads.
+                                       c = 'g' for thread used in other
+                                       operations.  If zero, pick a thread,
+                                       any thread.
+       reply           OK              for success
+                       ENN             for an error.
+
+       read registers  g
+       reply           XX....X         Each byte of register data
+                                       is described by two hex digits.
+                                       Registers are in the internal order
+                                       for GDB, and the bytes in a register
+                                       are in the same order the machine uses.
+                       or ENN          for an error.
+
+       write regs      GXX..XX         Each byte of register data
+                                       is described by two hex digits.
+       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
+                                       if able to read only part of the data.
+                       or ENN          NN is errno
+
+       write mem       MAA..AA,LLLL:XX..XX
+                                       AA..AA is address,
+                                       LLLL is number of bytes,
+                                       XX..XX is data
+       reply           OK              for success
+                       ENN             for an error (this includes the case
+                                       where only part of the data was
+                                       written).
+
+       write mem       XAA..AA,LLLL:XX..XX
+        (binary)                       AA..AA is address,
+                                       LLLL is number of bytes,
+                                       XX..XX is binary data
+       reply           OK              for success
+                       ENN             for an error
+
+       continue        cAA..AA         AA..AA is address to resume
+                                       If AA..AA is omitted,
+                                       resume at same address.
+
+       step            sAA..AA         AA..AA is address to resume
+                                       If AA..AA is omitted,
+                                       resume at same address.
+
+       continue with   Csig;AA..AA     Continue with signal sig (hex signal
+       signal                          number).  If ;AA..AA is omitted,
+                                       resume at same address.
+
+       step with       Ssig;AA..AA     Like 'C' but step not continue.
+       signal
+
+       last signal     ?               Reply the current reason for stopping.
+                                       This is the same reply as is generated
+                                       for step or cont : SAA where AA is the
+                                       signal number.
+
+       detach          D               Reply OK.
+
+       There is no immediate reply to step or cont.
+       The reply comes when the machine stops.
+       It is           SAA             AA is the signal number.
+
+       or...           TAAn...:r...;n...:r...;n...:r...;
+                                       AA = signal number
+                                       n... = register number (hex)
+                                         r... = register contents
+                                       n... = `thread'
+                                         r... = thread process ID.  This is
+                                                a hex integer.
+                                       n... = other string not starting
+                                           with valid hex digit.
+                                         gdb should ignore this n,r pair
+                                         and go on to the next.  This way
+                                         we can extend the protocol.
+       or...           WAA             The process exited, and AA is
+                                       the exit status.  This is only
+                                       applicable for certains sorts of
+                                       targets.
+       or...           XAA             The process terminated with signal
+                                       AA.
+       or (obsolete)   NAA;tttttttt;dddddddd;bbbbbbbb
+                                       AA = signal number
+                                       tttttttt = address of symbol "_start"
+                                       dddddddd = base of data section
+                                       bbbbbbbb = base of bss  section.
+                                       Note: only used by Cisco Systems
+                                       targets.  The difference between this
+                                       reply and the "qOffsets" query is that
+                                       the 'N' packet may arrive spontaneously
+                                       whereas the 'qOffsets' is a query
+                                       initiated by the host debugger.
+       or...           OXX..XX XX..XX  is hex encoding of ASCII data. This
+                                       can happen at any time while the
+                                       program is running and the debugger
+                                       should continue to wait for
+                                       'W', 'T', etc.
+
+       thread alive    TXX             Find out if the thread XX is alive.
+       reply           OK              thread is still alive
+                       ENN             thread is dead
+
+       remote restart  RXX             Restart the remote server
+
+       extended ops    !               Use the extended remote protocol.
+                                       Sticky -- only needs to be set once.
+
+       kill request    k
+
+       toggle debug    d               toggle debug flag (see 386 & 68k stubs)
+       reset           r               reset -- see sparc stub.
+       reserved        <other>         On other requests, the stub should
+                                       ignore the request and send an empty
+                                       response ($#<checksum>).  This way
+                                       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 character is an ASCII encoding giving a repeat count which
+       stands for that many repititions of the character preceding the '*'.
+       The encoding is n+29, yielding a printable character where n >=3
+       (which is where rle starts to win).  Don't use an n > 126.
+
+       So
+       "0* " means the same as "0000".  */
+/* *INDENT-ON* */
+
+/* This variable (available to the user via "set remotebinarydownload")
+   dictates whether downloads are sent in binary (via the 'X' packet).
+   We assume that the stub can, and attempt to do it. This will be cleared if
+   the stub does not understand it. This switch is still needed, though
+   in cases when the packet is supported in the stub, but the connection
+   does not allow it (i.e., 7-bit serial connection only). */
+static int remote_binary_download = 1;
+
+/* Have we already checked whether binary downloads work? */
+static int remote_binary_checked;
+
+/* 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(N) (((N)-32)/2)
+
+/* 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).  */
+/* Round up PBUFSIZ to hold all the registers, at least.  */
+#define        PBUFSIZ ((REGISTER_BYTES > MAXBUFBYTES (400)) \
+                ? (REGISTER_BYTES * 2 + 32) \
+                : 400)
+
+
+/* This variable sets the number of bytes to be written to the target
+   in a single packet.  Normally PBUFSIZ is satisfactory, but some
+   targets need smaller values (perhaps because the receiving end
+   is slow).  */
+
+static int remote_write_size = 0x7fffffff;
+
+/* This variable sets the number of bits in an address that are to be
+   sent in a memory ("M" or "m") packet.  Normally, after stripping
+   leading zeros, the entire address would be sent. This variable
+   restricts the address to REMOTE_ADDRESS_SIZE bits.  HISTORY: The
+   initial implementation of remote.c restricted the address sent in
+   memory packets to ``host::sizeof long'' bytes - (typically 32
+   bits).  Consequently, for 64 bit targets, the upper 32 bits of an
+   address was never sent.  Since fixing this bug may cause a break in
+   some remote targets this variable is principly provided to
+   facilitate backward compatibility. */
+
+static int remote_address_size;
+
+/* Convert hex digit A to a number.  */
+
+static int
+fromhex (int a)
+{
+  if (a >= '0' && a <= '9')
+    return a - '0';
+  else if (a >= 'a' && a <= 'f')
+    return a - 'a' + 10;
+  else if (a >= 'A' && a <= 'F')
+    return a - 'A' + 10;
+  else {
+    error ("Reply contains invalid hex digit %d", a);
+    return -1;
+  }
+}
+
+/* Convert number NIB to a hex digit.  */
+
+static int
+tohex (int nib)
+{
+  if (nib < 10)
+    return '0' + nib;
+  else
+    return 'a' + nib - 10;
+}
+
+/* Return the number of hex digits in num.  */
+
+static int
+hexnumlen (ULONGEST num)
+{
+  int i;
+
+  for (i = 0; num != 0; i++)
+    num >>= 4;
+
+  return max (i, 1);
+}
+
+/* Set BUF to the hex digits representing NUM.  */
+
+static int
+hexnumstr (char *buf, ULONGEST num)
+{
+  int i;
+  int len = hexnumlen (num);
+
+  buf[len] = '\0';
+
+  for (i = len - 1; i >= 0; i--)
+    {
+      buf[i] = "0123456789abcdef"[(num & 0xf)];
+      num >>= 4;
+    }
+
+  return len;
+}
+
+/* Mask all but the least significant REMOTE_ADDRESS_SIZE bits. */
+
+static CORE_ADDR
+remote_address_masked (CORE_ADDR addr)
+{
+  if (remote_address_size > 0
+      && remote_address_size < (sizeof (ULONGEST) * 8))
+    {
+      /* Only create a mask when that mask can safely be constructed
+        in a ULONGEST variable. */
+      ULONGEST mask = 1;
+      mask = (mask << remote_address_size) - 1;
+      addr &= mask;
+    }
+  return addr;
+}
+
+/* Determine whether the remote target supports binary downloading.
+   This is accomplished by sending a no-op memory write of zero length
+   to the target at the specified address. It does not suffice to send
+   the whole packet, since many stubs strip the eighth bit and subsequently
+   compute a wrong checksum, which causes real havoc with remote_write_bytes.
+
+   NOTE: This can still lose if the serial line is not eight-bit clean. In
+   cases like this, the user should clear "remotebinarydownload". */
+static void
+check_binary_download (CORE_ADDR addr)
+{
+  if (remote_binary_download && !remote_binary_checked)
+    {
+      char *buf = alloca (PBUFSIZ);
+      char *p;
+      remote_binary_checked = 1;
+
+      p = buf;
+      *p++ = 'X';
+      p += hexnumstr (p, (ULONGEST) addr);
+      *p++ = ',';
+      p += hexnumstr (p, (ULONGEST) 0);
+      *p++ = ':';
+      *p = '\0';
+
+      putpkt_binary (buf, (int) (p - buf));
+      getpkt (buf, 0);
+
+      if (buf[0] == '\0')
+       remote_binary_download = 0;
+    }
+
+  if (remote_debug)
+    {
+      if (remote_binary_download)
+       fprintf_unfiltered (gdb_stdlog,
+                           "binary downloading suppported by target\n");
+      else
+       fprintf_unfiltered (gdb_stdlog,
+                           "binary downloading NOT suppported by target\n");
+    }
+}
+
+/* Write memory data directly to the remote machine.
+   This does not inform the data cache; the data cache uses this.
+   MEMADDR is the address in the remote memory space.
+   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.  */
+
+int
+remote_write_bytes (memaddr, myaddr, len)
+     CORE_ADDR memaddr;
+     char *myaddr;
+     int len;
+{
+  unsigned char *buf = alloca (PBUFSIZ);
+  int max_buf_size;            /* Max size of packet output buffer */
+  int origlen;
+  extern int verbose;
+
+  /* Verify that the target can support a binary download */
+  check_binary_download (memaddr);
+
+  /* Chop the transfer down if necessary */
+
+  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);
+
+  /* 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); */
+      memaddr = remote_address_masked (memaddr);
+      p = buf;
+      if (remote_binary_download)
+       {
+         *p++ = 'X';
+         todo = min (len, max_buf_size);
+       }
+      else
+       {
+         *p++ = 'M';
+         todo = min (len, max_buf_size / 2);   /* num bytes that will fit */
+       }
+
+      p += hexnumstr ((char *)p, (ULONGEST) memaddr);
+      *p++ = ',';
+
+      plen = p;                        /* remember where len field goes */
+      p += hexnumstr ((char *)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).  */
+      if (remote_binary_download)
+       {
+         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 ((char *)plen, (ULONGEST) i);
+             *plen++ = ':';
+           }
+       }
+      else
+       {
+         for (i = 0; i < todo; i++)
+           {
+             *p++ = tohex ((myaddr[i] >> 4) & 0xf);
+             *p++ = tohex (myaddr[i] & 0xf);
+           }
+         *p = '\0';
+       }
+
+      putpkt_binary ((char *)buf, (int) (p - buf));
+      getpkt ((char *)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;
+       }
+
+      /* 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;
+
+      if (verbose)
+       putc('.', stderr);
+    }
+  return origlen;
+}
+
+/* Stuff for dealing with the packets which are part of this protocol.
+   See comment at top of file for details.  */
+
+/* Read a single character from the remote end, masking it down to 7 bits. */
+
+static int
+readchar (int timeout)
+{
+  int ch;
+
+  ch = SERIAL_READCHAR (remote_desc, timeout);
+
+  switch (ch)
+    {
+    case SERIAL_EOF:
+      error ("Remote connection closed");
+    case SERIAL_ERROR:
+      perror_with_name ("Remote communication error");
+    case SERIAL_TIMEOUT:
+      return ch;
+    default:
+      return ch & 0x7f;
+    }
+}
+
+static int
+putpkt (buf)
+     char *buf;
+{
+  return putpkt_binary (buf, strlen (buf));
+}
+
+/* Send a packet to the remote machine, with error checking.  The data
+   of the packet is in BUF.  The string in BUF can be at most  PBUFSIZ - 5
+   to account for the $, # and checksum, and for a possible /0 if we are
+   debugging (remote_debug) and want to print the sent packet as a string */
+
+static int
+putpkt_binary (buf, cnt)
+     char *buf;
+     int cnt;
+{
+  int i;
+  unsigned char csum = 0;
+  char *buf2 = alloca (PBUFSIZ);
+  char *junkbuf = alloca (PBUFSIZ);
+
+  int ch;
+  int tcount = 0;
+  char *p;
+
+  /* Copy the packet into buffer BUF2, encapsulating it
+     and giving it a checksum.  */
+
+  if (cnt > BUFSIZ - 5)                /* Prosanity check */
+    abort ();
+
+  p = buf2;
+  *p++ = '$';
+
+  for (i = 0; i < cnt; i++)
+    {
+      csum += buf[i];
+      *p++ = buf[i];
+    }
+  *p++ = '#';
+  *p++ = tohex ((csum >> 4) & 0xf);
+  *p++ = tohex (csum & 0xf);
+
+  /* Send it over and over until we get a positive ack.  */
+
+  while (1)
+    {
+      int started_error_output = 0;
+
+      if (remote_debug)
+       {
+         *p = '\0';
+         fprintf_unfiltered (gdb_stdlog, "Sending packet: ");
+         fputstrn_unfiltered (buf2, p - buf2, 0, gdb_stdlog);
+         fprintf_unfiltered (gdb_stdlog, "...");
+         gdb_flush (gdb_stdlog);
+       }
+      if (SERIAL_WRITE (remote_desc, buf2, p - buf2))
+       perror_with_name ("putpkt: write failed");
+
+      /* read until either a timeout occurs (-2) or '+' is read */
+      while (1)
+       {
+         ch = readchar (remote_timeout);
+
+         if (remote_debug)
+           {
+             switch (ch)
+               {
+               case '+':
+               case SERIAL_TIMEOUT:
+               case '$':
+                 if (started_error_output)
+                   {
+                     putchar_unfiltered ('\n');
+                     started_error_output = 0;
+                   }
+               }
+           }
+
+         switch (ch)
+           {
+           case '+':
+             if (remote_debug)
+               fprintf_unfiltered (gdb_stdlog, "Ack\n");
+             return 1;
+           case SERIAL_TIMEOUT:
+             tcount++;
+             if (tcount > 3)
+               return 0;
+             break;            /* Retransmit buffer */
+           case '$':
+             {
+               /* 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)
+               {
+                 if (!started_error_output)
+                   {
+                     started_error_output = 1;
+                     fprintf_unfiltered (gdb_stdlog, "putpkt: Junk: ");
+                   }
+                 fputc_unfiltered (ch & 0177, gdb_stdlog);
+               }
+             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
+    }
+}
+
+/* Come here after finding the start of the frame.  Collect the rest
+   into BUF, verifying the checksum, length, and handling run-length
+   compression.  Returns 0 on any error, 1 on success.  */
+
+static int
+read_frame (char *buf)
+{
+  unsigned char csum;
+  char *bp;
+  int c;
+
+  csum = 0;
+  bp = buf;
+
+  while (1)
+    {
+      c = readchar (remote_timeout);
+
+      switch (c)
+       {
+       case SERIAL_TIMEOUT:
+         if (remote_debug)
+           fputs_filtered ("Timeout in mid-packet, retrying\n", gdb_stdlog);
+         return 0;
+       case '$':
+         if (remote_debug)
+           fputs_filtered ("Saw new packet start in middle of old one\n",
+                           gdb_stdlog);
+         return 0;             /* Start a new packet, count retries */
+       case '#':
+         {
+           unsigned char pktcsum;
+
+           *bp = '\000';
+
+           pktcsum = fromhex (readchar (remote_timeout)) << 4;
+           pktcsum |= fromhex (readchar (remote_timeout));
+
+           if (csum == pktcsum)
+             {
+               return 1;
+             }
+
+           if (remote_debug)
+             {
+               fprintf_filtered (gdb_stdlog,
+                             "Bad checksum, sentsum=0x%x, csum=0x%x, buf=",
+                                 pktcsum, csum);
+               fputs_filtered (buf, gdb_stdlog);
+               fputs_filtered ("\n", gdb_stdlog);
+             }
+           return 0;
+         }
+       case '*':               /* Run length encoding */
+         csum += c;
+         c = readchar (remote_timeout);
+         csum += c;
+         c = c - ' ' + 3;      /* Compute repeat count */
+
+         if (c > 0 && c < 255 && bp + c - 1 < buf + PBUFSIZ - 1)
+           {
+             memset (bp, *(bp - 1), c);
+             bp += c;
+             continue;
+           }
+
+         *bp = '\0';
+         printf_filtered ("Repeat count %d too large for buffer: ", c);
+         puts_filtered (buf);
+         puts_filtered ("\n");
+         return 0;
+       default:
+         if (bp < buf + PBUFSIZ - 1)
+           {
+             *bp++ = c;
+             csum += c;
+             continue;
+           }
+
+         *bp = '\0';
+         puts_filtered ("Remote packet too long: ");
+         puts_filtered (buf);
+         puts_filtered ("\n");
+
+         return 0;
+       }
+    }
+}
+
+/* Read a packet from the remote machine, with error checking, and
+   store it in BUF.  BUF is expected to be of size PBUFSIZ.  If
+   FOREVER, wait forever rather than timing out; this is used while
+   the target is executing user code.  */
+
+static void
+getpkt (buf, forever)
+     char *buf;
+     int forever;
+{
+  int c;
+  int tries;
+  int timeout;
+  int val;
+
+  strcpy (buf, "timeout");
+
+  if (forever)
+    {
+      timeout = watchdog > 0 ? watchdog : -1;
+    }
+
+  else
+    timeout = remote_timeout;
+
+#define MAX_TRIES 3
+
+  for (tries = 1; tries <= MAX_TRIES; tries++)
+    {
+      /* 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.  */
+
+      /* Note that we will only wait forever prior to the start of a packet.
+        After that, we expect characters to arrive at a brisk pace.  They
+        should show up within remote_timeout intervals.  */
+
+      do
+       {
+         c = readchar (timeout);
+
+         if (c == SERIAL_TIMEOUT)
+           {
+             if (forever)      /* Watchdog went off.  Kill the target. */
+               {
+                 target_mourn_inferior ();
+                 error ("Watchdog has expired.  Target detached.\n");
+               }
+             if (remote_debug)
+               fputs_filtered ("Timed out.\n", gdb_stdlog);
+             goto retry;
+           }
+       }
+      while (c != '$');
+
+      /* We've found the start of a packet, now collect the data.  */
+
+      val = read_frame (buf);
+
+      if (val == 1)
+       {
+         if (remote_debug)
+           {
+             fprintf_unfiltered (gdb_stdlog, "Packet received: ");
+             fputstr_unfiltered (buf, 0, gdb_stdlog);
+             fprintf_unfiltered (gdb_stdlog, "\n");
+           }
+         SERIAL_WRITE (remote_desc, "+", 1);
+         return;
+       }
+
+      /* Try the whole thing again.  */
+    retry:
+      SERIAL_WRITE (remote_desc, "-", 1);
+    }
+
+  /* We have tried hard enough, and just can't receive the packet.  Give up. */
+
+  printf_unfiltered ("Ignoring packet error, continuing...\n");
+  SERIAL_WRITE (remote_desc, "+", 1);
+}