Wed Jul 31 14:46:11 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
[deliverable/binutils-gdb.git] / gdb / remote.c
index 103bf156dac6fee6b817af5386757135351a7e4e..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,8 +132,8 @@ 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.
 
@@ -182,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"
 
@@ -264,6 +266,18 @@ 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 */
 
@@ -272,7 +286,16 @@ extern struct target_ops extended_remote_ops;      /* Forward decl */
    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
@@ -299,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;
@@ -472,7 +502,7 @@ remote_open (name, from_tty)
 }
 
 /* Open a connection to a remote debugger using the extended
-   remote gdb protocol.  NAME is hte filename used for communication.  */
+   remote gdb protocol.  NAME is the filename used for communication.  */
 
 static void
 extended_remote_open (name, from_tty)
@@ -561,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");
@@ -592,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);
 }
 
@@ -656,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)();
@@ -741,7 +778,6 @@ remote_wait (pid, status)
              {
                unsigned char *p1;
                char *p_temp;
-               unsigned LONGEST val;
 
                regno = strtol ((const char *) p, &p_temp, 16); /* Read the register number */
                p1 = (unsigned char *)p_temp;
@@ -773,16 +809,13 @@ Packet: '%s'\n",
 Packet: '%s'\n",
                               regno, p, buf);
 
-                   val = 0L;
                    for (i = 0; i < REGISTER_RAW_SIZE (regno); i++)
                      {
                        if (p[0] == 0 || p[1] == 0)
                          warning ("Remote reply is too short: %s", buf);
-                       val = val * 256 + fromhex (p[0]) * 16 + fromhex (p[1]);
+                       regs[i] = fromhex (p[0]) * 16 + fromhex (p[1]);
                        p += 2;
-
                      }
-                   store_unsigned_integer (regs, REGISTER_RAW_SIZE (regno), val);
                    supply_register (regno, regs);
                  }
 
@@ -812,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)
@@ -1042,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;
 }
@@ -1090,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
@@ -1283,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;
@@ -1636,19 +1706,33 @@ extended_remote_create_inferior (exec_file, args, env)
 }
 
 \f
-#ifdef REMOTE_BREAKPOINT
-
 /* 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
 
-#else /* No REMOTE_BREAKPOINT.  */
+#ifdef REMOTE_BREAKPOINT
 
-/* Same old breakpoint instruction.  This code does nothing different
-   than mem-break.c.  */
-static unsigned char break_insn[] = 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
 
-#endif /* No REMOTE_BREAKPOINT.  */
+static unsigned char big_break_insn[] = BIG_REMOTE_BREAKPOINT;
+static unsigned char little_break_insn[] = LITTLE_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,
@@ -1663,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
@@ -1678,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 */
@@ -1699,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 */
@@ -1780,4 +1877,19 @@ _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.028645 seconds and 4 git commands to generate.