/* Remote target communications for serial-line targets in custom GDB protocol
- Copyright 1988, 1991, 1992, 1993 Free Software Foundation, Inc.
+ Copyright 1988, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
This file is part of GDB.
$ <data> # CSUM1 CSUM2
<data> must be ASCII alphanumeric and cannot include characters
- '$' or '#'
+ '$' 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.
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
AA = signal number
n... = register number
r... = register contents
-
+ or... WAA The process exited, and AA is
+ the exit status. This is only
+ applicable for certains sorts of
+ targets.
kill request k
toggle debug d toggle debug flag (see 386 & 68k stubs)
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 two characters are hex digits giving a repeat count which
+ stands for that many repititions of the character preceding the '*'.
+ Note that this means that responses cannot contain '*'. Example:
+ "0*03" means the same as "0000". */
#include "defs.h"
#include <string.h>
#include "wait.h"
#include "terminal.h"
#include "gdbcmd.h"
+#include "objfiles.h"
+#include "gdb-stabs.h"
#include "dcache.h"
remote_fetch_registers PARAMS ((int regno));
static void
-remote_resume PARAMS ((int pid, int step, int siggnal));
+remote_resume PARAMS ((int pid, int step, enum target_signal siggnal));
static int
remote_start_remote PARAMS ((char *dummy));
static int
readchar PARAMS ((void));
-static int
-remote_wait PARAMS ((WAITTYPE *status));
+static int remote_wait PARAMS ((int pid, struct target_waitstatus *status));
static int
tohex PARAMS ((int nib));
static void
remote_interrupt_twice PARAMS ((int signo));
+static void
+interrupt_query PARAMS ((void));
+
extern struct target_ops remote_ops; /* Forward decl */
/* This was 5 seconds, which is a long time to sit and wait.
starts. */
serial_t remote_desc = NULL;
-#define PBUFSIZ 1024
+/* 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
+ for writing large chunks of memory (e.g. in downloads). Also, this needs
+ to be more than 400 if required to hold the registers (see below, where
+ we round it up based on REGISTER_BYTES). */
+#define PBUFSIZ 400
/* 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 ((PBUFSIZ-32)/2)
/* Round up PBUFSIZ to hold all the registers, at least. */
+/* The blank line after the #if seems to be required to work around a
+ bug in HP's PA compiler. */
#if REGISTER_BYTES > MAXBUFBYTES
-#undef PBUFSIZ
+
+#undef PBUFSIZ
#define PBUFSIZ (REGISTER_BYTES * 2 + 32)
#endif
+
+/* 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;
+
\f
/* Clean up connection to a remote debugger. */
remote_desc = NULL;
}
+/* Query the remote side for the text, data and bss offsets. */
+
+static void
+get_offsets ()
+{
+ unsigned char buf[PBUFSIZ];
+ int nvals;
+ CORE_ADDR text_addr, data_addr, bss_addr;
+ struct section_offsets *offs;
+
+ putpkt ("qOffsets");
+
+ getpkt (buf, 0);
+
+ if (buf[0] == '\000')
+ return; /* Return silently. Stub doesn't support this
+ command. */
+ if (buf[0] == 'E')
+ {
+ warning ("Remote failure reply: %s", buf);
+ return;
+ }
+
+ nvals = sscanf (buf, "Text=%lx;Data=%lx;Bss=%lx", &text_addr, &data_addr,
+ &bss_addr);
+ if (nvals != 3)
+ error ("Malformed response to offset query, %s", buf);
+
+ if (symfile_objfile == NULL)
+ return;
+
+ 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));
+
+ /* FIXME: This code assumes gdb-stabs.h is being used; it's broken
+ for xcoff, dwarf, sdb-coff, etc. But there is no simple
+ canonical representation for this stuff. (Just what does "text"
+ as seen by the stub mean, anyway? I think it means all sections
+ with SEC_CODE set, but we currently have no way to deal with that). */
+
+ ANOFFSET (offs, SECT_OFF_TEXT) = text_addr;
+
+ /* This is a temporary kludge to force data and bss to use the same offsets
+ because that's what nlmconv does now. The real solution requires changes
+ to the stub and remote.c that I don't have time to do right now. */
+
+ ANOFFSET (offs, SECT_OFF_DATA) = data_addr;
+ ANOFFSET (offs, SECT_OFF_BSS) = data_addr;
+
+ objfile_relocate (symfile_objfile, offs);
+}
+
/* Stub for catch_errors. */
static int
remote_start_remote (dummy)
char *dummy;
{
+ immediate_quit = 1; /* Allow user to interrupt it */
+
/* Ack any packet which the remote side has already sent. */
- /* I'm not sure this \r is needed; we don't use it any other time we
- send an ack. */
- SERIAL_WRITE (remote_desc, "+\r", 2);
+
+ SERIAL_WRITE (remote_desc, "+", 1);
+
+ get_offsets (); /* Get text, data & bss offsets */
+
putpkt ("?"); /* initiate a query from remote machine */
+ immediate_quit = 0;
start_remote (); /* Initialize gdb process mechanisms */
+
return 1;
}
if (!remote_desc)
perror_with_name (name);
- if (baud_rate)
+ if (baud_rate != -1)
{
- int rate;
-
- if (sscanf (baud_rate, "%d", &rate) == 1)
- if (SERIAL_SETBAUDRATE (remote_desc, rate))
- {
- SERIAL_CLOSE (remote_desc);
- perror_with_name (name);
- }
+ if (SERIAL_SETBAUDRATE (remote_desc, baud_rate))
+ {
+ SERIAL_CLOSE (remote_desc);
+ perror_with_name (name);
+ }
}
SERIAL_RAW (remote_desc);
+ /* If there is something sitting in the buffer we might take it as a
+ response to a command, which would be bad. */
+ SERIAL_FLUSH_INPUT (remote_desc);
+
if (from_tty)
{
puts_filtered ("Remote debugging using ");
}
push_target (&remote_ops); /* Switch to using remote target now */
- /* Start the remote connection; if error (0), discard this target. */
- immediate_quit++; /* Allow user to interrupt it */
+ /* 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
+ stub to another, we can (if the target is closed and reopened) cope. */
+ stub_supports_P = 1;
+
+ /* Start the remote connection; if error (0), discard this target.
+ In particular, if the user quits, be sure to discard it
+ (we'd be in an inconsistent state otherwise). */
if (!catch_errors (remote_start_remote, (char *)0,
"Couldn't establish connection to remote target\n", RETURN_MASK_ALL))
pop_target();
static void
remote_resume (pid, step, siggnal)
- int pid, step, siggnal;
+ int pid, step;
+ enum target_signal siggnal;
{
char buf[PBUFSIZ];
if (siggnal)
{
- char *name;
target_terminal_ours_for_output ();
- printf_filtered ("Can't send signals to a remote system. ");
- name = strsigno (siggnal);
- if (name)
- printf_filtered (name);
- else
- printf_filtered ("Signal %d", siggnal);
- printf_filtered (" not sent.\n");
+ printf_filtered
+ ("Can't send signals to a remote system. %s not sent.\n",
+ target_signal_to_name (siggnal));
target_terminal_inferior ();
}
signal (signo, remote_interrupt_twice);
if (remote_debug)
- printf ("remote_interrupt called\n");
+ printf_unfiltered ("remote_interrupt called\n");
SERIAL_WRITE (remote_desc, "\003", 1); /* Send a ^C */
}
{
signal (signo, ofunc);
+ interrupt_query ();
+
+ signal (signo, remote_interrupt);
+}
+
+/* Ask the user what to do when an interrupt is received. */
+
+static void
+interrupt_query ()
+{
target_terminal_ours ();
+
if (query ("Interrupted while waiting for the program.\n\
Give up (and stop debugging it)? "))
{
target_mourn_inferior ();
return_to_top_level (RETURN_QUIT);
}
- else
- {
- signal (signo, remote_interrupt);
- target_terminal_inferior ();
- }
+
+ target_terminal_inferior ();
}
/* Wait until the remote machine stops, then return,
means in the case of this target). */
static int
-remote_wait (status)
- WAITTYPE *status;
+remote_wait (pid, status)
+ int pid;
+ struct target_waitstatus *status;
{
unsigned char buf[PBUFSIZ];
- unsigned char *p;
- int i;
- long regno;
- char regs[MAX_REGISTER_RAW_SIZE];
-
- WSETEXIT ((*status), 0);
- ofunc = (void (*)()) signal (SIGINT, remote_interrupt);
- getpkt ((char *) buf, 1);
- signal (SIGINT, ofunc);
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
- if (buf[0] == 'E')
- error ("Remote failure reply: %s", buf);
- if (buf[0] == 'T')
+ while (1)
{
- /* Expedited reply, containing Signal, {regno, reg} repeat */
- /* format is: 'Tssn...:r...;n...:r...;n...:r...;#cc', where
- ss = signal number
- n... = register number
- r... = register contents
- */
+ unsigned char *p;
- p = &buf[3]; /* after Txx */
+ ofunc = (void (*)()) signal (SIGINT, remote_interrupt);
+ getpkt ((char *) buf, 1);
+ signal (SIGINT, ofunc);
- while (*p)
+ if (buf[0] == 'E')
+ warning ("Remote failure reply: %s", buf);
+ else if (buf[0] == 'T')
{
- unsigned char *p1;
+ int i;
+ long regno;
+ char regs[MAX_REGISTER_RAW_SIZE];
- regno = strtol (p, &p1, 16); /* Read the register number */
+ /* Expedited reply, containing Signal, {regno, reg} repeat */
+ /* format is: 'Tssn...:r...;n...:r...;n...:r...;#cc', where
+ ss = signal number
+ n... = register number
+ r... = register contents
+ */
- if (p1 == p)
- error ("Remote sent badly formed register number: %s\nPacket: '%s'\n",
- p1, buf);
+ p = &buf[3]; /* after Txx */
- p = p1;
+ while (*p)
+ {
+ unsigned char *p1;
- if (*p++ != ':')
- error ("Malformed packet (missing colon): %s\nPacket: '%s'\n",
- p, buf);
+ regno = strtol (p, &p1, 16); /* Read the register number */
- if (regno >= NUM_REGS)
- error ("Remote sent bad register number %d: %s\nPacket: '%s'\n",
- regno, p, buf);
+ if (p1 == p)
+ warning ("Remote sent badly formed register number: %s\nPacket: '%s'\n",
+ p1, buf);
- for (i = 0; i < REGISTER_RAW_SIZE (regno); i++)
- {
- if (p[0] == 0 || p[1] == 0)
- error ("Remote reply is too short: %s", buf);
- regs[i] = fromhex (p[0]) * 16 + fromhex (p[1]);
- p += 2;
- }
+ p = p1;
+
+ if (*p++ != ':')
+ warning ("Malformed packet (missing colon): %s\nPacket: '%s'\n",
+ p, buf);
+
+ if (regno >= NUM_REGS)
+ warning ("Remote sent bad register number %d: %s\nPacket: '%s'\n",
+ regno, p, buf);
- if (*p++ != ';')
- error("Remote register badly formatted: %s", buf);
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i++)
+ {
+ if (p[0] == 0 || p[1] == 0)
+ warning ("Remote reply is too short: %s", buf);
+ regs[i] = fromhex (p[0]) * 16 + fromhex (p[1]);
+ p += 2;
+ }
- supply_register (regno, regs);
+ if (*p++ != ';')
+ warning ("Remote register badly formatted: %s", buf);
+
+ supply_register (regno, regs);
+ }
+ break;
+ }
+ else if (buf[0] == 'W')
+ {
+ /* The remote process exited. */
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = (fromhex (buf[1]) << 4) + fromhex (buf[2]);
+ return 0;
}
+ else if (buf[0] == 'S')
+ break;
+ else
+ warning ("Invalid remote reply: %s", buf);
}
- else if (buf[0] != 'S')
- error ("Invalid remote reply: %s", buf);
- WSETSTOP ((*status), (((fromhex (buf[1])) << 4) + (fromhex (buf[2]))));
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = (enum target_signal)
+ (((fromhex (buf[1])) << 4) + (fromhex (buf[2])));
return 0;
}
+/* Number of bytes of registers this stub implements. */
+static int register_bytes_found;
+
/* Read the remote registers into the block REGS. */
/* Currently we just read all the registers, so we don't use regno. */
/* ARGSUSED */
sprintf (buf, "g");
remote_send (buf);
+ /* Unimplemented registers read as all bits zero. */
+ memset (regs, 0, REGISTER_BYTES);
+
+ /* We can get out of synch in various cases. If the first character
+ in the buffer is not a hex character, assume that has happened
+ and try to fetch another packet to read. */
+ while ((buf[0] < '0' || buf[0] > '9')
+ && (buf[0] < 'a' || buf[0] > 'f'))
+ {
+ if (remote_debug)
+ printf_unfiltered ("Bad register packet; fetching a new packet\n");
+ getpkt (buf, 0);
+ }
+
/* Reply describes registers byte by byte, each byte encoded as two
hex characters. Suck them all up, then supply them to the
register cacheing/storage mechanism. */
p = buf;
for (i = 0; i < REGISTER_BYTES; i++)
{
- if (p[0] == 0 || p[1] == 0)
- error ("Remote reply is too short: %s", buf);
+ if (p[0] == 0)
+ break;
+ if (p[1] == 0)
+ {
+ warning ("Remote reply is of odd length: %s", buf);
+ /* Don't change register_bytes_found in this case, and don't
+ print a second warning. */
+ goto supply_them;
+ }
regs[i] = fromhex (p[0]) * 16 + fromhex (p[1]);
p += 2;
}
+
+ if (i != register_bytes_found)
+ {
+ register_bytes_found = i;
+#ifdef REGISTER_BYTES_OK
+ if (!REGISTER_BYTES_OK (i))
+ warning ("Remote reply is too short: %s", buf);
+#endif
+ }
+
+ supply_them:
for (i = 0; i < NUM_REGS; i++)
supply_register (i, ®s[REGISTER_BYTE(i)]);
}
-/* Prepare to store registers. Since we send them all, we have to
- read out the ones we don't want to change first. */
+/* Prepare to store registers. Since we may send them all (using a
+ 'G' request), we have to read out the ones we don't want to change
+ first. */
static void
remote_prepare_to_store ()
read_register_bytes (0, (char *)NULL, REGISTER_BYTES);
}
-/* Store the remote registers from the contents of the block REGISTERS.
- FIXME, eventually just store one register if that's all that is needed. */
+/* Store register REGNO, or all registers if REGNO == -1, from the contents
+ of REGISTERS. FIXME: ignores errors. */
-/* ARGSUSED */
static void
remote_store_registers (regno)
int regno;
int i;
char *p;
+ if (regno >= 0 && stub_supports_P)
+ {
+ /* Try storing a single register. */
+ char *regp;
+
+ sprintf (buf, "P%x=", regno);
+ p = buf + strlen (buf);
+ regp = ®isters[REGISTER_BYTE (regno)];
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); ++i)
+ {
+ *p++ = tohex ((regp[i] >> 4) & 0xf);
+ *p++ = tohex (regp[i] & 0xf);
+ }
+ *p = '\0';
+ remote_send (buf);
+ if (buf[0] != '\0')
+ {
+ /* The stub understands the 'P' request. We are done. */
+ return;
+ }
+
+ /* The stub does not support the 'P' request. Use 'G' instead,
+ and don't try using 'P' in the future (it will just waste our
+ time). */
+ stub_supports_P = 0;
+ }
+
buf[0] = 'G';
-
+
/* Command describes registers byte by byte,
each byte encoded as two hex characters. */
p = buf + 1;
- for (i = 0; i < REGISTER_BYTES; i++)
+ /* remote_prepare_to_store insures that register_bytes_found gets set. */
+ for (i = 0; i < register_bytes_found; i++)
{
*p++ = tohex ((registers[i] >> 4) & 0xf);
*p++ = tohex (registers[i] & 0xf);
remote_send (buf);
}
+#if 0
+
+/* Use of the data cache is disabled because it loses for looking at
+ and changing hardware I/O ports and the like. Accepting `volatile'
+ would perhaps be one way to fix it, but a better way which would
+ win for more cases would be to use the executable file for the text
+ segment, like the `icache' code below but done cleanly (in some
+ target-independent place, perhaps in target_xfer_memory, perhaps
+ based on assigning each target a speed or perhaps by some simpler
+ mechanism). */
+
/* Read a word from remote address ADDR and return it.
This goes through the data cache. */
-int
+static int
remote_fetch_word (addr)
CORE_ADDR addr;
{
/* Write a word WORD into remote address ADDR.
This goes through the data cache. */
-void
+static void
remote_store_word (addr, word)
CORE_ADDR addr;
int word;
{
dcache_poke (remote_dcache, addr, word);
}
-
+#endif /* 0 */
\f
/* Write memory data directly to the remote machine.
This does not inform the data cache; the data cache uses this.
int i;
char *p;
- if (len > PBUFSIZ / 2 - 20)
- abort ();
-
- sprintf (buf, "M%x,%x:", memaddr, len);
+ /* 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);
/* We send target system values byte by byte, in increasing byte addresses,
each byte encoded as two hex characters. */
if (len > PBUFSIZ / 2 - 1)
abort ();
- sprintf (buf, "m%x,%x", memaddr, len);
+ /* 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);
xfersize = len;
if (should_write)
- bytes_xferred = remote_write_bytes (memaddr, myaddr, xfersize);
+ bytes_xferred = remote_write_bytes (memaddr,
+ (unsigned char *)myaddr, xfersize);
else
- bytes_xferred = remote_read_bytes (memaddr, myaddr, xfersize);
+ bytes_xferred = remote_read_bytes (memaddr,
+ (unsigned char *)myaddr, xfersize);
/* If we get an error, we are done xferring. */
if (bytes_xferred == 0)
return total_xferred;
}
+#if 0
+/* Enable after 4.12. */
+
+void
+remote_search (len, data, mask, startaddr, increment, lorange, hirange
+ addr_found, data_found)
+ int len;
+ char *data;
+ char *mask;
+ CORE_ADDR startaddr;
+ int increment;
+ CORE_ADDR lorange;
+ CORE_ADDR hirange;
+ CORE_ADDR *addr_found;
+ char *data_found;
+{
+ if (increment == -4 && len == 4)
+ {
+ long mask_long, data_long;
+ long data_found_long;
+ CORE_ADDR addr_we_found;
+ char buf[PBUFSIZ];
+ long returned_long[2];
+ char *p;
+
+ mask_long = extract_unsigned_integer (mask, len);
+ data_long = extract_unsigned_integer (data, len);
+ sprintf (buf, "t%x:%x,%x", startaddr, data_long, mask_long);
+ putpkt (buf);
+ getpkt (buf, 0);
+ if (buf[0] == '\0')
+ {
+ /* The stub doesn't support the 't' request. We might want to
+ remember this fact, but on the other hand the stub could be
+ switched on us. Maybe we should remember it only until
+ the next "target remote". */
+ generic_search (len, data, mask, startaddr, increment, lorange,
+ hirange, addr_found, data_found);
+ return;
+ }
+
+ 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 use EIO. */
+ memory_error (EIO, startaddr);
+ p = buf;
+ addr_we_found = 0;
+ while (*p != '\0' && *p != ',')
+ addr_we_found = (addr_we_found << 4) + fromhex (*p++);
+ if (*p == '\0')
+ error ("Protocol error: short return for search");
+
+ data_found_long = 0;
+ while (*p != '\0' && *p != ',')
+ data_found_long = (data_found_long << 4) + fromhex (*p++);
+ /* Ignore anything after this comma, for future extensions. */
+
+ if (addr_we_found < lorange || addr_we_found >= hirange)
+ {
+ *addr_found = 0;
+ return;
+ }
+
+ *addr_found = addr_we_found;
+ *data_found = store_unsigned_integer (data_we_found, len);
+ return;
+ }
+ generic_search (len, data, mask, startaddr, increment, lorange,
+ hirange, addr_found, data_found);
+}
+#endif /* 0 */
+\f
static void
remote_files_info (ignore)
struct target_ops *ignore;
while (1)
{
+ int started_error_output = 0;
+
if (remote_debug)
{
*p = '\0';
- printf ("Sending packet: %s...", buf2); fflush(stdout);
+ printf_unfiltered ("Sending packet: %s...", buf2);
+ gdb_flush(gdb_stdout);
}
if (SERIAL_WRITE (remote_desc, buf2, p - buf2))
perror_with_name ("putpkt: write failed");
{
ch = readchar ();
+ if (remote_debug)
+ {
+ switch (ch)
+ {
+ case '+':
+ case SERIAL_TIMEOUT:
+ case SERIAL_ERROR:
+ case SERIAL_EOF:
+ case '$':
+ if (started_error_output)
+ {
+ putc_unfiltered ('\n');
+ started_error_output = 0;
+ }
+ }
+ }
+
switch (ch)
{
case '+':
if (remote_debug)
- printf("Ack\n");
+ printf_unfiltered("Ack\n");
return;
case SERIAL_TIMEOUT:
break; /* Retransmit buffer */
perror_with_name ("putpkt: couldn't read ACK");
case SERIAL_EOF:
error ("putpkt: EOF while trying to read ACK");
+ case '$':
+ {
+ unsigned char junkbuf[PBUFSIZ];
+
+ /* It's probably an old response, and we're out of sync. Just
+ gobble up the packet and ignore it. */
+ getpkt (junkbuf, 0);
+ continue; /* Now, go look for + */
+ }
default:
if (remote_debug)
- printf ("%02X %c ", ch&0xFF, ch);
+ {
+ if (!started_error_output)
+ {
+ started_error_output = 1;
+ printf_unfiltered ("putpkt: Junk: ");
+ }
+ putc_unfiltered (ch & 0177);
+ }
continue;
}
break; /* Here to retransmit */
}
+
+#if 0
+ /* This is wrong. If doing a long backtrace, the user should be
+ able to get out next time we call QUIT, without anything as violent
+ as interrupt_query. If we want to provide a way out of here
+ without getting to the next QUIT, it should be based on hitting
+ ^C twice as in remote_wait. */
+ if (quit_flag)
+ {
+ quit_flag = 0;
+ interrupt_query ();
+ }
+#endif
}
}
while the target is executing user code. */
static void
-getpkt (buf, forever)
- char *buf;
+getpkt (retbuf, forever)
+ char *retbuf;
int forever;
{
char *bp;
int c = 0;
unsigned char c1, c2;
int retries = 0;
+ char buf[PBUFSIZ];
+
#define MAX_RETRIES 10
while (1)
{
+#if 0
+ /* This is wrong. If doing a long backtrace, the user should be
+ able to get out time next we call QUIT, without anything as violent
+ as interrupt_query. If we want to provide a way out of here
+ without getting to the next QUIT, it should be based on hitting
+ ^C twice as in remote_wait. */
+ if (quit_flag)
+ {
+ quit_flag = 0;
+ interrupt_query ();
+ }
+#endif
+
/* This can loop forever if the remote side sends us characters
continuously, but if it pauses, we'll get a zero from readchar
because of timeout. Then we'll count that as a retry. */
{
if (forever)
continue;
- if (++retries >= MAX_RETRIES)
- if (remote_debug) puts_filtered ("Timed out.\n");
- goto out;
+ if (remote_debug)
+ puts_filtered ("Timed out.\n");
+ goto whole;
}
if (c == SERIAL_EOF)
}
else
{
- printf ("Ignoring packet error, continuing...\n");
+ printf_unfiltered ("Ignoring packet error, continuing...\n");
break;
}
}
-out:
+ /* Deal with run-length encoding. */
+ {
+ char *src = buf;
+ char *dest = retbuf;
+ int i;
+ int repeat;
+ do {
+ if (*src == '*')
+ {
+ if (src[1] == '\0' || src[2] == '\0')
+ {
+ if (remote_debug)
+ puts_filtered ("Packet too short, retrying\n");
+ goto whole;
+ }
+ repeat = (fromhex (src[1]) << 4) + fromhex (src[2]);
+ for (i = 0; i < repeat; ++i)
+ {
+ *dest++ = src[-1];
+ }
+ src += 2;
+ }
+ else
+ {
+ *dest++ = *src;
+ }
+ } while (*src++ != '\0');
+ }
SERIAL_WRITE (remote_desc, "+", 1);
if (remote_debug)
- fprintf (stderr,"Packet received: %s\n", buf);
+ fprintf_unfiltered (gdb_stderr,"Packet received: %s\n", buf);
}
\f
static void
NULL, /* sections_end */
OPS_MAGIC /* to_magic */
};
+#endif /* Use remote. */
void
_initialize_remote ()
{
+#if !defined(DONT_USE_REMOTE)
add_target (&remote_ops);
-}
#endif
+}