Wed Jul 31 14:46:11 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
[deliverable/binutils-gdb.git] / gdb / remote.c
index 8e59d4cab1e0f9e65809e3c72c38b2644a8cf6e3..65caedb62990302964c15e41ed1adb4f41643eb8 100644 (file)
@@ -1,5 +1,5 @@
 /* Remote target communications for serial-line targets in custom GDB protocol
-   Copyright 1988, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+   Copyright 1988, 1991, 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
 
 This file is part of GDB.
 
@@ -15,7 +15,7 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 /* Remote communication protocol.
 
@@ -108,6 +108,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
                                        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.
@@ -130,11 +132,20 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
                                        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
+        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)
@@ -165,7 +176,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
        "0* " means the same as "0000".  */
 
 #include "defs.h"
-#include <string.h>
+#include "gdb_string.h"
 #include <fcntl.h>
 #include "frame.h"
 #include "inferior.h"
@@ -173,11 +184,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "symfile.h"
 #include "target.h"
 #include "wait.h"
-#include "terminal.h"
+/*#include "terminal.h"*/
 #include "gdbcmd.h"
 #include "objfiles.h"
 #include "gdb-stabs.h"
-#include "thread.h"
+#include "gdbthread.h"
 
 #include "dcache.h"
 
@@ -213,10 +224,24 @@ static int remote_start_remote PARAMS ((char *dummy));
 
 static void remote_open PARAMS ((char *name, int from_tty));
 
+static void extended_remote_open PARAMS ((char *name, int from_tty));
+
+static void remote_open_1 PARAMS ((char *, int, struct target_ops *));
+
 static void remote_close PARAMS ((int quitting));
 
 static void remote_store_registers PARAMS ((int regno));
 
+static void remote_mourn PARAMS ((void));
+
+static void extended_remote_restart PARAMS ((void));
+
+static void extended_remote_mourn PARAMS ((void));
+
+static void extended_remote_create_inferior PARAMS ((char *, char *, char **));
+
+static void remote_mourn_1 PARAMS ((struct target_ops *));
+
 static void getpkt PARAMS ((char *buf, int forever));
 
 static int putpkt PARAMS ((char *buf));
@@ -241,14 +266,36 @@ static void remote_interrupt_twice PARAMS ((int signo));
 
 static void interrupt_query PARAMS ((void));
 
+static void set_thread PARAMS ((int, int));
+
+static int remote_thread_alive PARAMS ((int));
+
+static void get_offsets PARAMS ((void));
+
+static int read_frame PARAMS ((char *));
+
+static int remote_insert_breakpoint PARAMS ((CORE_ADDR, char *));
+
+static int remote_remove_breakpoint PARAMS ((CORE_ADDR, char *));
+
 extern struct target_ops remote_ops;   /* Forward decl */
+extern struct target_ops extended_remote_ops;  /* Forward decl */
 
 /* This was 5 seconds, which is a long time to sit and wait.
    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;
+/* Changed to allow option to set timeout value.
+   was static int remote_timeout = 2; */
+extern int remote_timeout;
+
+/* This variable chooses whether to send a ^C or a break when the user
+   requests program interruption.  Although ^C is usually what remote
+   systems expect, and that is the default here, sometimes a break is
+   preferable instead.  */
+
+static int remote_break;
 
 /* 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
@@ -275,6 +322,13 @@ serial_t remote_desc = NULL;
 #define        PBUFSIZ (REGISTER_BYTES * 2 + 32)
 #endif
 
+/* 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 = PBUFSIZ;
+
 /* Should we try the 'P' request?  If this is set to one when the stub
    doesn't support 'P', the only consequence is some unnecessary traffic.  */
 static int stub_supports_P = 1;
@@ -313,7 +367,7 @@ set_thread (th, gen)
     cont_thread = th;
 }
 \f
-/*   Return nonzero if the thread TH is still alive on the remote system.  */
+/*  Return nonzero if the thread TH is still alive on the remote system.  */
 
 static int
 remote_thread_alive (th)
@@ -330,6 +384,25 @@ remote_thread_alive (th)
   getpkt (buf, 0);
   return (buf[0] == 'O' && buf[1] == 'K');
 }
+
+/*  Restart the remote side; this is an extended protocol operation.  */
+
+static void
+extended_remote_restart ()
+{
+  char buf[PBUFSIZ];
+
+  /* Send the restart command; for reasons I don't understand the
+     remote side really expects a number after the "R".  */
+  buf[0] = 'R';
+  sprintf (&buf[1], "%x", 0);
+  putpkt (buf);
+
+  /* Now query for status so this looks just like we restarted
+     gdbserver from scratch.  */
+  putpkt ("?");
+  getpkt (buf, 0);
+}
 \f
 /* Clean up connection to a remote debugger.  */
 
@@ -420,12 +493,41 @@ remote_start_remote (dummy)
 /* Open a connection to a remote debugger.
    NAME is the filename used for communication.  */
 
+static void
+remote_open (name, from_tty)
+     char *name;
+     int from_tty;
+{
+  remote_open_1 (name, from_tty, &remote_ops);
+}
+
+/* Open a connection to a remote debugger using the extended
+   remote gdb protocol.  NAME is the filename used for communication.  */
+
+static void
+extended_remote_open (name, from_tty)
+     char *name;
+     int from_tty;
+{
+  char buf[PBUFSIZ];
+
+  /* Do the basic remote open stuff.  */
+  remote_open_1 (name, from_tty, &extended_remote_ops);
+
+  /* Now tell the remote that we're using the extended protocol.  */
+  putpkt ("!");
+  getpkt (buf, 0);
+
+}
+
+/* Generic code for opening a connection to a remote target.  */
 static DCACHE *remote_dcache;
 
 static void
-remote_open (name, from_tty)
+remote_open_1 (name, from_tty, target)
      char *name;
      int from_tty;
+     struct target_ops *target;
 {
   if (name == 0)
     error ("To open a remote debug connection, you need to specify what serial\n\
@@ -433,7 +535,7 @@ device is attached to the remote system (e.g. /dev/ttya).");
 
   target_preopen (from_tty);
 
-  unpush_target (&remote_ops);
+  unpush_target (target);
 
   remote_dcache = dcache_init (remote_read_bytes, remote_write_bytes);
 
@@ -463,7 +565,7 @@ device is attached to the remote system (e.g. /dev/ttya).");
       puts_filtered (name);
       puts_filtered ("\n");
     }
-  push_target (&remote_ops);   /* Switch to using remote target now */
+  push_target (target);        /* Switch to using remote target now */
 
   /* Start out by trying the 'P' request to set registers.  We set this each
      time that we open a new target so that if the user switches from one
@@ -489,22 +591,25 @@ device is attached to the remote system (e.g. /dev/ttya).");
     pop_target();
 }
 
-/* remote_detach()
-   takes a program previously attached to and detaches it.
-   We better not have left any breakpoints
-   in the program or it'll die when it hits one.
-   Close the open connection to the remote debugger.
-   Use this when you want to detach and do something else
-   with your gdb.  */
+/* This takes a program previously attached to and detaches it.  After
+   this is done, GDB can be used to debug some other program.  We
+   better not have left any breakpoints in the target program or it'll
+   die when it hits one.  */
 
 static void
 remote_detach (args, from_tty)
      char *args;
      int from_tty;
 {
+  char buf[PBUFSIZ];
+
   if (args)
     error ("Argument given to \"detach\" when remotely debugging.");
-  
+
+  /* Tell the remote target to detach.  */
+  strcpy (buf, "D");
+  remote_send (buf);
+
   pop_target ();
   if (from_tty)
     puts_filtered ("Ending remote debugging.\n");
@@ -520,7 +625,7 @@ fromhex (a)
     return a - '0';
   else if (a >= 'a' && a <= 'f')
     return a - 'a' + 10;
-  else
+  else 
     error ("Reply contains invalid hex digit %d", a);
 }
 
@@ -584,7 +689,11 @@ remote_interrupt (signo)
   if (remote_debug)
     printf_unfiltered ("remote_interrupt called\n");
 
-  SERIAL_WRITE (remote_desc, "\003", 1); /* Send a ^C */
+  /* Send a break or a ^C, depending on user preference.  */
+  if (remote_break)
+    SERIAL_SEND_BREAK (remote_desc);
+  else
+    SERIAL_WRITE (remote_desc, "\003", 1);
 }
 
 static void (*ofunc)();
@@ -670,19 +779,19 @@ remote_wait (pid, status)
                unsigned char *p1;
                char *p_temp;
 
-               regno = strtol (p, &p_temp, 16); /* Read the register number */
+               regno = strtol ((const char *) p, &p_temp, 16); /* Read the register number */
                p1 = (unsigned char *)p_temp;
 
                if (p1 == p)
                  {
-                   p1 = (unsigned char *) strchr (p, ':');
+                   p1 = (unsigned char *) strchr ((const char *) p, ':');
                    if (p1 == NULL)
                      warning ("Malformed packet (missing colon): %s\n\
 Packet: '%s'\n",
                               p, buf);
-                   if (strncmp (p, "thread", p1 - p) == 0)
+                   if (strncmp ((const char *) p, "thread", p1 - p) == 0)
                      {
-                       thread_num = strtol (++p1, &p_temp, 16);
+                       thread_num = strtol ((const char *) ++p1, &p_temp, 16);
                        p = (unsigned char *)p_temp;
                      }
                  }
@@ -696,7 +805,7 @@ Packet: '%s'\n",
                               p, buf);
 
                    if (regno >= NUM_REGS)
-                     warning ("Remote sent bad register number %d: %s\n\
+                     warning ("Remote sent bad register number %ld: %s\n\
 Packet: '%s'\n",
                               regno, p, buf);
 
@@ -736,7 +845,17 @@ Packet: '%s'\n",
 
          goto got_status;
        case 'O':               /* Console output */
-         fputs_filtered ((char *)(buf + 1), gdb_stdout);
+         for (p = buf + 1; *p; p +=2) 
+           {
+             char tb[2];
+             char c = fromhex (p[0]) * 16 + fromhex (p[1]);
+             tb[0] = c;
+             tb[1] = 0;
+             if (target_output_hook)
+               target_output_hook (tb);
+             else 
+               fputs_filtered (tb, gdb_stdout);
+           }
          continue;
        case '\0':
          if (last_sent_signal != TARGET_SIGNAL_0)
@@ -750,8 +869,8 @@ Packet: '%s'\n",
              last_sent_signal = TARGET_SIGNAL_0;
              target_terminal_inferior ();
 
-             strcpy (buf, last_sent_step ? "s" : "c");
-             putpkt (buf);
+             strcpy ((char *) buf, last_sent_step ? "s" : "c");
+             putpkt ((char *) buf);
              continue;
            }
          /* else fallthrough */
@@ -928,6 +1047,7 @@ remote_store_registers (regno)
 /* Read a word from remote address ADDR and return it.
    This goes through the data cache.  */
 
+#if 0  /* unused? */
 static int
 remote_fetch_word (addr)
      CORE_ADDR addr;
@@ -945,6 +1065,7 @@ remote_store_word (addr, word)
 {
   dcache_poke (remote_dcache, addr, word);
 }
+#endif /* 0 (unused?) */
 
 \f
 /* Write memory data directly to the remote machine.
@@ -964,33 +1085,46 @@ remote_write_bytes (memaddr, myaddr, len)
   char buf[PBUFSIZ];
   int i;
   char *p;
+  int done;
+  /* Chop the transfer down if necessary */
 
-  /* FIXME-32x64: Need a version of print_address_numeric which puts the
-     result in a buffer like sprintf.  */
-  sprintf (buf, "M%lx,%x:", (unsigned long) memaddr, len);
+  done = 0;
+  while (done < len)
+    {
+      int todo = len - done;
+      int cando = min(remote_write_size, PBUFSIZ) / 2 - 32; /* num bytes that will fit */
 
-  /* We send target system values byte by byte, in increasing byte addresses,
-     each byte encoded as two hex characters.  */
+      if (todo > cando)
+       todo = cando;
 
-  p = buf + strlen (buf);
-  for (i = 0; i < len; i++)
-    {
-      *p++ = tohex ((myaddr[i] >> 4) & 0xf);
-      *p++ = tohex (myaddr[i] & 0xf);
-    }
-  *p = '\0';
+      /* FIXME-32x64: Need a version of print_address_numeric which puts the
+        result in a buffer like sprintf.  */
+      sprintf (buf, "M%lx,%x:", (unsigned long) memaddr + done, todo);
 
-  putpkt (buf);
-  getpkt (buf, 0);
+      /* We send target system values byte by byte, in increasing byte addresses,
+        each byte encoded as two hex characters.  */
 
-  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;
+      p = buf + strlen (buf);
+      for (i = 0; i < todo; i++)
+       {
+         *p++ = tohex ((myaddr[i + done] >> 4) & 0xf);
+         *p++ = tohex (myaddr[i + done] & 0xf);
+       }
+      *p = '\0';
+
+      putpkt (buf);
+      getpkt (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;
+       }
+      done += todo;
     }
   return len;
 }
@@ -1012,40 +1146,54 @@ remote_read_bytes (memaddr, myaddr, len)
   char buf[PBUFSIZ];
   int i;
   char *p;
+  int done;
+  /* Chop transfer down if neccessary */
 
+#if 0
+  /* FIXME: This is wrong for larger packets */
   if (len > PBUFSIZ / 2 - 1)
     abort ();
-
-  /* FIXME-32x64: Need a version of print_address_numeric which puts the
-     result in a buffer like sprintf.  */
-  sprintf (buf, "m%lx,%x", (unsigned long) memaddr, len);
-  putpkt (buf);
-  getpkt (buf, 0);
-
-  if (buf[0] == 'E')
+#endif
+  done = 0;
+  while (done < len)
     {
-      /* 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;
-    }
+      int todo = len - done;
+      int cando = PBUFSIZ / 2 - 32; /* number of bytes that will fit. */
+      if (todo > cando)
+       todo = cando;
+
+      /* FIXME-32x64: Need a version of print_address_numeric which puts the
+        result in a buffer like sprintf.  */
+      sprintf (buf, "m%lx,%x", (unsigned long) memaddr + done, todo);
+      putpkt (buf);
+      getpkt (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;
+       }
 
   /* Reply describes memory byte by byte,
      each byte encoded as two hex characters.  */
 
-  p = buf;
-  for (i = 0; i < len; i++)
-    {
-      if (p[0] == 0 || p[1] == 0)
-       /* Reply is short.  This means that we were able to read only part
-          of what we wanted to.  */
-       break;
-      myaddr[i] = fromhex (p[0]) * 16 + fromhex (p[1]);
-      p += 2;
+      p = buf;
+      for (i = 0; i < todo; i++)
+       {
+         if (p[0] == 0 || p[1] == 0)
+           /* Reply is short.  This means that we were able to read only part
+              of what we wanted to.  */
+           return i + done;
+         myaddr[i + done] = fromhex (p[0]) * 16 + fromhex (p[1]);
+         p += 2;
+       }
+      done += todo;
     }
-  return i;
+  return len;
 }
 \f
 /* Read or write LEN bytes from inferior memory at MEMADDR, transferring
@@ -1205,7 +1353,7 @@ putpkt (buf)
   /* Copy the packet into buffer BUF2, encapsulating it
      and giving it a checksum.  */
 
-  if (cnt > sizeof(buf2) - 5)          /* Prosanity check */
+  if (cnt > (int) sizeof (buf2) - 5)           /* Prosanity check */
     abort();
 
   p = buf2;
@@ -1403,7 +1551,6 @@ getpkt (buf, forever)
      char *buf;
      int forever;
 {
-  char *bp;
   int c;
   int tries;
   int timeout;
@@ -1502,26 +1649,90 @@ remote_kill ()
 static void
 remote_mourn ()
 {
-  unpush_target (&remote_ops);
+  remote_mourn_1 (&remote_ops);
+}
+
+static void
+extended_remote_mourn ()
+{
+  /* We do _not_ want to mourn the target like this; this will
+     remove the extended remote target  from the target stack,
+     and the next time the user says "run" it'll fail. 
+
+     FIXME: What is the right thing to do here?  */
+#if 0
+  remote_mourn_1 (&extended_remote_ops);
+#endif
+}
+
+/* Worker function for remote_mourn.  */
+static void
+remote_mourn_1 (target)
+     struct target_ops *target;
+{
+  unpush_target (target);
   generic_mourn_inferior ();
 }
-\f
-#ifdef REMOTE_BREAKPOINT
 
+/* In the extended protocol we want to be able to do things like
+   "run" and have them basically work as expected.  So we need
+   a special create_inferior function. 
+
+   FIXME: One day add support for changing the exec file
+   we're debugging, arguments and an environment.  */
+
+static void
+extended_remote_create_inferior (exec_file, args, env)
+     char *exec_file;
+     char *args;
+     char **env;
+{
+  /* Rip out the breakpoints; we'll reinsert them after restarting
+     the remote server.  */
+  remove_breakpoints ();
+
+  /* Now restart the remote server.  */
+  extended_remote_restart ();
+
+  /* Now put the breakpoints back in.  This way we're safe if the
+     restart function works via a unix fork on the remote side.  */
+  insert_breakpoints ();
+
+  /* Clean up from the last time we were running.  */
+  clear_proceed_status ();
+
+  /* Let the remote process run.  */
+  proceed (-1, TARGET_SIGNAL_0, 0);
+}
+
+\f
 /* On some machines, e.g. 68k, we may use a different breakpoint instruction
-   than other targets.  */
-static unsigned char break_insn[] = REMOTE_BREAKPOINT;
+   than other targets; in those use REMOTE_BREAKPOINT instead of just
+   BREAKPOINT.  Also, bi-endian targets may define LITTLE_REMOTE_BREAKPOINT
+   and BIG_REMOTE_BREAKPOINT.  If none of these are defined, we just call
+   the standard routines that are in mem-break.c.  */
+
+/* FIXME, these ought to be done in a more dynamic fashion.  For instance,
+   the choice of breakpoint instruction affects target program design and
+   vice versa, and by making it user-tweakable, the special code here
+   goes away and we need fewer special GDB configurations.  */
+
+#if defined (LITTLE_REMOTE_BREAKPOINT) && defined (BIG_REMOTE_BREAKPOINT) && !defined(REMOTE_BREAKPOINT)
+#define REMOTE_BREAKPOINT
+#endif
 
-/* Check that it fits in BREAKPOINT_MAX bytes.  */
-static unsigned char check_break_insn_size[BREAKPOINT_MAX] = REMOTE_BREAKPOINT;
+#ifdef REMOTE_BREAKPOINT
 
-#else /* No REMOTE_BREAKPOINT.  */
+/* If the target isn't bi-endian, just pretend it is.  */
+#if !defined (LITTLE_REMOTE_BREAKPOINT) && !defined (BIG_REMOTE_BREAKPOINT)
+#define LITTLE_REMOTE_BREAKPOINT REMOTE_BREAKPOINT
+#define BIG_REMOTE_BREAKPOINT REMOTE_BREAKPOINT
+#endif
 
-/* Same old breakpoint instruction.  This code does nothing different
-   than mem-break.c.  */
-static unsigned char break_insn[] = BREAKPOINT;
+static unsigned char big_break_insn[] = BIG_REMOTE_BREAKPOINT;
+static unsigned char little_break_insn[] = LITTLE_REMOTE_BREAKPOINT;
 
-#endif /* No REMOTE_BREAKPOINT.  */
+#endif /* REMOTE_BREAKPOINT */
 
 /* Insert a breakpoint on targets that don't have any better breakpoint
    support.  We read the contents of the target location and stash it,
@@ -1536,14 +1747,25 @@ remote_insert_breakpoint (addr, contents_cache)
      CORE_ADDR addr;
      char *contents_cache;
 {
+#ifdef REMOTE_BREAKPOINT
   int val;
 
-  val = target_read_memory (addr, contents_cache, sizeof break_insn);
+  val = target_read_memory (addr, contents_cache, sizeof big_break_insn);
 
   if (val == 0)
-    val = target_write_memory (addr, (char *)break_insn, sizeof break_insn);
+    {
+      if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+       val = target_write_memory (addr, (char *) big_break_insn,
+                                  sizeof big_break_insn);
+      else
+       val = target_write_memory (addr, (char *) little_break_insn,
+                                  sizeof little_break_insn);
+    }
 
   return val;
+#else
+  return memory_insert_breakpoint (addr, contents_cache);
+#endif /* REMOTE_BREAKPOINT */
 }
 
 static int
@@ -1551,7 +1773,11 @@ remote_remove_breakpoint (addr, contents_cache)
      CORE_ADDR addr;
      char *contents_cache;
 {
-  return target_write_memory (addr, contents_cache, sizeof break_insn);
+#ifdef REMOTE_BREAKPOINT
+  return target_write_memory (addr, contents_cache, sizeof big_break_insn);
+#else
+  return memory_remove_breakpoint (addr, contents_cache);
+#endif /* REMOTE_BREAKPOINT */
 }
 \f
 /* Define the target subroutine names */
@@ -1572,10 +1798,8 @@ Specify the serial device it is connected to (e.g. /dev/ttya).",  /* to_doc */
   remote_prepare_to_store,     /* to_prepare_to_store */
   remote_xfer_memory,          /* to_xfer_memory */
   remote_files_info,           /* to_files_info */
-
   remote_insert_breakpoint,    /* to_insert_breakpoint */
   remote_remove_breakpoint,    /* to_remove_breakpoint */
-
   NULL,                                /* to_terminal_init */
   NULL,                                /* to_terminal_inferior */
   NULL,                                /* to_terminal_ours_for_output */
@@ -1602,8 +1826,70 @@ Specify the serial device it is connected to (e.g. /dev/ttya).",  /* to_doc */
   OPS_MAGIC                    /* to_magic */
 };
 
+struct target_ops extended_remote_ops = {
+  "extended-remote",                   /* to_shortname */
+  "Extended remote serial target in gdb-specific protocol",/* to_longname */
+  "Use a remote computer via a serial line, using a gdb-specific protocol.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).",  /* to_doc */
+  extended_remote_open,                        /* to_open */
+  remote_close,                        /* to_close */
+  NULL,                                /* to_attach */
+  remote_detach,               /* to_detach */
+  remote_resume,               /* to_resume */
+  remote_wait,                 /* to_wait */
+  remote_fetch_registers,      /* to_fetch_registers */
+  remote_store_registers,      /* to_store_registers */
+  remote_prepare_to_store,     /* to_prepare_to_store */
+  remote_xfer_memory,          /* to_xfer_memory */
+  remote_files_info,           /* to_files_info */
+
+  remote_insert_breakpoint,    /* to_insert_breakpoint */
+  remote_remove_breakpoint,    /* to_remove_breakpoint */
+
+  NULL,                                /* to_terminal_init */
+  NULL,                                /* to_terminal_inferior */
+  NULL,                                /* to_terminal_ours_for_output */
+  NULL,                                /* to_terminal_ours */
+  NULL,                                /* to_terminal_info */
+  remote_kill,                 /* to_kill */
+  generic_load,                        /* to_load */
+  NULL,                                /* to_lookup_symbol */
+  extended_remote_create_inferior,/* to_create_inferior */
+  extended_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 */
+  1,                           /* to_has_memory */
+  1,                           /* to_has_stack */
+  1,                           /* to_has_registers */
+  1,                           /* to_has_execution */
+  NULL,                                /* sections */
+  NULL,                                /* sections_end */
+  OPS_MAGIC                    /* to_magic */
+};
+
 void
 _initialize_remote ()
 {
   add_target (&remote_ops);
+  add_target (&extended_remote_ops);
+
+  add_show_from_set (add_set_cmd ("remotetimeout", no_class,
+                                 var_integer, (char *)&remote_timeout,
+                                 "Set timeout value for remote read.\n", &setlist),
+                    &showlist);
+
+  add_show_from_set (add_set_cmd ("remotebreak", no_class,
+                                 var_integer, (char *)&remote_break,
+                                 "Set whether to send break if interrupted.\n", &setlist),
+                    &showlist);
+
+  add_show_from_set (add_set_cmd ("remotewritesize", no_class,
+                                 var_integer, (char *)&remote_write_size,
+                                 "Set the maximum number of bytes in each memory write packet.\n", &setlist),
+                    &showlist);
 }
This page took 0.031301 seconds and 4 git commands to generate.