]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdb/remote.c
import gdb-1999-09-21
[thirdparty/binutils-gdb.git] / gdb / remote.c
index c697bd45501a832e7cc5a6b799dd3916afa5c474..645ef2231046f84cc2ffcca4c33e2cb30fd1031a 100644 (file)
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.  */
-/* *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* */
-
-
 
+/* See the GDB User Guide for details of the GDB remote protocol. */
 
 #include "defs.h"
 #include "gdb_string.h"
 #include "objfiles.h"
 #include "gdb-stabs.h"
 #include "gdbthread.h"
+#include "remote.h"
 
 #include "dcache.h"
 
 #endif
 
 #include "event-loop.h"
+#include "event-top.h"
 
 #include <signal.h>
 #include "serial.h"
@@ -280,6 +102,7 @@ static void remote_close PARAMS ((int quitting));
 static void remote_store_registers PARAMS ((int regno));
 
 static void remote_mourn PARAMS ((void));
+static void remote_async_mourn PARAMS ((void));
 
 static void extended_remote_restart PARAMS ((void));
 
@@ -365,19 +188,11 @@ static void record_currthread PARAMS ((int currthread));
 
 extern int fromhex PARAMS ((int a));
 
-extern void getpkt PARAMS ((char *buf, int forever));
-
-extern int putpkt PARAMS ((char *buf));
-
 static int putpkt_binary PARAMS ((char *buf, int cnt));
 
-void remote_console_output PARAMS ((char *));
-
 static void check_binary_download PARAMS ((CORE_ADDR addr));
 
-#if __STDC__
 struct packet_config;
-#endif
 
 static void show_packet_config_cmd PARAMS ((struct packet_config * config));
 
@@ -401,6 +216,13 @@ static void set_remote_protocol_P_packet_cmd PARAMS ((char *args,
 static void show_remote_protocol_P_packet_cmd PARAMS ((char *args,
                                                       int from_tty));
 
+static void set_remote_protocol_Z_packet_cmd PARAMS ((char *args,
+                                                     int from_tty,
+                                             struct cmd_list_element * c));
+
+static void show_remote_protocol_Z_packet_cmd PARAMS ((char *args,
+                                                      int from_tty));
+
 
 
 
@@ -447,17 +269,6 @@ static serial_t remote_desc = NULL;
    to denote that the target is in kernel mode.  */
 static int cisco_kernel_mode = 0;
 
-/* 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)
@@ -558,7 +369,7 @@ set_packet_config_cmd (config, c)
       config->support = PACKET_SUPPORT_UNKNOWN;
     }
   else
-    fatal ("Bad enum value");
+    internal_error ("Bad enum value");
 }
 
 static void
@@ -657,6 +468,54 @@ show_remote_protocol_P_packet_cmd (args, from_tty)
   show_packet_config_cmd (&remote_protocol_P);
 }
 
+/* Should we try the 'Z' (set breakpoint) request?  */
+
+static struct packet_config remote_protocol_Z;
+
+static void
+set_remote_protocol_Z_packet_cmd (args, from_tty, c)
+     char *args;
+     int from_tty;
+     struct cmd_list_element *c;
+{
+  set_packet_config_cmd (&remote_protocol_Z, c);
+}
+
+static void
+show_remote_protocol_Z_packet_cmd (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  show_packet_config_cmd (&remote_protocol_Z);
+}
+
+/* Should we try the 'X' (remote binary download) packet?
+
+   This variable (available to the user via "set remote X-packet")
+   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 struct packet_config remote_protocol_binary_download;
+
+static void
+set_remote_protocol_binary_download_cmd (char *args,
+                                        int from_tty,
+                                        struct cmd_list_element *c)
+{
+  set_packet_config_cmd (&remote_protocol_binary_download, c);
+}
+
+static void
+show_remote_protocol_binary_download_cmd (char *args,
+                                         int from_tty)
+{
+  show_packet_config_cmd (&remote_protocol_binary_download);
+}
+
 
 /* Tokens for use by the asynchronous signal handlers for SIGINT */
 PTR sigint_remote_twice_token;
@@ -1636,13 +1495,8 @@ get_offsets ()
   if (symfile_objfile == NULL)
     return;
 
-  offs = 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));
+  offs = (struct section_offsets *) alloca (SIZEOF_SECTION_OFFSETS);
+  memcpy (offs, symfile_objfile->section_offsets, SIZEOF_SECTION_OFFSETS);
 
   ANOFFSET (offs, SECT_OFF_TEXT) = text_addr;
 
@@ -1729,8 +1583,10 @@ remote_cisco_section_offsets (text_addr, data_addr, bss_addr,
       sprintf_vma (tmp + strlen (tmp), bss_addr);
       fprintf_filtered (gdb_stdlog, tmp);
       fprintf_filtered (gdb_stdlog,
-                       "Reloc offset: text = 0x%x data = 0x%x bss = 0x%x\n",
-                   (long) *text_offs, (long) *data_offs, (long) *bss_offs);
+                       "Reloc offset: text = 0x%s data = 0x%s bss = 0x%s\n",
+                       paddr_nz (*text_offs),
+                       paddr_nz (*data_offs),
+                       paddr_nz (*bss_offs));
     }
 
   return 0;
@@ -1742,7 +1598,7 @@ remote_cisco_section_offsets (text_addr, data_addr, bss_addr,
  * Relocate the symbol file for a remote target. 
  */
 
-static void
+void
 remote_cisco_objfile_relocate (text_off, data_off, bss_off)
      bfd_signed_vma text_off;
      bfd_signed_vma data_off;
@@ -1756,15 +1612,8 @@ remote_cisco_objfile_relocate (text_off, data_off, bss_off)
          broken for xcoff, dwarf, sdb-coff, etc.  But there is no
          simple canonical representation for this stuff.  */
 
-      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))));
+      offs = (struct section_offsets *) alloca (SIZEOF_SECTION_OFFSETS);
+      memcpy (offs, symfile_objfile->section_offsets, SIZEOF_SECTION_OFFSETS);
 
       ANOFFSET (offs, SECT_OFF_TEXT) = text_off;
       ANOFFSET (offs, SECT_OFF_DATA) = data_off;
@@ -1902,13 +1751,14 @@ serial device is attached to the remote system (e.g. /dev/ttya).");
   push_target (target);                /* Switch to using remote target now */
 
   init_packet_config (&remote_protocol_P);
-
+  init_packet_config (&remote_protocol_Z);
+  
   general_thread = -2;
   continue_thread = -2;
 
   /* Force remote_write_bytes to check whether target supports
      binary downloading. */
-  remote_binary_checked = 0;
+  init_packet_config (&remote_protocol_binary_download);
 
   /* Without this, some commands which require an active target (such
      as kill) won't work.  This variable serves (at least) double duty
@@ -1986,24 +1836,27 @@ serial device is attached to the remote system (e.g. /dev/ttya).");
      event loop.  Set things up so that when there is an event on the
      file descriptor, the event loop will call fetch_inferior_event,
      which will do the proper analysis to determine what happened. */
-  if (async_p)
-    add_file_handler (remote_desc->fd, (file_handler_func *) fetch_inferior_event, 0);
+  if (async_p && SERIAL_CAN_ASYNC_P (remote_desc))
+    SERIAL_ASYNC (remote_desc, inferior_event_handler, 0);
+  if (remote_debug && SERIAL_IS_ASYNC_P (remote_desc))
+    fputs_unfiltered ("Async mode.\n", gdb_stdlog);
 
   push_target (target);                /* Switch to using remote target now */
 
   init_packet_config (&remote_protocol_P);
+  init_packet_config (&remote_protocol_Z);
 
   general_thread = -2;
   continue_thread = -2;
 
   /* Force remote_write_bytes to check whether target supports
      binary downloading. */
-  remote_binary_checked = 0;
+  init_packet_config (&remote_protocol_binary_download);
 
   /* If running asynchronously, set things up for telling the target
      to use the extended protocol. This will happen only after the
      target has been connected to, in fetch_inferior_event. */
-  if (extended_p && async_p)
+  if (extended_p && SERIAL_IS_ASYNC_P (remote_desc))
     add_continuation (set_extended_protocol, NULL);
 
   /* Without this, some commands which require an active target (such
@@ -2022,13 +1875,13 @@ serial device is attached to the remote system (e.g. /dev/ttya).");
                     RETURN_MASK_ALL))
     {
       /* Unregister the file descriptor from the event loop. */
-      if (async_p)
-       delete_file_handler (remote_desc->fd);
+      if (SERIAL_IS_ASYNC_P (remote_desc))
+       SERIAL_ASYNC (remote_desc, NULL, 0);
       pop_target ();
       return;
     }
 
-  if (!async_p)
+  if (!SERIAL_IS_ASYNC_P (remote_desc))
     {
       if (extended_p)
        {
@@ -2074,6 +1927,7 @@ remote_detach (args, from_tty)
   pop_target ();
   if (from_tty)
     puts_filtered ("Ending remote debugging.\n");
+
 }
 
 /* Same as remote_detach, but with async support. */
@@ -2092,8 +1946,8 @@ remote_async_detach (args, from_tty)
   remote_send (buf);
 
   /* Unregister the file descriptor from the event loop. */
-  if (async_p)
-    delete_file_handler (remote_desc->fd);
+  if (SERIAL_IS_ASYNC_P (remote_desc))
+    SERIAL_ASYNC (remote_desc, NULL, 0);
 
   pop_target ();
   if (from_tty)
@@ -2197,7 +2051,7 @@ remote_async_resume (pid, step, siggnal)
      command, because it is also called by handle_inferior_event. So
      we make sure that we don't do the initialization for sync
      execution more than once. */
-  if (async_p && !target_executing)
+  if (SERIAL_IS_ASYNC_P (remote_desc) && !target_executing)
     {
       target_executing = 1;
 
@@ -2289,9 +2143,9 @@ cleanup_sigint_signal_handler ()
 {
   signal (SIGINT, handle_sigint);
   if (sigint_remote_twice_token)
-    delete_async_signal_handler ((async_signal_handler **) & sigint_remote_twice_token);
+    delete_async_signal_handler ((struct async_signal_handler **) & sigint_remote_twice_token);
   if (sigint_remote_token)
-    delete_async_signal_handler ((async_signal_handler **) & sigint_remote_token);
+    delete_async_signal_handler ((struct async_signal_handler **) & sigint_remote_token);
 }
 
 /* Send ^C to target to halt it.  Target will respond, and send us a
@@ -2523,7 +2377,7 @@ Packet: '%s'\n",
 
            if (symfile_objfile == NULL)
              {
-               warning ("Relocation packet recieved with no symbol file.  \
+               warning ("Relocation packet received with no symbol file.  \
 Packet Dropped");
                goto got_status;
              }
@@ -2617,10 +2471,10 @@ remote_async_wait (pid, status)
     {
       unsigned char *p;
 
-      if (!async_p)
+      if (!SERIAL_IS_ASYNC_P (remote_desc))
        ofunc = signal (SIGINT, remote_interrupt);
       getpkt ((char *) buf, 1);
-      if (!async_p)
+      if (!SERIAL_IS_ASYNC_P (remote_desc))
        signal (SIGINT, ofunc);
 
       /* This is a hook for when we need to do something (perhaps the
@@ -3103,41 +2957,52 @@ remote_address_masked (addr)
    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". */
+   NOTE: This can still lose if the serial line is not eight-bit
+   clean. In cases like this, the user should clear "remote
+   X-packet". */
+
 static void
 check_binary_download (addr)
      CORE_ADDR addr;
 {
-  if (remote_binary_download && !remote_binary_checked)
+  switch (remote_protocol_binary_download.support)
     {
-      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;
-    }
+    case PACKET_DISABLE:
+      break;
+    case PACKET_ENABLE:
+      break;
+    case PACKET_SUPPORT_UNKNOWN:
+      {
+       char *buf = alloca (PBUFSIZ);
+       char *p;
+       
+       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 (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");
+       if (buf[0] == '\0')
+         {
+           if (remote_debug)
+             fprintf_unfiltered (gdb_stdlog,
+                                 "binary downloading NOT suppported by target\n");
+           remote_protocol_binary_download.support = PACKET_DISABLE;
+         }
+       else
+         {
+           if (remote_debug)
+             fprintf_unfiltered (gdb_stdlog,
+                                 "binary downloading suppported by target\n");
+           remote_protocol_binary_download.support = PACKET_ENABLE;
+         }
+       break;
+      }
     }
 }
 
@@ -3182,15 +3047,18 @@ remote_write_bytes (memaddr, myaddr, len)
       /* sprintf (buf, "M%lx,%x:", (unsigned long) memaddr, todo); */
       memaddr = remote_address_masked (memaddr);
       p = buf;
-      if (remote_binary_download)
+      switch (remote_protocol_binary_download.support)
        {
+       case PACKET_ENABLE:
          *p++ = 'X';
          todo = min (len, max_buf_size);
-       }
-      else
-       {
+         break;
+       case PACKET_DISABLE:
          *p++ = 'M';
          todo = min (len, max_buf_size / 2);   /* num bytes that will fit */
+         break;
+       case PACKET_SUPPORT_UNKNOWN:
+         internal_error ("remote_write_bytes: bad switch");
        }
 
       p += hexnumstr (p, (ULONGEST) memaddr);
@@ -3204,50 +3072,57 @@ remote_write_bytes (memaddr, myaddr, len)
       /* 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 (plen, (ULONGEST) i);
-             *plen++ = ':';
-           }
-       }
-      else
+      switch (remote_protocol_binary_download.support)
        {
-         for (i = 0; i < todo; i++)
-           {
-             *p++ = tohex ((myaddr[i] >> 4) & 0xf);
-             *p++ = tohex (myaddr[i] & 0xf);
-           }
-         *p = '\0';
+       case PACKET_ENABLE:
+         {
+           int escaped = 0;
+           for (i = 0;
+                (i < todo) && (i + escaped) < (max_buf_size - 2);
+                i++)
+             {
+               switch (myaddr[i] & 0xff)
+                 {
+                 case '$':
+                 case '#':
+                 case 0x7d:
+                   /* These must be escaped */
+                   escaped++;
+                   *p++ = 0x7d;
+                   *p++ = (myaddr[i] & 0xff) ^ 0x20;
+                   break;
+                 default:
+                   *p++ = myaddr[i] & 0xff;
+                   break;
+                 }
+             }
+           
+           if (i < todo)
+             {
+               /* Escape chars have filled up the buffer prematurely, 
+                  and we have actually sent fewer bytes than planned.
+                  Fix-up the length field of the packet.  */
+               
+               /* FIXME: will fail if new len is a shorter string than 
+                  old len.  */
+               
+               plen += hexnumstr (plen, (ULONGEST) i);
+               *plen++ = ':';
+             }
+           break;
+         }
+       case PACKET_DISABLE:
+         {
+           for (i = 0; i < todo; i++)
+             {
+               *p++ = tohex ((myaddr[i] >> 4) & 0xf);
+               *p++ = tohex (myaddr[i] & 0xf);
+             }
+           *p = '\0';
+           break;
+         }
+       case PACKET_SUPPORT_UNKNOWN:
+         internal_error ("remote_write_bytes: bad switch");
        }
 
       putpkt_binary (buf, (int) (p - buf));
@@ -3566,7 +3441,7 @@ putpkt_binary (buf, cnt)
          *p = '\0';
          fprintf_unfiltered (gdb_stdlog, "Sending packet: ");
          fputstrn_unfiltered (buf2, p - buf2, 0, gdb_stdlog);
-         fprintf_unfiltered (gdb_stdlog, "...", buf2);
+         fprintf_unfiltered (gdb_stdlog, "...");
          gdb_flush (gdb_stdlog);
        }
       if (SERIAL_WRITE (remote_desc, buf2, p - buf2))
@@ -3642,33 +3517,6 @@ putpkt_binary (buf, cnt)
 
 static int remote_cisco_mode;
 
-static void
-remote_cisco_expand (src, dest)
-     char *src;
-     char *dest;
-{
-  int i;
-  int repeat;
-
-  do
-    {
-      if (*src == '*')
-       {
-         repeat = (fromhex (src[1]) << 4) + fromhex (src[2]);
-         for (i = 0; i < repeat; i++)
-           {
-             *dest++ = *(src - 1);
-           }
-         src += 2;
-       }
-      else
-       {
-         *dest++ = *src;
-       }
-    }
-  while (*src++);
-}
-
 /* 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.  */
@@ -3709,16 +3557,7 @@ read_frame (buf)
            pktcsum |= fromhex (readchar (remote_timeout));
 
            if (csum == pktcsum)
-             {
-               if (remote_cisco_mode)  /* variant run-length-encoding */
-                 {
-                   char *tmp_buf = alloca (PBUFSIZ);
-
-                   remote_cisco_expand (buf, tmp_buf);
-                   strcpy (buf, tmp_buf);
-                 }
-               return 1;
-             }
+              return 1;
 
            if (remote_debug)
              {
@@ -3731,27 +3570,43 @@ read_frame (buf)
            return 0;
          }
        case '*':               /* Run length encoding */
-         if (remote_cisco_mode == 0)   /* variant run-length-encoding */
-           {
-             csum += c;
-             c = readchar (remote_timeout);
-             csum += c;
-             c = c - ' ' + 3;  /* Compute repeat count */
+          {
+           int repeat;
+           csum += c;
 
-             if (c > 0 && c < 255 && bp + c - 1 < buf + PBUFSIZ - 1)
-               {
-                 memset (bp, *(bp - 1), c);
-                 bp += c;
-                 continue;
-               }
+           if (remote_cisco_mode == 0)
+             {
+               c = readchar (remote_timeout);
+               csum += c;
+               repeat = c - ' ' + 3;   /* Compute repeat count */
+             }
+           else 
+             { 
+               /* Cisco's run-length encoding variant uses two 
+                  hex chars to represent the repeat count. */
+
+               c = readchar (remote_timeout);
+               csum += c;
+               repeat  = fromhex (c) << 4;
+               c = readchar (remote_timeout);
+               csum += c;
+               repeat += fromhex (c);
+             }
 
-             *bp = '\0';
-             printf_filtered ("Repeat count %d too large for buffer: ", c);
-             puts_filtered (buf);
-             puts_filtered ("\n");
-             return 0;
-           }
-         /* else fall thru to treat like default */
+           if (repeat > 0 && repeat <= 255 
+                && bp + repeat - 1 < buf + PBUFSIZ - 1)
+             {
+               memset (bp, *(bp - 1), repeat);
+               bp += c;
+               continue;
+             }
+
+           *bp = '\0';
+           printf_filtered ("Repeat count %d too large for buffer: ", repeat);
+           puts_filtered (buf);
+           puts_filtered ("\n");
+           return 0;
+         }
        default:
          if (bp < buf + PBUFSIZ - 1)
            {
@@ -3878,8 +3733,8 @@ static void
 remote_async_kill ()
 {
   /* Unregister the file descriptor from the event loop. */
-  if (async_p)
-    delete_file_handler (remote_desc->fd);
+  if (SERIAL_IS_ASYNC_P (remote_desc))
+    SERIAL_ASYNC (remote_desc, NULL, 0);
 
   /* For some mysterious reason, wait_for_inferior calls kill instead of
      mourn after it gets TARGET_WAITKIND_SIGNALLED.  Work around it.  */
@@ -3905,6 +3760,12 @@ remote_mourn ()
   remote_mourn_1 (&remote_ops);
 }
 
+static void
+remote_async_mourn ()
+{
+  remote_mourn_1 (&remote_async_ops);
+}
+
 static void
 extended_remote_mourn ()
 {
@@ -3971,8 +3832,8 @@ extended_remote_async_create_inferior (exec_file, args, env)
 
   /* If running asynchronously, register the target file descriptor
      with the event loop. */
-  if (async_p)
-    add_file_handler (remote_desc->fd, (file_handler_func *) fetch_inferior_event, 0);
+  if (async_p && SERIAL_CAN_ASYNC_P (remote_desc))
+    SERIAL_ASYNC (remote_desc, inferior_event_handler, 0);
 
   /* Now restart the remote server.  */
   extended_remote_restart ();
@@ -4032,7 +3893,52 @@ remote_insert_breakpoint (addr, contents_cache)
 {
 #ifdef REMOTE_BREAKPOINT
   int val;
+#endif  
+  int bp_size;
+
+  /* Try the "Z" packet if it is not already disabled.
+     If it succeeds, then set the support to PACKET_ENABLE.
+     If it fails, and the user has explicitly requested the Z support 
+     then report an error, otherwise, mark it disabled and go on. */
+  
+  if ((remote_protocol_Z.support == PACKET_ENABLE)
+      || (remote_protocol_Z.support == PACKET_SUPPORT_UNKNOWN)) 
+    {
+      char buf[PBUFSIZ], *p = buf;
+      
+      addr = remote_address_masked (addr);
+      *(p++) = 'Z';
+      *(p++) = '0';
+      *(p++) = ',';
+      p += hexnumstr (p, (ULONGEST) addr);
+      BREAKPOINT_FROM_PC (&addr, &bp_size);
+      sprintf (p, ",%d", bp_size);
+      
+      putpkt (buf);
+      getpkt (buf, 0);
+
+      if (buf[0] != '\0')
+       {
+         remote_protocol_Z.support = PACKET_ENABLE;
+         return (buf[0] == 'E');
+       }
+      
+      /* The stub does not support the 'Z' request.  If the user has
+         explicitly requested the Z support, or if the stub previously
+        said it supported the packet, this is an error,
+         otherwise, mark it disabled. */
+      
+      else if (remote_protocol_Z.support == PACKET_ENABLE)
+       {
+         error ("Protocol error: Z packet not recognized by stub");
+       }
+      else
+       {
+         remote_protocol_Z.support = PACKET_DISABLE;
+       }
+    }
 
+#ifdef REMOTE_BREAKPOINT  
   val = target_read_memory (addr, contents_cache, sizeof big_break_insn);
 
   if (val == 0)
@@ -4056,6 +3962,28 @@ remote_remove_breakpoint (addr, contents_cache)
      CORE_ADDR addr;
      char *contents_cache;
 {
+  int bp_size;
+
+  if ((remote_protocol_Z.support == PACKET_ENABLE)
+      || (remote_protocol_Z.support == PACKET_SUPPORT_UNKNOWN))
+    {
+      char buf[PBUFSIZ], *p = buf;
+      
+      *(p++) = 'z';
+      *(p++) = '0';
+      *(p++) = ',';
+
+      addr = remote_address_masked (addr);
+      p += hexnumstr (p, (ULONGEST) addr);
+      BREAKPOINT_FROM_PC (&addr, &bp_size);
+      sprintf (p, ",%d", bp_size);
+      
+      putpkt (buf);
+      getpkt (buf, 0);
+
+      return (buf[0] == 'E');
+    }
+
 #ifdef REMOTE_BREAKPOINT
   return target_write_memory (addr, contents_cache, sizeof big_break_insn);
 #else
@@ -4063,6 +3991,107 @@ remote_remove_breakpoint (addr, contents_cache)
 #endif /* REMOTE_BREAKPOINT */
 }
 
+#ifdef TARGET_HAS_HARDWARE_WATCHPOINTS
+int
+remote_insert_watchpoint (addr, len, type)
+     CORE_ADDR addr;
+     int len;
+     int type;
+{
+  char buf[PBUFSIZ], *p;
+
+  if (remote_protocol_Z.support == PACKET_DISABLE)
+    error ("Can't set hardware watchpoints without the 'Z' packet\n");
+  
+  sprintf (buf, "Z%x,", type + 2 );
+  p = strchr (buf, '\0');
+  addr = remote_address_masked (addr);
+  p += hexnumstr (p, (ULONGEST) addr);
+  sprintf (p, ",%x", len);
+  
+  putpkt (buf);
+  getpkt (buf, 0);
+
+  if (buf[0] == '\0' || buf [0] == 'E')
+    return -1;
+
+  return 0;
+}
+
+int
+remote_remove_watchpoint (addr, len, type)
+     CORE_ADDR addr;
+     int len;
+     int type;
+{
+  char buf[PBUFSIZ], *p;
+  
+  sprintf (buf, "z%x,", type + 2 );
+  p = strchr (buf, '\0');
+  addr = remote_address_masked (addr);
+  p += hexnumstr (p, (ULONGEST) addr);
+  sprintf (p, ",%x", len);
+  putpkt (buf);
+  getpkt (buf, 0);
+
+  if (buf[0] == '\0' || buf [0] == 'E')
+    return -1;
+
+  return 0;
+}
+
+int
+remote_insert_hw_breakpoint (addr, len)
+     CORE_ADDR addr;
+     int len;
+{
+  char buf[PBUFSIZ], *p = buf;
+      
+  if (remote_protocol_Z.support == PACKET_DISABLE)
+    error ("Can't set hardware breakpoints without the 'Z' packet\n");
+
+  *(p++) = 'Z';
+  *(p++) = '1';
+  *(p++) = ',';
+  
+  addr = remote_address_masked (addr);
+  p += hexnumstr (p, (ULONGEST) addr);
+  *p = '\0';
+
+  putpkt (buf);
+  getpkt (buf, 0);
+
+  if (buf[0] == '\0' || buf [0] == 'E')
+    return -1;
+
+  return 0;
+}
+
+int 
+remote_remove_hw_breakpoint (addr, len)
+     CORE_ADDR addr;
+     int len;
+{
+  char buf[PBUFSIZ], *p = buf;
+  
+  *(p++) = 'z';
+  *(p++) = '1';
+  *(p++) = ',';
+  
+  addr = remote_address_masked (addr);
+  p += hexnumstr (p, (ULONGEST) addr);
+  *p = '\0';
+
+  putpkt(buf);
+  getpkt (buf, 0);
+  
+  if (buf[0] == '\0' || buf [0] == 'E')
+    return -1;
+
+  return 0;
+}
+#endif
+
 /* Some targets are only capable of doing downloads, and afterwards
    they switch to the remote serial protocol.  This function provides
    a clean way to get from the download target to the remote target.
@@ -4196,8 +4225,8 @@ compare_sections_command (args, from_tty)
       for (target_crc = 0, tmp = &buf[1]; *tmp; tmp++)
        target_crc = target_crc * 16 + fromhex (*tmp);
 
-      printf_filtered ("Section %s, range 0x%08x -- 0x%08x: ",
-                      sectname, lma, lma + size);
+      printf_filtered ("Section %s, range 0x%s -- 0x%s: ",
+                      sectname, paddr (lma), paddr (lma + size));
       if (host_crc == target_crc)
        printf_filtered ("matched.\n");
       else
@@ -4225,7 +4254,6 @@ remote_query (query_type, buf, outbuf, bufsiz)
   int i;
   char *buf2 = alloca (PBUFSIZ);
   char *p2 = &buf2[0];
-  char *p = buf;
 
   if (!bufsiz)
     error ("null pointer to remote bufer size specified");
@@ -4286,6 +4314,68 @@ remote_query (query_type, buf, outbuf, bufsiz)
   return 0;
 }
 
+static void
+remote_rcmd (char *command,
+            struct gdb_file *outbuf)
+{
+  int i;
+  char *buf = alloca (PBUFSIZ);
+  char *p = buf;
+
+  if (!remote_desc)
+    error ("remote rcmd is only available after target open");
+
+  /* Send a NULL command across as an empty command */
+  if (command == NULL)
+    command = "";
+
+  /* The query prefix */
+  strcpy (buf, "qRcmd,");
+  p = strchr (buf, '\0');
+
+  if ((strlen (buf) + strlen (command) * 2 + 8/*misc*/) > PBUFSIZ)
+    error ("\"monitor\" command ``%s'' is too long\n", command);
+
+  /* Encode the actual command */
+  for (i = 0; command[i]; i++)
+    {
+      *p++ = tohex ((command[i] >> 4) & 0xf);
+      *p++ = tohex (command[i] & 0xf);
+    }
+  *p = '\0';
+
+  if (putpkt (buf) < 0)
+    error ("Communication problem with target\n");
+
+  /* get/display the response */
+  while (1)
+    {
+      /* XXX - see also tracepoint.c:remote_get_noisy_reply() */
+      buf[0] = '\0';
+      getpkt (buf, 0);
+      if (buf[0] == '\0')
+       error ("Target does not support this command\n");
+      if (buf[0] == 'O' && buf[1] != 'K')
+       {
+         remote_console_output (buf + 1); /* 'O' message from stub */
+         continue;
+       }
+      if (strcmp (buf, "OK") == 0)
+       break;
+      if (strlen (buf) == 3 && buf[0] == 'E'
+         && isdigit (buf[1]) && isdigit (buf[2]))
+       {
+         error ("Protocol error with Rcmd");
+       }
+      for (p = buf; p[0] != '\0' && p[1] != '\0'; p += 2)
+       {
+         char c = (fromhex (p[0]) << 4) + fromhex (p[1]);
+         fputc_unfiltered (c, outbuf);
+       }
+      break;
+    }
+}
+
 static void
 packet_command (args, from_tty)
      char *args;
@@ -4498,6 +4588,7 @@ Specify the serial device it is connected to (e.g. /dev/ttya).";
   remote_ops.to_find_new_threads = remote_threads_info;
   remote_ops.to_stop = remote_stop;
   remote_ops.to_query = remote_query;
+  remote_ops.to_rcmd = remote_rcmd;
   remote_ops.to_stratum = process_stratum;
   remote_ops.to_has_all_memory = 1;
   remote_ops.to_has_memory = 1;
@@ -4623,13 +4714,14 @@ device is attached to the remote system (e.g. host:port).");
   push_target (&remote_cisco_ops);     /* Switch to using cisco target now */
 
   init_packet_config (&remote_protocol_P);
+  init_packet_config (&remote_protocol_Z);
 
   general_thread = -2;
   continue_thread = -2;
 
   /* Force remote_write_bytes to check whether target supports
      binary downloading. */
-  remote_binary_checked = 0;
+  init_packet_config (&remote_protocol_binary_download);
 
   /* Without this, some commands which require an active target (such
      as kill) won't work.  This variable serves (at least) double duty
@@ -4751,7 +4843,6 @@ readsocket ()
 static int
 readtty ()
 {
-  int status;
   int tty_bytecount;
 
   /* First, read a buffer full from the terminal */
@@ -4826,7 +4917,7 @@ minitelnet ()
 
       FD_ZERO (&input);
       FD_SET (fileno (stdin), &input);
-      FD_SET (remote_desc->fd, &input);
+      FD_SET (DEPRECATED_SERIAL_FD (remote_desc), &input);
 
       status = select (tablesize, &input, 0, 0, 0);
       if ((status == -1) && (errno != EINTR))
@@ -4947,11 +5038,12 @@ Specify the serial device it is connected to (e.g. /dev/ttya).";
   remote_async_ops.to_remove_breakpoint = remote_remove_breakpoint;
   remote_async_ops.to_kill = remote_async_kill;
   remote_async_ops.to_load = generic_load;
-  remote_async_ops.to_mourn_inferior = remote_mourn;
+  remote_async_ops.to_mourn_inferior = remote_async_mourn;
   remote_async_ops.to_thread_alive = remote_thread_alive;
   remote_async_ops.to_find_new_threads = remote_threads_info;
   remote_async_ops.to_stop = remote_stop;
   remote_async_ops.to_query = remote_query;
+  remote_async_ops.to_rcmd = remote_rcmd;
   remote_async_ops.to_stratum = process_stratum;
   remote_async_ops.to_has_all_memory = 1;
   remote_async_ops.to_has_memory = 1;
@@ -5035,13 +5127,13 @@ _initialize_remote ()
 Remote protocol specific variables\n\
 Configure various remote-protocol specific variables such as\n\
 the packets being used",
-                 &remote_set_cmdlist, "remote ",
+                 &remote_set_cmdlist, "set remote ",
                  0/*allow-unknown*/, &setlist);
   add_prefix_cmd ("remote", class_maintenance, set_remote_cmd, "\
 Remote protocol specific variables\n\
 Configure various remote-protocol specific variables such as\n\
 the packets being used",
-                 &remote_show_cmdlist, "remote ",
+                 &remote_show_cmdlist, "show remote ",
                  0/*allow-unknown*/, &showlist);
 
   add_cmd ("compare-sections", class_obscure, compare_sections_command,
@@ -5088,11 +5180,20 @@ in a memory packet.\n",
                  &setlist),
      &showlist);
 
+  add_packet_config_cmd (&remote_protocol_binary_download,
+                        "X", "binary-download",
+                        set_remote_protocol_binary_download_cmd,
+                        show_remote_protocol_binary_download_cmd,
+                        &remote_set_cmdlist, &remote_show_cmdlist);
+#if 0
+  /* XXXX - should ``set remotebinarydownload'' be retained for
+     compatibility. */
   add_show_from_set
     (add_set_cmd ("remotebinarydownload", no_class,
                  var_boolean, (char *) &remote_binary_download,
                  "Set binary downloads.\n", &setlist),
      &showlist);
+#endif
 
   add_info ("remote-process", remote_info_process,
            "Query the remote system for process info.");
@@ -5101,4 +5202,9 @@ in a memory packet.\n",
                         set_remote_protocol_P_packet_cmd,
                         show_remote_protocol_P_packet_cmd,
                         &remote_set_cmdlist, &remote_show_cmdlist);
+
+  add_packet_config_cmd (&remote_protocol_Z, "Z", "breakpoint",
+                        set_remote_protocol_Z_packet_cmd,
+                        show_remote_protocol_Z_packet_cmd,
+                        &remote_set_cmdlist, &remote_show_cmdlist);
 }