diff options
author | Michael Snyder <msnyder@vmware.com> | 1998-03-20 23:33:28 +0000 |
---|---|---|
committer | Michael Snyder <msnyder@vmware.com> | 1998-03-20 23:33:28 +0000 |
commit | d1732185ee5d6d0076f3927efe8910b6253bbda5 (patch) | |
tree | 6261201e33bed41d5e2a447266d3e8e325502830 /gdb/gdbserver/remote-utils.c | |
parent | 25957cb0640f86ef0587dd4dc8e821d3233ec734 (diff) | |
download | gdb-d1732185ee5d6d0076f3927efe8910b6253bbda5.zip gdb-d1732185ee5d6d0076f3927efe8910b6253bbda5.tar.gz gdb-d1732185ee5d6d0076f3927efe8910b6253bbda5.tar.bz2 |
Fri Mar 20 14:45:36 1998 Michael Snyder <msnyder@cleaver.cygnus.com>
* gdbserver/Makefile.in: add dependency on XM_CLIBS.
* gdbserver/low-sim.c (registers) force into alignment.
(create_inferior): Fix typo on new_argv; add abfd arg to
sim_open, sim_create_inferior. Add reg_size arg to
sim_fetch_register, sim_store_register. Make simulator
take a single-step to get into a known running state.
* gdbserver/gdbreplay.c: include fcntl.h for def'n of F_SETFL.
* gdbserver/server.c: Add remote_debug variable to control
debug output.
* gdbserver/server.h: Add prototypes for enable/disable_async_io.
* gdbserver/remote-utils.c: add verbose debugging output controlled
by "remote_debug" variable. Add call to "disable_async_io()"
to avoid being killed by async SIGIO signals.
* config/m32r/m32r.mt: define GDBSERVER_(LIBS and DEPFILES),
so that gdbserver can be built with the m32r simulator.
Diffstat (limited to 'gdb/gdbserver/remote-utils.c')
-rw-r--r-- | gdb/gdbserver/remote-utils.c | 308 |
1 files changed, 225 insertions, 83 deletions
diff --git a/gdb/gdbserver/remote-utils.c b/gdb/gdbserver/remote-utils.c index a16ba0a..5283404 100644 --- a/gdb/gdbserver/remote-utils.c +++ b/gdb/gdbserver/remote-utils.c @@ -15,48 +15,34 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "defs.h" +#include "server.h" +#include "terminal.h" #include <stdio.h> -#include <signal.h> -#include <sys/wait.h> +#include <string.h> #include <sys/ioctl.h> -#include <a.out.h> #include <sys/file.h> -#include <sgtty.h> #include <netinet/in.h> -#include <arpa/inet.h> #include <sys/socket.h> -#include <sys/types.h> +#include <netdb.h> #include <netinet/tcp.h> -#include <sys/time.h> - -extern int remote_desc; -extern int remote_debugging; +#include <sys/ioctl.h> +#include <signal.h> +#include <fcntl.h> -void remote_open (); -void remote_send (); -void putpkt (); -void getpkt (); +int remote_debug = 1; -void write_ok (); -void write_enn (); -void convert_ascii_to_int (); -void convert_int_to_ascii (); -void prepare_resume_reply (); +static int remote_desc; /* Open a connection to a remote debugger. NAME is the filename used for communication. */ void -remote_open (name, from_tty) +remote_open (name) char *name; - int from_tty; { - struct sgttyb sg; - - remote_debugging = 0; + int save_fcntl_flags; if (!strchr (name, ':')) { @@ -64,9 +50,51 @@ remote_open (name, from_tty) if (remote_desc < 0) perror_with_name ("Could not open remote device"); - ioctl (remote_desc, TIOCGETP, &sg); - sg.sg_flags = RAW; - ioctl (remote_desc, TIOCSETP, &sg); +#ifdef HAVE_TERMIOS + { + struct termios termios; + tcgetattr(remote_desc, &termios); + + termios.c_iflag = 0; + termios.c_oflag = 0; + termios.c_lflag = 0; + termios.c_cflag &= ~(CSIZE|PARENB); + termios.c_cflag |= CLOCAL | CS8; + termios.c_cc[VMIN] = 0; + termios.c_cc[VTIME] = 0; + + tcsetattr(remote_desc, TCSANOW, &termios); + } +#endif + +#ifdef HAVE_TERMIO + { + struct termio termio; + ioctl (remote_desc, TCGETA, &termio); + + termio.c_iflag = 0; + termio.c_oflag = 0; + termio.c_lflag = 0; + termio.c_cflag &= ~(CSIZE|PARENB); + termio.c_cflag |= CLOCAL | CS8; + termio.c_cc[VMIN] = 0; + termio.c_cc[VTIME] = 0; + + ioctl (remote_desc, TCSETA, &termio); + } +#endif + +#ifdef HAVE_SGTTY + { + struct sgttyb sg; + + ioctl (remote_desc, TIOCGETP, &sg); + sg.sg_flags = RAW; + ioctl (remote_desc, TIOCSETP, &sg); + } +#endif + + } else { @@ -74,43 +102,67 @@ remote_open (name, from_tty) int port; struct sockaddr_in sockaddr; int tmp; + struct protoent *protoent; + int tmp_desc; port_str = strchr (name, ':'); port = atoi (port_str + 1); - remote_desc = socket (PF_INET, SOCK_STREAM, 0); - if (remote_desc < 0) + tmp_desc = socket (PF_INET, SOCK_STREAM, 0); + if (tmp_desc < 0) perror_with_name ("Can't open socket"); /* Allow rapid reuse of this port. */ tmp = 1; - setsockopt (remote_desc, SOL_SOCKET, SO_REUSEADDR, (char *)&tmp, + setsockopt (tmp_desc, SOL_SOCKET, SO_REUSEADDR, (char *)&tmp, sizeof(tmp)); - /* Enable TCP keep alive process. */ - tmp = 1; - setsockopt (remote_desc, SOL_SOCKET, SO_KEEPALIVE, (char *)&tmp, sizeof(tmp)); - sockaddr.sin_family = PF_INET; sockaddr.sin_port = htons(port); sockaddr.sin_addr.s_addr = INADDR_ANY; - if (bind (remote_desc, &sockaddr, sizeof (sockaddr)) - || listen (remote_desc, 1)) + if (bind (tmp_desc, (struct sockaddr *)&sockaddr, sizeof (sockaddr)) + || listen (tmp_desc, 1)) perror_with_name ("Can't bind address"); tmp = sizeof (sockaddr); - remote_desc = accept (remote_desc, &sockaddr, &tmp); + remote_desc = accept (tmp_desc, (struct sockaddr *)&sockaddr, &tmp); if (remote_desc == -1) perror_with_name ("Accept failed"); + protoent = getprotobyname ("tcp"); + if (!protoent) + perror_with_name ("getprotobyname"); + + /* Enable TCP keep alive process. */ tmp = 1; - setsockopt (remote_desc, 6, TCP_NODELAY, (char *)&tmp, sizeof(tmp)); + setsockopt (tmp_desc, SOL_SOCKET, SO_KEEPALIVE, (char *)&tmp, sizeof(tmp)); + + /* Tell TCP not to delay small packets. This greatly speeds up + interactive response. */ + tmp = 1; + setsockopt (remote_desc, protoent->p_proto, TCP_NODELAY, + (char *)&tmp, sizeof(tmp)); + + close (tmp_desc); /* No longer need this */ + + signal (SIGPIPE, SIG_IGN); /* If we don't do this, then gdbserver simply + exits when the remote side dies. */ } +#if defined(F_SETFL) && defined (FASYNC) + save_fcntl_flags = fcntl (remote_desc, F_GETFL, 0); + fcntl (remote_desc, F_SETFL, save_fcntl_flags | FASYNC); + disable_async_io (); +#endif /* FASYNC */ fprintf (stderr, "Remote debugging using %s\n", name); - remote_debugging = 1; +} + +void +remote_close() +{ + close (remote_desc); } /* Convert hex digit A to a number. */ @@ -139,25 +191,10 @@ tohex (nib) return 'a' + nib - 10; } -/* Send the command in BUF to the remote machine, - and read the reply into BUF. - Report an error if we get an error reply. */ - -void -remote_send (buf) - char *buf; -{ - putpkt (buf); - getpkt (buf); - - if (buf[0] == 'E') - error ("Remote failure reply: E"); -} - /* Send a packet to the remote machine, with error checking. - The data of the packet is in BUF. */ + The data of the packet is in BUF. Returns >= 0 on success, -1 otherwise. */ -void +int putpkt (buf) char *buf; { @@ -183,16 +220,76 @@ putpkt (buf) *p++ = tohex ((csum >> 4) & 0xf); *p++ = tohex (csum & 0xf); + *p = '\0'; + /* Send it over and over until we get a positive ack. */ do { - write (remote_desc, buf2, p - buf2); - read (remote_desc, buf3, 1); + int cc; + + if (write (remote_desc, buf2, p - buf2) != p - buf2) + { + perror ("putpkt(write)"); + return -1; + } + + if (remote_debug) + printf ("putpkt (\"%s\"); [looking for ack]\n", buf2); + cc = read (remote_desc, buf3, 1); + if (remote_debug) + printf ("[received '%c' (0x%x)]\n", buf3[0], buf3[0]); + if (cc <= 0) + { + if (cc == 0) + fprintf (stderr, "putpkt(read): Got EOF\n"); + else + perror ("putpkt(read)"); + + return -1; + } } while (buf3[0] != '+'); + + return 1; /* Success! */ +} + +/* Come here when we get an input interrupt from the remote side. This + interrupt should only be active while we are waiting for the child to do + something. About the only thing that should come through is a ^C, which + will cause us to send a SIGINT to the child. */ + +static void +input_interrupt() +{ + int cc; + char c; + + cc = read (remote_desc, &c, 1); + + if (cc != 1 || c != '\003') + { + fprintf(stderr, "input_interrupt, cc = %d c = %d\n", cc, c); + return; + } + + kill (inferior_pid, SIGINT); +} + +void +enable_async_io() +{ + signal (SIGIO, input_interrupt); } +void +disable_async_io() +{ + signal (SIGIO, SIG_IGN); +} + +/* Returns next char from remote GDB. -1 if error. */ + static int readchar () { @@ -207,8 +304,12 @@ readchar () if (bufcnt <= 0) { - perror ("readchar"); - fatal ("read error, quitting"); + if (bufcnt == 0) + fprintf (stderr, "readchar: Got EOF\n"); + else + perror ("readchar"); + + return -1; } bufp = buf; @@ -217,9 +318,9 @@ readchar () } /* Read a packet from the remote machine, with error checking, - and store it in BUF. */ + and store it in BUF. Returns length of packet, or negative if error. */ -void +int getpkt (buf) char *buf; { @@ -231,12 +332,23 @@ getpkt (buf) { csum = 0; - while ((c = readchar ()) != '$'); + while (1) + { + c = readchar (); + if (c == '$') + break; + if (remote_debug) + printf ("[getpkt: discarding char '%c']\n", c); + if (c < 0) + return -1; + } bp = buf; while (1) { c = readchar (); + if (c < 0) + return -1; if (c == '#') break; *bp++ = c; @@ -246,6 +358,7 @@ getpkt (buf) c1 = fromhex (readchar ()); c2 = fromhex (readchar ()); + if (csum == (c1 << 4) + c2) break; @@ -254,7 +367,14 @@ getpkt (buf) write (remote_desc, "-", 1); } + if (remote_debug) + printf ("getpkt (\"%s\"); [sending ack] \n", buf); + write (remote_desc, "+", 1); + + if (remote_debug) + printf ("[sent ack]\n"); + return bp - buf; } void @@ -262,7 +382,7 @@ write_ok (buf) char *buf; { buf[0] = 'O'; - buf[1] = 'k'; + buf[1] = 'K'; buf[2] = '\0'; } @@ -315,49 +435,70 @@ outreg(regno, buf) char *buf; { extern char registers[]; + int regsize = REGISTER_RAW_SIZE (regno); *buf++ = tohex (regno >> 4); *buf++ = tohex (regno & 0xf); *buf++ = ':'; - convert_int_to_ascii (®isters[REGISTER_BYTE (regno)], buf, 4); - buf += 8; + convert_int_to_ascii (®isters[REGISTER_BYTE (regno)], buf, regsize); + buf += 2 * regsize; *buf++ = ';'; return buf; } void -prepare_resume_reply (buf, status, signal) - char *buf, status; - unsigned char signal; +prepare_resume_reply (buf, status, signo) + char *buf; + char status; + unsigned char signo; { int nib; - char ch; - *buf++ = 'T'; + *buf++ = status; - nib = ((signal & 0xf0) >> 4); + /* FIXME! Should be converting this signal number (numbered + according to the signal numbering of the system we are running on) + to the signal numbers used by the gdb protocol (see enum target_signal + in gdb/target.h). */ + nib = ((signo & 0xf0) >> 4); *buf++ = tohex (nib); - nib = signal & 0x0f; + nib = signo & 0x0f; *buf++ = tohex (nib); - buf = outreg (PC_REGNUM, buf); - buf = outreg (FP_REGNUM, buf); - buf = outreg (SP_REGNUM, buf); + if (status == 'T') + { + buf = outreg (PC_REGNUM, buf); + buf = outreg (FP_REGNUM, buf); + buf = outreg (SP_REGNUM, buf); #ifdef NPC_REGNUM - buf = outreg (NPC_REGNUM, buf); + buf = outreg (NPC_REGNUM, buf); #endif #ifdef O7_REGNUM - buf = outreg (O7_REGNUM, buf); + buf = outreg (O7_REGNUM, buf); #endif + /* If the debugger hasn't used any thread features, don't burden it with + threads. If we didn't check this, GDB 4.13 and older would choke. */ + if (cont_thread != 0) + { + if (old_thread_from_wait != thread_from_wait) + { + sprintf (buf, "thread:%x;", thread_from_wait); + buf += strlen (buf); + old_thread_from_wait = thread_from_wait; + } + } + } + /* For W and X, we're done. */ *buf++ = 0; } void decode_m_packet (from, mem_addr_ptr, len_ptr) char *from; - unsigned int *mem_addr_ptr, *len_ptr; + CORE_ADDR *mem_addr_ptr; + unsigned int *len_ptr; { int i = 0, j = 0; char ch; @@ -381,9 +522,10 @@ decode_m_packet (from, mem_addr_ptr, len_ptr) void decode_M_packet (from, mem_addr_ptr, len_ptr, to) char *from, *to; - unsigned int *mem_addr_ptr, *len_ptr; + CORE_ADDR *mem_addr_ptr; + unsigned int *len_ptr; { - int i = 0, j = 0; + int i = 0; char ch; *mem_addr_ptr = *len_ptr = 0; |