#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 */
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. */
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;
}
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. */
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. */
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;
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, ':'))
{
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
{
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. */
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;
{
*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 ()
{
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;
}
/* 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;
{
{
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;
c1 = fromhex (readchar ());
c2 = fromhex (readchar ());
+
if (csum == (c1 << 4) + c2)
break;
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
char *buf;
{
buf[0] = 'O';
- buf[1] = 'k';
+ buf[1] = 'K';
buf[2] = '\0';
}
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;
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;