123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916 |
- /*
- * taken from gdb/remote.c
- *
- * I am only interested in the write to memory stuff - everything else
- * has been ripped out
- *
- * all the copyright notices etc have been left in
- */
- /* enough so that it will compile */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <errno.h>
- /*nicked from gcc..*/
- #ifndef alloca
- #ifdef __GNUC__
- #define alloca __builtin_alloca
- #else /* not GNU C. */
- #if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi)
- #include <alloca.h>
- #else /* not sparc */
- #if defined (MSDOS) && !defined (__TURBOC__)
- #include <malloc.h>
- #else /* not MSDOS, or __TURBOC__ */
- #if defined(_AIX)
- #include <malloc.h>
- #pragma alloca
- #else /* not MSDOS, __TURBOC__, or _AIX */
- #ifdef __hpux
- #endif /* __hpux */
- #endif /* not _AIX */
- #endif /* not MSDOS, or __TURBOC__ */
- #endif /* not sparc. */
- #endif /* not GNU C. */
- #ifdef __cplusplus
- extern "C" {
- #endif
- void* alloca(size_t);
- #ifdef __cplusplus
- }
- #endif
- #endif /* alloca not defined. */
- #include "serial.h"
- #include "error.h"
- #include "remote.h"
- #define REGISTER_BYTES 0
- #define fprintf_unfiltered fprintf
- #define fprintf_filtered fprintf
- #define fputs_unfiltered fputs
- #define fputs_filtered fputs
- #define fputc_unfiltered fputc
- #define fputc_filtered fputc
- #define printf_unfiltered printf
- #define printf_filtered printf
- #define puts_unfiltered puts
- #define puts_filtered puts
- #define putchar_unfiltered putchar
- #define putchar_filtered putchar
- #define fputstr_unfiltered(a,b,c) fputs((a), (c))
- #define gdb_stdlog stderr
- #define SERIAL_READCHAR(fd,timo) serialreadchar((fd), (timo))
- #define SERIAL_WRITE(fd, addr, len) serialwrite((fd), (addr), (len))
- #define error Error
- #define perror_with_name Perror
- #define gdb_flush fflush
- #define max(a,b) (((a)>(b))?(a):(b))
- #define min(a,b) (((a)<(b))?(a):(b))
- #define target_mourn_inferior() {}
- #define ULONGEST unsigned long
- #define CORE_ADDR unsigned long
- static int putpkt (char *);
- static int putpkt_binary(char *, int);
- static void getpkt (char *, int);
- static int remote_debug = 0, remote_register_buf_size = 0, watchdog = 0;
- int remote_desc = -1, remote_timeout = 10;
- static void
- fputstrn_unfiltered(char *s, int n, int x, FILE *fp)
- {
- while (n-- > 0)
- fputc(*s++, fp);
- }
- void
- remote_reset(void)
- {
- SERIAL_WRITE(remote_desc, "+", 1);
- }
- void
- remote_continue(void)
- {
- putpkt("c");
- }
- /* Remote target communications for serial-line targets in custom GDB protocol
- Copyright 1988, 91, 92, 93, 94, 95, 96, 97, 98, 1999
- Free Software Foundation, Inc.
- This file is part of GDB.
- * SPDX-License-Identifier: GPL-2.0+
- */
- /* *INDENT-OFF* */
- /* Remote communication protocol.
- A debug packet whose contents are <data>
- is encapsulated for transmission in the form:
- $ <data> # CSUM1 CSUM2
- <data> must be ASCII alphanumeric and cannot include characters
- '$' 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.
- the hex digits 0-9,a-f are used.
- Receiver responds with:
- + - if CSUM is correct and ready for next packet
- - - if CSUM is incorrect
- <data> is as follows:
- Most values are encoded in ascii hex digits. Signal numbers are according
- to the numbering in target.h.
- Request Packet
- set thread Hct... Set thread for subsequent operations.
- c = 'c' for thread used in step and
- continue; t... can be -1 for all
- threads.
- c = 'g' for thread used in other
- operations. If zero, pick a thread,
- any thread.
- reply OK for success
- ENN for an error.
- read registers g
- reply XX....X Each byte of register data
- is described by two hex digits.
- Registers are in the internal order
- for GDB, and the bytes in a register
- are in the same order the machine uses.
- or ENN for an error.
- write regs GXX..XX Each byte of register data
- is described by two hex digits.
- 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
- if able to read only part of the data.
- or ENN NN is errno
- write mem MAA..AA,LLLL:XX..XX
- AA..AA is address,
- LLLL is number of bytes,
- XX..XX is data
- reply OK for success
- ENN for an error (this includes the case
- where only part of the data was
- written).
- write mem XAA..AA,LLLL:XX..XX
- (binary) AA..AA is address,
- LLLL is number of bytes,
- XX..XX is binary data
- reply OK for success
- ENN for an error
- continue cAA..AA AA..AA is address to resume
- If AA..AA is omitted,
- resume at same address.
- step sAA..AA AA..AA is address to resume
- If AA..AA is omitted,
- resume at same address.
- 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..AA Like 'C' but step not continue.
- signal
- last signal ? Reply the current reason for stopping.
- This is the same reply as is generated
- 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.
- or... TAAn...:r...;n...:r...;n...:r...;
- AA = signal number
- n... = register number (hex)
- r... = register contents
- n... = `thread'
- r... = thread process ID. This is
- a hex integer.
- n... = other string not starting
- with valid hex digit.
- gdb should ignore this n,r pair
- and go on to the next. This way
- we can extend the protocol.
- or... WAA The process exited, and AA is
- the exit status. This is only
- applicable for certains sorts of
- targets.
- or... XAA The process terminated with signal
- AA.
- or (obsolete) NAA;tttttttt;dddddddd;bbbbbbbb
- AA = signal number
- tttttttt = address of symbol "_start"
- dddddddd = base of data section
- bbbbbbbb = base of bss section.
- Note: only used by Cisco Systems
- targets. The difference between this
- reply and the "qOffsets" query is that
- the 'N' packet may arrive spontaneously
- whereas the 'qOffsets' is a query
- initiated by the host debugger.
- 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)
- reset r reset -- see sparc stub.
- reserved <other> On other requests, the stub should
- ignore the request and send an empty
- response ($#<checksum>). This way
- 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 character is an ASCII encoding giving a repeat count which
- stands for that many repititions of the character preceding the '*'.
- The encoding is n+29, yielding a printable character where n >=3
- (which is where rle starts to win). Don't use an n > 126.
- So
- "0* " means the same as "0000". */
- /* *INDENT-ON* */
- /* This variable (available to the user via "set remotebinarydownload")
- dictates whether downloads are sent in binary (via the 'X' packet).
- We assume that the stub can, and attempt to do it. This will be cleared if
- the stub does not understand it. This switch is still needed, though
- in cases when the packet is supported in the stub, but the connection
- does not allow it (i.e., 7-bit serial connection only). */
- static int remote_binary_download = 1;
- /* Have we already checked whether binary downloads work? */
- static int remote_binary_checked;
- /* 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(N) (((N)-32)/2)
- /* 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). */
- /* Round up PBUFSIZ to hold all the registers, at least. */
- #define PBUFSIZ ((REGISTER_BYTES > MAXBUFBYTES (400)) \
- ? (REGISTER_BYTES * 2 + 32) \
- : 400)
- /* 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 = 0x7fffffff;
- /* This variable sets the number of bits in an address that are to be
- sent in a memory ("M" or "m") packet. Normally, after stripping
- leading zeros, the entire address would be sent. This variable
- restricts the address to REMOTE_ADDRESS_SIZE bits. HISTORY: The
- initial implementation of remote.c restricted the address sent in
- memory packets to ``host::sizeof long'' bytes - (typically 32
- bits). Consequently, for 64 bit targets, the upper 32 bits of an
- address was never sent. Since fixing this bug may cause a break in
- some remote targets this variable is principly provided to
- facilitate backward compatibility. */
- static int remote_address_size;
- /* Convert hex digit A to a number. */
- static int
- fromhex (int a)
- {
- if (a >= '0' && a <= '9')
- return a - '0';
- else if (a >= 'a' && a <= 'f')
- return a - 'a' + 10;
- else if (a >= 'A' && a <= 'F')
- return a - 'A' + 10;
- else {
- error ("Reply contains invalid hex digit %d", a);
- return -1;
- }
- }
- /* Convert number NIB to a hex digit. */
- static int
- tohex (int nib)
- {
- if (nib < 10)
- return '0' + nib;
- else
- return 'a' + nib - 10;
- }
- /* Return the number of hex digits in num. */
- static int
- hexnumlen (ULONGEST num)
- {
- int i;
- for (i = 0; num != 0; i++)
- num >>= 4;
- return max (i, 1);
- }
- /* Set BUF to the hex digits representing NUM. */
- static int
- hexnumstr (char *buf, ULONGEST num)
- {
- int i;
- int len = hexnumlen (num);
- buf[len] = '\0';
- for (i = len - 1; i >= 0; i--)
- {
- buf[i] = "0123456789abcdef"[(num & 0xf)];
- num >>= 4;
- }
- return len;
- }
- /* Mask all but the least significant REMOTE_ADDRESS_SIZE bits. */
- static CORE_ADDR
- remote_address_masked (CORE_ADDR addr)
- {
- if (remote_address_size > 0
- && remote_address_size < (sizeof (ULONGEST) * 8))
- {
- /* Only create a mask when that mask can safely be constructed
- in a ULONGEST variable. */
- ULONGEST mask = 1;
- mask = (mask << remote_address_size) - 1;
- addr &= mask;
- }
- return addr;
- }
- /* Determine whether the remote target supports binary downloading.
- This is accomplished by sending a no-op memory write of zero length
- to the target at the specified address. It does not suffice to send
- the whole packet, since many stubs strip the eighth bit and subsequently
- compute a wrong checksum, which causes real havoc with remote_write_bytes.
- NOTE: This can still lose if the serial line is not eight-bit clean. In
- cases like this, the user should clear "remotebinarydownload". */
- static void
- check_binary_download (CORE_ADDR addr)
- {
- if (remote_binary_download && !remote_binary_checked)
- {
- char *buf = alloca (PBUFSIZ);
- char *p;
- remote_binary_checked = 1;
- p = buf;
- *p++ = 'X';
- p += hexnumstr (p, (ULONGEST) addr);
- *p++ = ',';
- p += hexnumstr (p, (ULONGEST) 0);
- *p++ = ':';
- *p = '\0';
- putpkt_binary (buf, (int) (p - buf));
- getpkt (buf, 0);
- if (buf[0] == '\0')
- remote_binary_download = 0;
- }
- if (remote_debug)
- {
- if (remote_binary_download)
- fprintf_unfiltered (gdb_stdlog,
- "binary downloading suppported by target\n");
- else
- fprintf_unfiltered (gdb_stdlog,
- "binary downloading NOT suppported by target\n");
- }
- }
- /* 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.
- MYADDR is the address of the buffer in our space.
- LEN is the number of bytes.
- Returns number of bytes transferred, or 0 for error. */
- int
- remote_write_bytes (memaddr, myaddr, len)
- CORE_ADDR memaddr;
- char *myaddr;
- int len;
- {
- unsigned char *buf = alloca (PBUFSIZ);
- int max_buf_size; /* Max size of packet output buffer */
- int origlen;
- extern int verbose;
- /* Verify that the target can support a binary download */
- check_binary_download (memaddr);
- /* Chop the transfer down if necessary */
- max_buf_size = min (remote_write_size, PBUFSIZ);
- if (remote_register_buf_size != 0)
- max_buf_size = min (max_buf_size, remote_register_buf_size);
- /* Subtract header overhead from max payload size - $M<memaddr>,<len>:#nn */
- max_buf_size -= 2 + hexnumlen (memaddr + len - 1) + 1 + hexnumlen (len) + 4;
- origlen = len;
- while (len > 0)
- {
- unsigned char *p, *plen;
- int todo;
- int i;
- /* construct "M"<memaddr>","<len>":" */
- /* sprintf (buf, "M%lx,%x:", (unsigned long) memaddr, todo); */
- memaddr = remote_address_masked (memaddr);
- p = buf;
- if (remote_binary_download)
- {
- *p++ = 'X';
- todo = min (len, max_buf_size);
- }
- else
- {
- *p++ = 'M';
- todo = min (len, max_buf_size / 2); /* num bytes that will fit */
- }
- p += hexnumstr ((char *)p, (ULONGEST) memaddr);
- *p++ = ',';
- plen = p; /* remember where len field goes */
- p += hexnumstr ((char *)p, (ULONGEST) todo);
- *p++ = ':';
- *p = '\0';
- /* We send target system values byte by byte, in increasing byte
- addresses, each byte encoded as two hex characters (or one
- binary character). */
- if (remote_binary_download)
- {
- int escaped = 0;
- for (i = 0;
- (i < todo) && (i + escaped) < (max_buf_size - 2);
- i++)
- {
- switch (myaddr[i] & 0xff)
- {
- case '$':
- case '#':
- case 0x7d:
- /* These must be escaped */
- escaped++;
- *p++ = 0x7d;
- *p++ = (myaddr[i] & 0xff) ^ 0x20;
- break;
- default:
- *p++ = myaddr[i] & 0xff;
- break;
- }
- }
- if (i < todo)
- {
- /* Escape chars have filled up the buffer prematurely,
- and we have actually sent fewer bytes than planned.
- Fix-up the length field of the packet. */
- /* FIXME: will fail if new len is a shorter string than
- old len. */
- plen += hexnumstr ((char *)plen, (ULONGEST) i);
- *plen++ = ':';
- }
- }
- else
- {
- for (i = 0; i < todo; i++)
- {
- *p++ = tohex ((myaddr[i] >> 4) & 0xf);
- *p++ = tohex (myaddr[i] & 0xf);
- }
- *p = '\0';
- }
- putpkt_binary ((char *)buf, (int) (p - buf));
- getpkt ((char *)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;
- }
- /* Increment by i, not by todo, in case escape chars
- caused us to send fewer bytes than we'd planned. */
- myaddr += i;
- memaddr += i;
- len -= i;
- if (verbose)
- putc('.', stderr);
- }
- return origlen;
- }
- /* Stuff for dealing with the packets which are part of this protocol.
- See comment at top of file for details. */
- /* Read a single character from the remote end, masking it down to 7 bits. */
- static int
- readchar (int timeout)
- {
- int ch;
- ch = SERIAL_READCHAR (remote_desc, timeout);
- switch (ch)
- {
- case SERIAL_EOF:
- error ("Remote connection closed");
- case SERIAL_ERROR:
- perror_with_name ("Remote communication error");
- case SERIAL_TIMEOUT:
- return ch;
- default:
- return ch & 0x7f;
- }
- }
- static int
- putpkt (buf)
- char *buf;
- {
- return putpkt_binary (buf, strlen (buf));
- }
- /* Send a packet to the remote machine, with error checking. The data
- of the packet is in BUF. The string in BUF can be at most PBUFSIZ - 5
- to account for the $, # and checksum, and for a possible /0 if we are
- debugging (remote_debug) and want to print the sent packet as a string */
- static int
- putpkt_binary (buf, cnt)
- char *buf;
- int cnt;
- {
- int i;
- unsigned char csum = 0;
- char *buf2 = alloca (PBUFSIZ);
- char *junkbuf = alloca (PBUFSIZ);
- int ch;
- int tcount = 0;
- char *p;
- /* Copy the packet into buffer BUF2, encapsulating it
- and giving it a checksum. */
- if (cnt > BUFSIZ - 5) /* Prosanity check */
- abort ();
- p = buf2;
- *p++ = '$';
- for (i = 0; i < cnt; i++)
- {
- csum += buf[i];
- *p++ = buf[i];
- }
- *p++ = '#';
- *p++ = tohex ((csum >> 4) & 0xf);
- *p++ = tohex (csum & 0xf);
- /* Send it over and over until we get a positive ack. */
- while (1)
- {
- int started_error_output = 0;
- if (remote_debug)
- {
- *p = '\0';
- fprintf_unfiltered (gdb_stdlog, "Sending packet: ");
- fputstrn_unfiltered (buf2, p - buf2, 0, gdb_stdlog);
- fprintf_unfiltered (gdb_stdlog, "...");
- gdb_flush (gdb_stdlog);
- }
- if (SERIAL_WRITE (remote_desc, buf2, p - buf2))
- perror_with_name ("putpkt: write failed");
- /* read until either a timeout occurs (-2) or '+' is read */
- while (1)
- {
- ch = readchar (remote_timeout);
- if (remote_debug)
- {
- switch (ch)
- {
- case '+':
- case SERIAL_TIMEOUT:
- case '$':
- if (started_error_output)
- {
- putchar_unfiltered ('\n');
- started_error_output = 0;
- }
- }
- }
- switch (ch)
- {
- case '+':
- if (remote_debug)
- fprintf_unfiltered (gdb_stdlog, "Ack\n");
- return 1;
- case SERIAL_TIMEOUT:
- tcount++;
- if (tcount > 3)
- return 0;
- break; /* Retransmit buffer */
- case '$':
- {
- /* 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)
- {
- if (!started_error_output)
- {
- started_error_output = 1;
- fprintf_unfiltered (gdb_stdlog, "putpkt: Junk: ");
- }
- fputc_unfiltered (ch & 0177, gdb_stdlog);
- }
- 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
- }
- }
- /* Come here after finding the start of the frame. Collect the rest
- into BUF, verifying the checksum, length, and handling run-length
- compression. Returns 0 on any error, 1 on success. */
- static int
- read_frame (char *buf)
- {
- unsigned char csum;
- char *bp;
- int c;
- csum = 0;
- bp = buf;
- while (1)
- {
- c = readchar (remote_timeout);
- switch (c)
- {
- case SERIAL_TIMEOUT:
- if (remote_debug)
- fputs_filtered ("Timeout in mid-packet, retrying\n", gdb_stdlog);
- return 0;
- case '$':
- if (remote_debug)
- fputs_filtered ("Saw new packet start in middle of old one\n",
- gdb_stdlog);
- return 0; /* Start a new packet, count retries */
- case '#':
- {
- unsigned char pktcsum;
- *bp = '\000';
- pktcsum = fromhex (readchar (remote_timeout)) << 4;
- pktcsum |= fromhex (readchar (remote_timeout));
- if (csum == pktcsum)
- {
- return 1;
- }
- if (remote_debug)
- {
- fprintf_filtered (gdb_stdlog,
- "Bad checksum, sentsum=0x%x, csum=0x%x, buf=",
- pktcsum, csum);
- fputs_filtered (buf, gdb_stdlog);
- fputs_filtered ("\n", gdb_stdlog);
- }
- return 0;
- }
- case '*': /* Run length encoding */
- csum += c;
- c = readchar (remote_timeout);
- csum += c;
- c = c - ' ' + 3; /* Compute repeat count */
- if (c > 0 && c < 255 && bp + c - 1 < buf + PBUFSIZ - 1)
- {
- memset (bp, *(bp - 1), c);
- bp += c;
- continue;
- }
- *bp = '\0';
- printf_filtered ("Repeat count %d too large for buffer: ", c);
- puts_filtered (buf);
- puts_filtered ("\n");
- return 0;
- default:
- if (bp < buf + PBUFSIZ - 1)
- {
- *bp++ = c;
- csum += c;
- continue;
- }
- *bp = '\0';
- puts_filtered ("Remote packet too long: ");
- puts_filtered (buf);
- puts_filtered ("\n");
- return 0;
- }
- }
- }
- /* Read a packet from the remote machine, with error checking, and
- store it in BUF. BUF is expected to be of size PBUFSIZ. If
- FOREVER, wait forever rather than timing out; this is used while
- the target is executing user code. */
- static void
- getpkt (buf, forever)
- char *buf;
- int forever;
- {
- int c;
- int tries;
- int timeout;
- int val;
- strcpy (buf, "timeout");
- if (forever)
- {
- timeout = watchdog > 0 ? watchdog : -1;
- }
- else
- timeout = remote_timeout;
- #define MAX_TRIES 3
- for (tries = 1; tries <= MAX_TRIES; tries++)
- {
- /* 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. */
- /* Note that we will only wait forever prior to the start of a packet.
- After that, we expect characters to arrive at a brisk pace. They
- should show up within remote_timeout intervals. */
- do
- {
- c = readchar (timeout);
- if (c == SERIAL_TIMEOUT)
- {
- if (forever) /* Watchdog went off. Kill the target. */
- {
- target_mourn_inferior ();
- error ("Watchdog has expired. Target detached.\n");
- }
- if (remote_debug)
- fputs_filtered ("Timed out.\n", gdb_stdlog);
- goto retry;
- }
- }
- while (c != '$');
- /* We've found the start of a packet, now collect the data. */
- val = read_frame (buf);
- if (val == 1)
- {
- if (remote_debug)
- {
- fprintf_unfiltered (gdb_stdlog, "Packet received: ");
- fputstr_unfiltered (buf, 0, gdb_stdlog);
- fprintf_unfiltered (gdb_stdlog, "\n");
- }
- SERIAL_WRITE (remote_desc, "+", 1);
- return;
- }
- /* Try the whole thing again. */
- retry:
- SERIAL_WRITE (remote_desc, "-", 1);
- }
- /* We have tried hard enough, and just can't receive the packet. Give up. */
- printf_unfiltered ("Ignoring packet error, continuing...\n");
- SERIAL_WRITE (remote_desc, "+", 1);
- }
|