* inftarg.c (child_thread_alive): New function to see if a
[deliverable/binutils-gdb.git] / gdb / remote.c
index 8debf22b170c29fecbebc4daff2a3d48f6f8eda2..8e59d4cab1e0f9e65809e3c72c38b2644a8cf6e3 100644 (file)
@@ -1,5 +1,5 @@
 /* Remote target communications for serial-line targets in custom GDB protocol
-   Copyright 1988, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+   Copyright 1988, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
 
 This file is part of GDB.
 
@@ -38,10 +38,21 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
        -       - if CSUM is incorrect
 
    <data> is as follows:
-   All values are encoded in ascii hex digits.
+   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.
@@ -78,7 +89,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
                                        where only part of the data was
                                        written).
 
-       cont            cAA..AA         AA..AA is address to resume
+       continue        cAA..AA         AA..AA is address to resume
                                        If AA..AA is omitted,
                                        resume at same address.
 
@@ -86,6 +97,12 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
                                        If AA..AA is omitted,
                                        resume at same address.
 
+       continue with   Csig;AA         Continue with signal sig (hex signal
+       signal                          number).
+
+       step with       Ssig;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
@@ -93,16 +110,31 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
        There is no immediate reply to step or cont.
        The reply comes when the machine stops.
-       It is           SAA             AA is the "signal number"
+       It is           SAA             AA is the signal number.
 
-       or...           TAAn...:r...;n:r...;n...:r...;
+       or...           TAAn...:r...;n...:r...;n...:r...;
                                        AA = signal number
-                                       n... = register number
-                                       r... = register contents
+                                       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...           Otext           Send text to stdout.  This can happen
+                                       at any time while the program is
+                                       running and the debugger should
+                                       continue to wait for 'W', 'T', etc.
+
        kill request    k
 
        toggle debug    d               toggle debug flag (see 386 & 68k stubs)
@@ -122,8 +154,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
        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
-       console output  Otext           Send text to stdout.  Only comes from
-                                       remote target.
 
        Responses can be run-length encoded to save space.  A '*' means that
        the next character is an ASCII encoding giving a repeat count which
@@ -147,6 +177,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "gdbcmd.h"
 #include "objfiles.h"
 #include "gdb-stabs.h"
+#include "thread.h"
 
 #include "dcache.h"
 
@@ -159,71 +190,56 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 /* Prototypes for local functions */
 
-static int
-remote_write_bytes PARAMS ((CORE_ADDR memaddr, unsigned char *myaddr, int len));
+static int remote_write_bytes PARAMS ((CORE_ADDR memaddr,
+                                      char *myaddr, int len));
 
-static int
-remote_read_bytes PARAMS ((CORE_ADDR memaddr, unsigned char *myaddr, int len));
+static int remote_read_bytes PARAMS ((CORE_ADDR memaddr,
+                                     char *myaddr, int len));
 
-static void
-remote_files_info PARAMS ((struct target_ops *ignore));
+static void remote_files_info PARAMS ((struct target_ops *ignore));
 
-static int
-remote_xfer_memory PARAMS ((CORE_ADDR memaddr, char *myaddr, int len,
-                           int should_write, struct target_ops *target));
+static int remote_xfer_memory PARAMS ((CORE_ADDR memaddr, char *myaddr,
+                                      int len, int should_write,
+                                      struct target_ops *target));
 
-static void 
-remote_prepare_to_store PARAMS ((void));
+static void remote_prepare_to_store PARAMS ((void));
 
-static void
-remote_fetch_registers PARAMS ((int regno));
+static void remote_fetch_registers PARAMS ((int regno));
 
-static void
-remote_resume PARAMS ((int pid, int step, enum target_signal siggnal));
+static void remote_resume PARAMS ((int pid, int step,
+                                  enum target_signal siggnal));
 
-static int
-remote_start_remote PARAMS ((char *dummy));
+static int remote_start_remote PARAMS ((char *dummy));
 
-static void
-remote_open PARAMS ((char *name, int from_tty));
+static void remote_open PARAMS ((char *name, int from_tty));
 
-static void
-remote_close PARAMS ((int quitting));
+static void remote_close PARAMS ((int quitting));
 
-static void
-remote_store_registers PARAMS ((int regno));
+static void remote_store_registers PARAMS ((int regno));
 
-static void
-getpkt PARAMS ((char *buf, int forever));
+static void getpkt PARAMS ((char *buf, int forever));
 
-static void
-putpkt PARAMS ((char *buf));
+static int putpkt PARAMS ((char *buf));
 
-static void
-remote_send PARAMS ((char *buf));
+static void remote_send PARAMS ((char *buf));
 
-static int
-readchar PARAMS ((int timeout));
+static int readchar PARAMS ((int timeout));
 
 static int remote_wait PARAMS ((int pid, struct target_waitstatus *status));
 
-static int
-tohex PARAMS ((int nib));
+static void remote_kill PARAMS ((void));
 
-static int
-fromhex PARAMS ((int a));
+static int tohex PARAMS ((int nib));
 
-static void
-remote_detach PARAMS ((char *args, int from_tty));
+static int fromhex PARAMS ((int a));
 
-static void
-remote_interrupt PARAMS ((int signo));
+static void remote_detach PARAMS ((char *args, int from_tty));
 
-static void
-remote_interrupt_twice PARAMS ((int signo));
+static void remote_interrupt PARAMS ((int signo));
 
-static void
-interrupt_query PARAMS ((void));
+static void remote_interrupt_twice PARAMS ((int signo));
+
+static void interrupt_query PARAMS ((void));
 
 extern struct target_ops remote_ops;   /* Forward decl */
 
@@ -231,11 +247,8 @@ extern struct target_ops remote_ops;       /* Forward decl */
    Unless this is going though some terminal server or multiplexer or
    other form of hairy serial connection, I would think 2 seconds would
    be plenty.  */
-static int remote_timeout = 2;
 
-#if 0
-int icache;
-#endif
+static int remote_timeout = 2;
 
 /* Descriptor for I/O to remote machine.  Initialize it to NULL so that
    remote_open knows that we don't have a file open when the program
@@ -266,6 +279,57 @@ serial_t remote_desc = NULL;
    doesn't support 'P', the only consequence is some unnecessary traffic.  */
 static int stub_supports_P = 1;
 
+\f
+/* These are the threads which we last sent to the remote system.  -1 for all
+   or -2 for not sent yet.  */
+int general_thread;
+int cont_thread;
+
+static void
+set_thread (th, gen)
+     int th;
+     int gen;
+{
+  char buf[PBUFSIZ];
+  int state = gen ? general_thread : cont_thread;
+  if (state == th)
+    return;
+  buf[0] = 'H';
+  buf[1] = gen ? 'g' : 'c';
+  if (th == 42000)
+    {
+      buf[2] = '0';
+      buf[3] = '\0';
+    }
+  else if (th < 0)
+    sprintf (&buf[2], "-%x", -th);
+  else
+    sprintf (&buf[2], "%x", th);
+  putpkt (buf);
+  getpkt (buf, 0);
+  if (gen)
+    general_thread = th;
+  else
+    cont_thread = th;
+}
+\f
+/*   Return nonzero if the thread TH is still alive on the remote system.  */
+
+static int
+remote_thread_alive (th)
+     int th;
+{
+  char buf[PBUFSIZ];
+
+  buf[0] = 'T';
+  if (th < 0)
+    sprintf (&buf[1], "-%x", -th);
+  else
+    sprintf (&buf[1], "%x", th);
+  putpkt (buf);
+  getpkt (buf, 0);
+  return (buf[0] == 'O' && buf[1] == 'K');
+}
 \f
 /* Clean up connection to a remote debugger.  */
 
@@ -284,7 +348,7 @@ remote_close (quitting)
 static void
 get_offsets ()
 {
-  unsigned char buf[PBUFSIZ];
+  char buf[PBUFSIZ];
   int nvals;
   CORE_ADDR text_addr, data_addr, bss_addr;
   struct section_offsets *offs;
@@ -318,12 +382,6 @@ get_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
@@ -345,16 +403,17 @@ remote_start_remote (dummy)
   immediate_quit = 1;          /* Allow user to interrupt it */
 
   /* Ack any packet which the remote side has already sent.  */
-
   SERIAL_WRITE (remote_desc, "+", 1);
 
+  /* Let the stub know that we want it to return the thread.  */
+  set_thread (-1, 0);
+
   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;
 }
 
@@ -369,8 +428,7 @@ remote_open (name, from_tty)
      int from_tty;
 {
   if (name == 0)
-    error (
-"To open a remote debug connection, you need to specify what serial\n\
+    error ("To open a remote debug connection, you need to specify what serial\n\
 device is attached to the remote system (e.g. /dev/ttya).");
 
   target_preopen (from_tty);
@@ -392,6 +450,7 @@ device is attached to the remote system (e.g. /dev/ttya).");
        }
     }
 
+
   SERIAL_RAW (remote_desc);
 
   /* If there is something sitting in the buffer we might take it as a
@@ -411,12 +470,8 @@ device is attached to the remote system (e.g. /dev/ttya).");
      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();
+  general_thread = -2;
+  cont_thread = -2;
 
   /* Without this, some commands which require an active target (such as kill)
      won't work.  This variable serves (at least) double duty as both the pid
@@ -425,7 +480,13 @@ device is attached to the remote system (e.g. /dev/ttya).");
      variables, especially since GDB will someday have a notion of debugging
      several processes.  */
 
-  inferior_pid = -1;
+  inferior_pid = 42000;
+  /* 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();
 }
 
 /* remote_detach()
@@ -460,7 +521,7 @@ fromhex (a)
   else if (a >= 'a' && a <= 'f')
     return a - 'a' + 10;
   else
-    error ("Reply contains invalid hex digit");
+    error ("Reply contains invalid hex digit %d", a);
 }
 
 /* Convert number NIB to a hex digit.  */
@@ -477,6 +538,9 @@ tohex (nib)
 \f
 /* Tell the remote machine to resume.  */
 
+static enum target_signal last_sent_signal = TARGET_SIGNAL_0;
+int last_sent_step;
+
 static void
 remote_resume (pid, step, siggnal)
      int pid, step;
@@ -484,18 +548,25 @@ remote_resume (pid, step, siggnal)
 {
   char buf[PBUFSIZ];
 
-  if (siggnal)
-    {
-      target_terminal_ours_for_output ();
-      printf_filtered
-       ("Can't send signals to a remote system.  %s not sent.\n",
-        target_signal_to_name (siggnal));
-      target_terminal_inferior ();
-    }
+  if (pid == -1)
+    set_thread (inferior_pid, 0);
+  else
+    set_thread (pid, 0);
 
   dcache_flush (remote_dcache);
 
-  strcpy (buf, step ? "s": "c");
+  last_sent_signal = siggnal;
+  last_sent_step = step;
+
+  if (siggnal != TARGET_SIGNAL_0)
+    {
+      buf[0] = step ? 'S' : 'C';
+      buf[1] = tohex (((int)siggnal >> 4) & 0xf);
+      buf[2] = tohex ((int)siggnal & 0xf);
+      buf[3] = '\0';
+    }
+  else
+    strcpy (buf, step ? "s": "c");
 
   putpkt (buf);
 }
@@ -547,6 +618,9 @@ Give up (and stop debugging it)? "))
   target_terminal_inferior ();
 }
 
+/* If nonzero, ignore the next kill.  */
+int kill_kludge;
+
 /* Wait until the remote machine stops, then return,
    storing status in STATUS just as `wait' would.
    Returns "pid" (though it's not clear what, if anything, that
@@ -558,6 +632,7 @@ remote_wait (pid, status)
      struct target_waitstatus *status;
 {
   unsigned char buf[PBUFSIZ];
+  int thread_num = -1;
 
   status->kind = TARGET_WAITKIND_EXITED;
   status->value.integer = 0;
@@ -593,35 +668,50 @@ remote_wait (pid, status)
            while (*p)
              {
                unsigned char *p1;
+               char *p_temp;
 
-               regno = strtol (p, &p1, 16); /* Read the register number */
+               regno = strtol (p, &p_temp, 16); /* Read the register number */
+               p1 = (unsigned char *)p_temp;
 
                if (p1 == p)
-                 warning ("Remote sent badly formed register number: %s\nPacket: '%s'\n",
-                          p1, buf);
-
-               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);
-
-               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;
+                   p1 = (unsigned char *) strchr (p, ':');
+                   if (p1 == NULL)
+                     warning ("Malformed packet (missing colon): %s\n\
+Packet: '%s'\n",
+                              p, buf);
+                   if (strncmp (p, "thread", p1 - p) == 0)
+                     {
+                       thread_num = strtol (++p1, &p_temp, 16);
+                       p = (unsigned char *)p_temp;
+                     }
+                 }
+               else
+                 {
+                   p = p1;
+
+                   if (*p++ != ':')
+                     warning ("Malformed packet (missing colon): %s\n\
+Packet: '%s'\n",
+                              p, buf);
+
+                   if (regno >= NUM_REGS)
+                     warning ("Remote sent bad register number %d: %s\n\
+Packet: '%s'\n",
+                              regno, p, 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);
              }
          }
          /* fall through */
@@ -630,22 +720,59 @@ remote_wait (pid, status)
          status->value.sig = (enum target_signal)
            (((fromhex (buf[1])) << 4) + (fromhex (buf[2])));
 
-         return 0;
+         goto got_status;
        case 'W':               /* Target exited */
          {
            /* The remote process exited.  */
            status->kind = TARGET_WAITKIND_EXITED;
            status->value.integer = (fromhex (buf[1]) << 4) + fromhex (buf[2]);
-           return 0;
+           goto got_status;
          }
+       case 'X':
+         status->kind = TARGET_WAITKIND_SIGNALLED;
+         status->value.sig = (enum target_signal)
+           (((fromhex (buf[1])) << 4) + (fromhex (buf[2])));
+         kill_kludge = 1;
+
+         goto got_status;
        case 'O':               /* Console output */
-         fputs_filtered (buf + 1, gdb_stdout);
+         fputs_filtered ((char *)(buf + 1), gdb_stdout);
          continue;
+       case '\0':
+         if (last_sent_signal != TARGET_SIGNAL_0)
+           {
+             /* Zero length reply means that we tried 'S' or 'C' and
+                the remote system doesn't support it.  */
+             target_terminal_ours_for_output ();
+             printf_filtered
+               ("Can't send signals to this remote system.  %s not sent.\n",
+                target_signal_to_name (last_sent_signal));
+             last_sent_signal = TARGET_SIGNAL_0;
+             target_terminal_inferior ();
+
+             strcpy (buf, last_sent_step ? "s" : "c");
+             putpkt (buf);
+             continue;
+           }
+         /* else fallthrough */
        default:
          warning ("Invalid remote reply: %s", buf);
          continue;
        }
     }
+ got_status:
+  if (thread_num != -1)
+    {
+      /* Initial thread value can only be acquired via wait, so deal with
+        this marker which is used before the first thread value is
+        acquired.  */
+      if (inferior_pid == 42000)
+       {
+         inferior_pid = thread_num;
+         add_thread (inferior_pid);
+       }
+      return thread_num;
+    }
   return inferior_pid;
 }
 
@@ -664,6 +791,8 @@ remote_fetch_registers (regno)
   char *p;
   char regs[REGISTER_BYTES];
 
+  set_thread (inferior_pid, 1);
+
   sprintf (buf, "g");
   remote_send (buf);
 
@@ -737,6 +866,8 @@ remote_store_registers (regno)
   int i;
   char *p;
 
+  set_thread (inferior_pid, 1);
+
   if (regno >= 0 && stub_supports_P)
     {
       /* Try storing a single register.  */
@@ -781,16 +912,18 @@ remote_store_registers (regno)
   remote_send (buf);
 }
 
-#if 0
-
-/* Use of the data cache is disabled because it loses for looking at
+/* 
+   Use of the data cache *used* to be 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).  */
+   would perhaps be one way to fix it.  Another idea would be to use the
+   executable file for the text segment (for all SEC_CODE sections?
+   For all SEC_READONLY sections?).  This has problems if you want to
+   actually see what the memory contains (e.g. self-modifying code,
+   clobbered memory, user downloaded the wrong thing).  
+
+   Because it speeds so much up, it's now enabled, if you're playing
+   with registers you turn it of (set remotecache 0)
+*/
 
 /* Read a word from remote address ADDR and return it.
    This goes through the data cache.  */
@@ -799,19 +932,6 @@ static int
 remote_fetch_word (addr)
      CORE_ADDR addr;
 {
-#if 0
-  if (icache)
-    {
-      extern CORE_ADDR text_start, text_end;
-
-      if (addr >= text_start && addr < text_end)
-       {
-         int buffer;
-         xfer_core_file (addr, &buffer, sizeof (int));
-         return buffer;
-       }
-    }
-#endif
   return dcache_fetch (remote_dcache, addr);
 }
 
@@ -825,7 +945,7 @@ remote_store_word (addr, 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.
@@ -838,7 +958,7 @@ remote_store_word (addr, word)
 static int
 remote_write_bytes (memaddr, myaddr, len)
      CORE_ADDR memaddr;
-     unsigned char *myaddr;
+     char *myaddr;
      int len;
 {
   char buf[PBUFSIZ];
@@ -886,7 +1006,7 @@ remote_write_bytes (memaddr, myaddr, len)
 static int
 remote_read_bytes (memaddr, myaddr, len)
      CORE_ADDR memaddr;
-     unsigned char *myaddr;
+     char *myaddr;
      int len;
 {
   char buf[PBUFSIZ];
@@ -941,36 +1061,10 @@ remote_xfer_memory(memaddr, myaddr, len, should_write, target)
      int should_write;
      struct target_ops *target;                        /* ignored */
 {
-  int xfersize;
-  int bytes_xferred;
-  int total_xferred = 0;
-
-  while (len > 0)
-    {
-      if (len > MAXBUFBYTES)
-       xfersize = MAXBUFBYTES;
-      else
-       xfersize = len;
-
-      if (should_write)
-        bytes_xferred = remote_write_bytes (memaddr,
-                                           (unsigned char *)myaddr, xfersize);
-      else
-       bytes_xferred = remote_read_bytes (memaddr,
-                                          (unsigned char *)myaddr, xfersize);
-
-      /* If we get an error, we are done xferring.  */
-      if (bytes_xferred == 0)
-       break;
-
-      memaddr += bytes_xferred;
-      myaddr  += bytes_xferred;
-      len     -= bytes_xferred;
-      total_xferred += bytes_xferred;
-    }
-  return total_xferred;
+  return dcache_xfer_memory (remote_dcache, memaddr, myaddr, len, should_write);
 }
 
+   
 #if 0
 /* Enable after 4.12.  */
 
@@ -1086,7 +1180,6 @@ static void
 remote_send (buf)
      char *buf;
 {
-
   putpkt (buf);
   getpkt (buf, 0);
 
@@ -1097,7 +1190,7 @@ remote_send (buf)
 /* Send a packet to the remote machine, with error checking.
    The data of the packet is in BUF.  */
 
-static void
+static int
 putpkt (buf)
      char *buf;
 {
@@ -1106,6 +1199,7 @@ putpkt (buf)
   char buf2[PBUFSIZ];
   int cnt = strlen (buf);
   int ch;
+  int tcount = 0;
   char *p;
 
   /* Copy the packet into buffer BUF2, encapsulating it
@@ -1146,7 +1240,7 @@ putpkt (buf)
        {
          ch = readchar (remote_timeout);
 
-         if (remote_debug)
+         if (remote_debug)
            {
              switch (ch)
                {
@@ -1155,7 +1249,7 @@ putpkt (buf)
                case '$':
                  if (started_error_output)
                    {
-                     putc_unfiltered ('\n');
+                     putchar_unfiltered ('\n');
                      started_error_output = 0;
                    }
                }
@@ -1166,12 +1260,15 @@ putpkt (buf)
            case '+':
              if (remote_debug)
                printf_unfiltered("Ack\n");
-             return;
+             return 1;
            case SERIAL_TIMEOUT:
+             tcount ++;
+             if (tcount > 3)
+               return 0;
              break;            /* Retransmit buffer */
            case '$':
              {
-               unsigned char junkbuf[PBUFSIZ];
+               char junkbuf[PBUFSIZ];
 
              /* It's probably an old response, and we're out of sync.  Just
                 gobble up the packet and ignore it.  */
@@ -1186,7 +1283,7 @@ putpkt (buf)
                      started_error_output = 1;
                      printf_unfiltered ("putpkt: Junk: ");
                    }
-                 putc_unfiltered (ch & 0177);
+                 putchar_unfiltered (ch & 0177);
                }
              continue;
            }
@@ -1249,11 +1346,13 @@ read_frame (buf)
            if (csum == pktcsum)
              return 1;
 
-           printf_filtered ("Bad checksum, sentsum=0x%x, csum=0x%x, buf=",
-                            pktcsum, csum);
-           puts_filtered (buf);
-           puts_filtered ("\n");
-
+           if (remote_debug) 
+             {
+               printf_filtered ("Bad checksum, sentsum=0x%x, csum=0x%x, buf=",
+                                pktcsum, csum);
+               puts_filtered (buf);
+               puts_filtered ("\n");
+             }
            return 0;
          }
        case '*':               /* Run length encoding */
@@ -1262,7 +1361,8 @@ read_frame (buf)
          csum += c;
          c = c - ' ' + 3;      /* Compute repeat count */
 
-         if (bp + c - 1 < buf + PBUFSIZ - 1)
+
+         if (c > 0 && c < 255 && bp + c - 1 < buf + PBUFSIZ - 1)
            {
              memset (bp, *(bp - 1), c);
              bp += c;
@@ -1309,12 +1409,21 @@ getpkt (buf, forever)
   int timeout;
   int val;
 
+  strcpy (buf,"timeout");
+
   if (forever)
-    timeout = -1;
+    {
+#ifdef MAINTENANCE_CMDS
+      timeout = watchdog > 0 ? watchdog : -1;
+#else
+      timeout = -1;
+#endif
+    }
+
   else
     timeout = remote_timeout;
 
-#define MAX_TRIES 10
+#define MAX_TRIES 3
 
   for (tries = 1; tries <= MAX_TRIES; tries++)
     {
@@ -1332,6 +1441,13 @@ getpkt (buf, forever)
 
          if (c == SERIAL_TIMEOUT)
            {
+#ifdef MAINTENANCE_CMDS
+             if (forever)      /* Watchdog went off.  Kill the target. */
+               {
+                 target_mourn_inferior ();
+                 error ("Watchdog has expired.  Target detached.\n");
+               }
+#endif
              if (remote_debug)
                puts_filtered ("Timed out.\n");
              goto retry;
@@ -1352,7 +1468,7 @@ getpkt (buf, forever)
        }
 
       /* Try the whole thing again.  */
-retry:
+    retry:
       SERIAL_WRITE (remote_desc, "-", 1);
     }
 
@@ -1365,7 +1481,19 @@ retry:
 static void
 remote_kill ()
 {
-  putpkt ("k");
+  /* For some mysterious reason, wait_for_inferior calls kill instead of
+     mourn after it gets TARGET_WAITKIND_SIGNALLED.  Work around it.  */
+  if (kill_kludge)
+    {
+      kill_kludge = 0;
+      target_mourn_inferior ();
+      return;
+    }
+
+  /* Use catch_errors so the user can quit from gdb even when we aren't on
+     speaking terms with the remote system.  */
+  catch_errors (putpkt, "k", "", RETURN_MASK_ERROR);
+
   /* Don't wait for it to die.  I'm not really sure it matters whether
      we do or not.  For the existing stubs, kill is a noop.  */
   target_mourn_inferior ();
@@ -1460,6 +1588,8 @@ Specify the serial device it is connected to (e.g. /dev/ttya).",  /* to_doc */
   remote_mourn,                        /* to_mourn_inferior */
   0,                           /* to_can_run */
   0,                           /* to_notice_signals */
+  remote_thread_alive,         /* to_thread_alive */
+  0,                           /* to_stop */
   process_stratum,             /* to_stratum */
   NULL,                                /* to_next */
   1,                           /* to_has_all_memory */
This page took 0.033317 seconds and 4 git commands to generate.