📄 remote.c
字号:
"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. */intremote_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 intreadchar (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 intputpkt (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 intputpkt_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 intread_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 voidgetpkt (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);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -