* remote.c: Fix doc for `C' and `S' commands to indicate full
authorStu Grossman <grossman@cygnus>
Fri, 4 Apr 1997 16:52:55 +0000 (16:52 +0000)
committerStu Grossman <grossman@cygnus>
Fri, 4 Apr 1997 16:52:55 +0000 (16:52 +0000)
address.
* (remote_ops extended_remote_ops remote_desc remote_write_size):
Make static.
* (remote_fetch_registers remote_write_bytes remote_read_bytes):
Record size of response to fetch registers command, use this to
limit size of memory read and write commands.
* (push_remote_target):  New function to make it possible to have
another target switch to the remote target.
* target.h:  Add prototype for push_remote_target.
* sh-tdep.c (sh_frame_find_saved_regs):  Fix sign extension bugs
for hosts which default to unsigned chars (such as SGI's).
* (_initialize_sh_tdep):  Don't set remote_write_size.  It's now
handled automatically in remote.c.

gdb/ChangeLog
gdb/remote.c
gdb/sh-tdep.c

index b5ddf0dbd8e9fa33650f3a814a4b03841ea85e2f..5773c7e72f39d3517183a34b3f6ee8372272e055 100644 (file)
@@ -1,3 +1,20 @@
+Fri Apr  4 08:21:21 1997  Stu Grossman  (grossman@critters.cygnus.com)
+
+       * remote.c:  Fix doc for `C' and `S' commands to indicate full
+       address.
+       * (remote_ops extended_remote_ops remote_desc remote_write_size):
+       Make static.
+       * (remote_fetch_registers remote_write_bytes remote_read_bytes):
+       Record size of response to fetch registers command, use this to
+       limit size of memory read and write commands.
+       * (push_remote_target):  New function to make it possible to have
+       another target switch to the remote target.
+       * target.h:  Add prototype for push_remote_target.
+       * sh-tdep.c (sh_frame_find_saved_regs):  Fix sign extension bugs
+       for hosts which default to unsigned chars (such as SGI's).
+       * (_initialize_sh_tdep):  Don't set remote_write_size.  It's now
+       handled automatically in remote.c.
+
 Thu Apr  3 15:10:30 1997  Michael Snyder  <msnyder@cleaver.cygnus.com>
 
        * blockframe.c: blockvector_for_pc_sect(), block_for_pc_sect(), 
index 65caedb62990302964c15e41ed1adb4f41643eb8..1e23db1a18df03e3c452ad9715088e53df530ef5 100644 (file)
@@ -1,5 +1,5 @@
 /* Remote target communications for serial-line targets in custom GDB protocol
-   Copyright 1988, 1991, 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+   Copyright 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
 
 This file is part of GDB.
 
@@ -97,10 +97,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
                                        If AA..AA is omitted,
                                        resume at same address.
 
-       continue with   Csig;AA         Continue with signal sig (hex signal
-       signal                          number).
+       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         Like 'C' but step not continue.
+       step with       Ssig;AA..AA     Like 'C' but step not continue.
        signal
 
        last signal     ?               Reply the current reason for stopping.
@@ -278,8 +279,8 @@ 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 */
+static struct target_ops remote_ops;   /* Forward decl */
+static 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
@@ -300,7 +301,7 @@ 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
    starts.  */
-serial_t remote_desc = NULL;
+static serial_t remote_desc = NULL;
 
 /* Having this larger than 400 causes us to be incompatible with m68k-stub.c
    and i386-stub.c.  Normally, no one would notice because it only matters
@@ -329,10 +330,22 @@ serial_t remote_desc = NULL;
 
 static int remote_write_size = PBUFSIZ;
 
+/* This is the size (in chars) of the first response to the `g' command.  This
+   is used to limit the size of the memory read and write commands to prevent
+   stub buffers from overflowing.  */
+
+static int remote_register_buf_size = 0;
+
 /* 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;
 
+/* These are pointers to hook functions that may be set in order to
+   modify resume/wait behavior for a particular architecture.  */
+
+void (*target_resume_hook) PARAMS ((void));
+void (*target_wait_loop_hook) PARAMS ((void));
+
 \f
 /* These are the threads which we last sent to the remote system.  -1 for all
    or -2 for not sent yet.  */
@@ -663,6 +676,11 @@ remote_resume (pid, step, siggnal)
   last_sent_signal = siggnal;
   last_sent_step = step;
 
+  /* A hook for when we need to do something at the last moment before
+     resumption.  */
+  if (target_resume_hook)
+    (*target_resume_hook) ();
+
   if (siggnal != TARGET_SIGNAL_0)
     {
       buf[0] = step ? 'S' : 'C';
@@ -754,6 +772,11 @@ remote_wait (pid, status)
       getpkt ((char *) buf, 1);
       signal (SIGINT, ofunc);
 
+      /* This is a hook for when we need to do something (perhaps the
+        collection of trace data) every time the target stops.  */
+      if (target_wait_loop_hook)
+       (*target_wait_loop_hook) ();
+
       switch (buf[0])
        {
        case 'E':               /* Error of some sort */
@@ -915,6 +938,9 @@ remote_fetch_registers (regno)
   sprintf (buf, "g");
   remote_send (buf);
 
+  if (remote_register_buf_size == 0)
+    remote_register_buf_size = strlen (buf);
+
   /* Unimplemented registers read as all bits zero.  */
   memset (regs, 0, REGISTER_BYTES);
 
@@ -1068,6 +1094,21 @@ remote_store_word (addr, word)
 #endif /* 0 (unused?) */
 
 \f
+
+/* Return the number of hex digits in num.  */
+
+static int
+hexnumlen (num)
+     ULONGEST num;
+{
+  int i;
+
+  for (i = 0; num != 0; i++)
+    num >>= 4;
+
+  return min (i, 1);
+}
+
 /* Write memory data directly to the remote machine.
    This does not inform the data cache; the data cache uses this.
    MEMADDR is the address in the remote memory space.
@@ -1082,24 +1123,32 @@ remote_write_bytes (memaddr, myaddr, len)
      char *myaddr;
      int len;
 {
-  char buf[PBUFSIZ];
-  int i;
-  char *p;
-  int done;
+  int max_buf_size;            /* Max size of packet output buffer */
+  int origlen;
+
   /* Chop the transfer down if necessary */
 
-  done = 0;
-  while (done < len)
+  max_buf_size = min (remote_write_size, PBUFSIZ);
+  max_buf_size = min (max_buf_size, remote_register_buf_size);
+
+#define PACKET_OVERHEAD (1 + 1 + 1 + 2)        /* $x#xx  - Overhead for all types of packets */
+
+  /* packet overhead + <memaddr>,<len>:  */
+  max_buf_size -= PACKET_OVERHEAD + hexnumlen (memaddr + len - 1) + 1 + hexnumlen (len) + 1;
+
+  origlen = len;
+  while (len > 0)
     {
-      int todo = len - done;
-      int cando = min(remote_write_size, PBUFSIZ) / 2 - 32; /* num bytes that will fit */
+      char buf[PBUFSIZ];
+      char *p;
+      int todo;
+      int i;
 
-      if (todo > cando)
-       todo = cando;
+      todo = min (len, max_buf_size / 2); /* num bytes that will fit */
 
       /* 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);
+      sprintf (buf, "M%lx,%x:", (unsigned long) memaddr, todo);
 
       /* We send target system values byte by byte, in increasing byte addresses,
         each byte encoded as two hex characters.  */
@@ -1107,8 +1156,8 @@ remote_write_bytes (memaddr, myaddr, len)
       p = buf + strlen (buf);
       for (i = 0; i < todo; i++)
        {
-         *p++ = tohex ((myaddr[i + done] >> 4) & 0xf);
-         *p++ = tohex (myaddr[i + done] & 0xf);
+         *p++ = tohex ((myaddr[i] >> 4) & 0xf);
+         *p++ = tohex (myaddr[i] & 0xf);
        }
       *p = '\0';
 
@@ -1124,9 +1173,11 @@ remote_write_bytes (memaddr, myaddr, len)
          errno = EIO;
          return 0;
        }
-      done += todo;
+      myaddr += todo;
+      memaddr += todo;
+      len -= todo;
     }
-  return len;
+  return origlen;
 }
 
 /* Read memory data directly from the remote machine.
@@ -1143,28 +1194,30 @@ remote_read_bytes (memaddr, myaddr, len)
      char *myaddr;
      int len;
 {
-  char buf[PBUFSIZ];
-  int i;
-  char *p;
-  int done;
-  /* Chop transfer down if neccessary */
+  int max_buf_size;            /* Max size of packet output buffer */
+  int origlen;
 
-#if 0
-  /* FIXME: This is wrong for larger packets */
-  if (len > PBUFSIZ / 2 - 1)
-    abort ();
-#endif
-  done = 0;
-  while (done < len)
+  /* Chop the transfer down if necessary */
+
+  max_buf_size = min (remote_write_size, PBUFSIZ);
+  max_buf_size = min (max_buf_size, remote_register_buf_size);
+
+  /* packet overhead */
+  max_buf_size -= PACKET_OVERHEAD;
+
+  origlen = len;
+  while (len > 0)
     {
-      int todo = len - done;
-      int cando = PBUFSIZ / 2 - 32; /* number of bytes that will fit. */
-      if (todo > cando)
-       todo = cando;
+      char buf[PBUFSIZ];
+      char *p;
+      int todo;
+      int i;
+
+      todo = min (len, max_buf_size / 2); /* num bytes that will fit */
 
       /* 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);
+      sprintf (buf, "m%lx,%x", (unsigned long) memaddr, todo);
       putpkt (buf);
       getpkt (buf, 0);
 
@@ -1187,13 +1240,15 @@ remote_read_bytes (memaddr, myaddr, len)
          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]);
+           return i + (origlen - len);
+         myaddr[i] = fromhex (p[0]) * 16 + fromhex (p[1]);
          p += 2;
        }
-      done += todo;
+      myaddr += todo;
+      memaddr += todo;
+      len -= todo;
     }
-  return len;
+  return origlen;
 }
 \f
 /* Read or write LEN bytes from inferior memory at MEMADDR, transferring
@@ -1782,7 +1837,8 @@ remote_remove_breakpoint (addr, contents_cache)
 \f
 /* Define the target subroutine names */
 
-struct target_ops remote_ops = {
+static struct target_ops remote_ops =
+{
   "remote",                    /* to_shortname */
   "Remote serial target in gdb-specific protocol",     /* to_longname */
   "Use a remote computer via a serial line, using a gdb-specific protocol.\n\
@@ -1826,7 +1882,8 @@ Specify the serial device it is connected to (e.g. /dev/ttya).",  /* to_doc */
   OPS_MAGIC                    /* to_magic */
 };
 
-struct target_ops extended_remote_ops = {
+static 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\
@@ -1872,6 +1929,26 @@ Specify the serial device it is connected to (e.g. /dev/ttya).",  /* to_doc */
   OPS_MAGIC                    /* to_magic */
 };
 
+/* 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.  It's basically just a
+   wrapper so that we don't have to expose any of the internal workings of
+   remote.c.
+
+   Prior to calling this routine, you should shutdown the current target code,
+   else you will get the "A program is being debugged already..." message.
+   Usually a call to pop_target() suffices.
+*/
+
+void
+push_remote_target (name, from_tty)
+     char *name;
+     int from_tty;
+{
+  printf_filtered ("Switching to remote protocol\n");
+  remote_open (name, from_tty);
+}
+
 void
 _initialize_remote ()
 {
index 4a3eb2e0d46c6482534d0bb4ff63f476822d0d8b..dcec84629814c01cdf306dc13bb56edcf7ea939a 100644 (file)
@@ -262,7 +262,7 @@ sh_frame_find_saved_regs (fi, fsr)
        }
       else if (IS_MOV_R3 (insn))
        {
-         r3_val = (char) (insn & 0xff);
+         r3_val = ((insn & 0xff) ^ 0x80) - 0x80;
          pc += 2;
          insn = read_memory_integer (pc, 2);
        }
@@ -281,7 +281,7 @@ sh_frame_find_saved_regs (fi, fsr)
       else if (IS_ADD_SP (insn))
        {
          pc += 2;
-         depth += -((char) (insn & 0xff));
+         depth -= ((insn & 0xff) ^ 0x80) - 0x80;
          insn = read_memory_integer (pc, 2);
        }
       else
@@ -706,9 +706,4 @@ Set this to be able to access processor-type-specific registers.\n\
   sh_set_processor_type_command (strsave (DEFAULT_SH_TYPE), 0);
 
   add_com ("regs", class_vars, sh_show_regs, "Print all registers");
-
-  /* Reduce the remote write size because some CMONs can't take
-    more than 400 bytes in a packet.  300 seems like a safe bet.  */
-  remote_write_size = 300;
 }
-