/* 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.
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.
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
/* 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
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. */
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';
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 */
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);
#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.
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. */
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';
errno = EIO;
return 0;
}
- done += todo;
+ myaddr += todo;
+ memaddr += todo;
+ len -= todo;
}
- return len;
+ return origlen;
}
/* Read memory data directly from the remote machine.
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);
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
\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\
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\
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 ()
{