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 | |
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')
-rw-r--r-- | gdb/gdbserver/low-sim.c | 56 | ||||
-rw-r--r-- | gdb/gdbserver/remote-utils.c | 308 |
2 files changed, 257 insertions, 107 deletions
diff --git a/gdb/gdbserver/low-sim.c b/gdb/gdbserver/low-sim.c index 08d600a..8ad6e91 100644 --- a/gdb/gdbserver/low-sim.c +++ b/gdb/gdbserver/low-sim.c @@ -23,9 +23,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "callback.h" /* GDB simulator callback interface */ #include "remote-sim.h" /* GDB simulator interface */ +extern int remote_debug; + extern host_callback default_callback; /* in sim/common/callback.c */ -char registers[REGISTER_BYTES]; +char registers[REGISTER_BYTES] __attribute__ ((aligned)); int target_byte_order; /* used by simulator */ @@ -52,28 +54,28 @@ generic_load (loadfile_bfd) if (size > 0) { char *buffer; - bfd_vma vma; + bfd_vma lma; /* use load address, not virtual address */ buffer = xmalloc (size); - vma = bfd_get_section_vma (loadfile_bfd, s); + lma = s->lma; /* Is this really necessary? I guess it gives the user something to look at during a long download. */ - fprintf (stderr, "Loading section %s, size 0x%lx vma 0x%lx\n", - bfd_get_section_name (loadfile_bfd, s), - (unsigned long) size, - (unsigned long) vma); /* chops high 32 bits. FIXME!! */ + printf ("Loading section %s, size 0x%lx lma 0x%lx\n", + bfd_get_section_name (loadfile_bfd, s), + (unsigned long) size, + (unsigned long) lma); /* chops high 32 bits. FIXME!! */ bfd_get_section_contents (loadfile_bfd, s, buffer, 0, size); - write_inferior_memory (vma, buffer, size); + write_inferior_memory (lma, buffer, size); free (buffer); } } } - fprintf (stderr, "Start address 0x%lx\n", - (unsigned long)loadfile_bfd->start_address); + printf ("Start address 0x%lx\n", + (unsigned long)loadfile_bfd->start_address); /* We were doing this in remote-mips.c, I suspect it is right for other targets too. */ @@ -115,25 +117,26 @@ create_inferior (program, argv) new_argv = alloca (sizeof (char *) * (nargs + 3)); /* allocate new args */ for (nargs = 0; argv[nargs] != NULL; nargs++) /* copy old to new */ new_argv[nargs] = argv[nargs]; - new_args[nargs] = "-E"; - new_args[nargs + 1] = bfd_big_endian (abfd) ? "big" : "little"; - new_args[nargs + 2] = NULL; - argv = new_args; + new_argv[nargs] = "-E"; + new_argv[nargs + 1] = bfd_big_endian (abfd) ? "big" : "little"; + new_argv[nargs + 2] = NULL; + argv = new_argv; #endif /* Create an instance of the simulator. */ default_callback.init (&default_callback); - gdbsim_desc = sim_open (SIM_OPEN_STANDALONE, &default_callback, argv); + gdbsim_desc = sim_open (SIM_OPEN_STANDALONE, &default_callback, abfd, argv); if (gdbsim_desc == 0) exit (1); /* Load the program into the simulator. */ - if (sim_load (gdbsim_desc, program, NULL, 0) == SIM_RC_FAIL) - generic_load (abfd); + if (abfd) + if (sim_load (gdbsim_desc, program, NULL, 0) == SIM_RC_FAIL) + generic_load (abfd); /* Create an inferior process in the simulator. This initializes SP. */ - sim_create_inferior (gdbsim_desc, argv, /* env */ NULL); - + sim_create_inferior (gdbsim_desc, abfd, argv, /* env */ NULL); + sim_resume (gdbsim_desc, 1, 0); /* execute one instr */ return pid; } @@ -152,7 +155,8 @@ static void fetch_register (regno) int regno; { - sim_fetch_register (gdbsim_desc, regno, ®isters[REGISTER_BYTE (regno)]); + sim_fetch_register (gdbsim_desc, regno, ®isters[REGISTER_BYTE (regno)], + REGISTER_RAW_SIZE (regno)); } /* Fetch all registers, or just one, from the child process. */ @@ -182,7 +186,8 @@ store_inferior_registers (regno) store_inferior_registers (regno); } else - sim_store_register (gdbsim_desc, regno, ®isters[REGISTER_BYTE (regno)]); + sim_store_register (gdbsim_desc, regno, ®isters[REGISTER_BYTE (regno)], + REGISTER_RAW_SIZE (regno)); } /* Return nonzero if the given thread is still alive. */ @@ -206,19 +211,22 @@ mywait (status) switch (reason) { case sim_exited: - fprintf (stderr, "\nChild exited with retcode = %x \n", sigrc); + if (remote_debug) + printf ("\nChild exited with retcode = %x \n", sigrc); *status = 'W'; return sigrc; #if 0 case sim_stopped: - fprintf (stderr, "\nChild terminated with signal = %x \n", sigrc); + if (remote_debug) + printf ("\nChild terminated with signal = %x \n", sigrc); *status = 'X'; return sigrc; #endif default: /* should this be sim_signalled or sim_stopped? FIXME!! */ - fprintf (stderr, "\nChild received signal = %x \n", sigrc); + if (remote_debug) + printf ("\nChild received signal = %x \n", sigrc); fetch_inferior_registers (0); *status = 'T'; return (unsigned char) sigrc; 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; |