diff options
Diffstat (limited to 'qemu/roms/u-boot/tools/gdb/remote.c')
-rw-r--r-- | qemu/roms/u-boot/tools/gdb/remote.c | 916 |
1 files changed, 0 insertions, 916 deletions
diff --git a/qemu/roms/u-boot/tools/gdb/remote.c b/qemu/roms/u-boot/tools/gdb/remote.c deleted file mode 100644 index f3681043f..000000000 --- a/qemu/roms/u-boot/tools/gdb/remote.c +++ /dev/null @@ -1,916 +0,0 @@ -/* - * 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); -} |