* defs.h maint.c monitor.c remote-mips.c remote.c: Add support

for `watchdog' variable.  This allows the user to put an upper
	limit on the amount of time that GDB will wait for the target to
	return from a step or continue operation.  This will primarily be
	used for the testsuite, where it is difficult to come up with a
	reasonable timeout for things like function calls, which can take
	as long as three minutes under some circumstances.  If the
	watchdog timer expires, GDB will generate an error that looks like
	`Watchdog has expired.', and will detach from the target.

	* remote-mips.c (mips_open):  Setup initial frame from target.
	Print it out so that user is told where the program is stopped
	when they attach.

	* remote-nrom.c:  Loads of cleanups.  Use serial code to open
	network connections.  Use expect() to wait for response to
	download command.

	* ser-tcp.c (tcp_open):  Retry connection if we get ECONNREFUSED.

	* serial.c serial.h (serial_open serial_fdopen serial_close):
	Allow users to open the same device multiple times.  They all get
	to share the same serial_t.  This is about the only way to have
	multiple active targets use the same device (for download and
	debug).

	* sparcl-tdep.c:  Keep #include <unistd.h> away from GO32.

	* target.c:  Add `targetdebug' variable.  If this is non-zero,
	then a special target is put at the top of the target stack which
	will cause all calls through the target vector to have their args
	and results printed out.
This commit is contained in:
Stu Grossman 1995-06-08 22:42:36 +00:00
parent 311f7c4b6a
commit 4887063b3c
8 changed files with 264 additions and 132 deletions

View File

@ -1,3 +1,42 @@
Thu Jun 8 15:06:00 1995 Stu Grossman (grossman@cygnus.com)
* defs.h maint.c monitor.c remote-mips.c remote.c: Add support
for `watchdog' variable. This allows the user to put an upper
limit on the amount of time that GDB will wait for the target to
return from a step or continue operation. This will primarily be
used for the testsuite, where it is difficult to come up with a
reasonable timeout for things like function calls, which can take
as long as three minutes under some circumstances. If the
watchdog timer expires, GDB will generate an error that looks like
`Watchdog has expired.', and will detach from the target.
* remote-mips.c (mips_open): Setup initial frame from target.
Print it out so that user is told where the program is stopped
when they attach.
* remote-nrom.c: Loads of cleanups. Use serial code to open
network connections. Use expect() to wait for response to
download command.
* ser-tcp.c (tcp_open): Retry connection if we get ECONNREFUSED.
* serial.c serial.h (serial_open serial_fdopen serial_close):
Allow users to open the same device multiple times. They all get
to share the same serial_t. This is about the only way to have
multiple active targets use the same device (for download and
debug).
* sparcl-tdep.c: Keep #include <unistd.h> away from GO32.
* target.c: Add `targetdebug' variable. If this is non-zero,
then a special target is put at the top of the target stack which
will cause all calls through the target vector to have their args
and results printed out.
Wed Jun 7 17:40:37 1995 Per Bothner <bothner@kalessin.cygnus.com>
* ch-exp.y: Handle <primitive_value> "->" <modename>.
Wed Jun 7 17:46:33 1995 Michael Meissner <meissner@tiktok.cygnus.com>
* mem-break.c (LITTLE_BREAKPOINT): If BREAKPOINT and

View File

@ -43,6 +43,14 @@ static void maintenance_time_display PARAMS ((char *, int));
static void maintenance_space_display PARAMS ((char *, int));
/* Set this to the maximum number of seconds to wait instead of waiting forever
in target_wait(). If this timer times out, then it generates an error and
the command is aborted. This replaces most of the need for timeouts in the
GDB test suite, and makes it possible to distinguish between a hung target
and one with slow communications. */
int watchdog = 0;
/*
LOCAL FUNCTION
@ -330,5 +338,13 @@ If a SOURCE file is specified, dump only that file's partial symbols.",
add_cmd ("check-symtabs", class_maintenance, maintenance_check_symtabs,
"Check consistency of psymtabs and symtabs.",
&maintenancelist);
add_show_from_set (
add_set_cmd ("watchdog", class_maintenance, var_zinteger, (char *)&watchdog,
"Set watchdog timer.\n\
When non-zero, this timeout is used instead of waiting forever for a target to\n\
finish a low-level step or continue operation. If the specified amount of time\n\
passes without a response from the target, an error occurs.", &setlist),
&showlist);
#endif /* MAINTENANCE_CMDS */
}

View File

@ -1,5 +1,5 @@
/* Remote debugging interface for MIPS remote debugging protocol.
Copyright 1993, 1994 Free Software Foundation, Inc.
Copyright 1993, 1994, 1995 Free Software Foundation, Inc.
Contributed by Cygnus Support. Written by Ian Lance Taylor
<ian@cygnus.com>.
@ -128,7 +128,7 @@ extern struct target_ops mips_ops;
The value is
0x40 + seq
An acknowlegment packet contains the sequence number of the
packet being acknowledged plus 1 module 64. Data packets are
packet being acknowledged plus 1 modulo 64. Data packets are
transmitted in sequence. There may only be one outstanding
unacknowledged data packet at a time. The sequence numbers
are independent in each direction. If an acknowledgement for
@ -334,10 +334,24 @@ mips_readchar (timeout)
int ch;
static int state = 0;
static char nextstate[5] = { '<', 'I', 'D', 'T', '>' };
#ifdef MAINTENANCE_CMDS
int i;
i = timeout;
if (i == -1 && watchdog > 0)
i = watchdog;
#endif
if (state == 5)
timeout = 1;
ch = SERIAL_READCHAR (mips_desc, timeout);
#ifdef MAINTENANCE_CMDS
if (ch == SERIAL_TIMEOUT && timeout == -1) /* Watchdog went off */
{
target_mourn_inferior ();
error ("Watchdog has expired. Target detached.\n");
}
#endif
if (ch == SERIAL_EOF)
mips_error ("End of file from remote");
if (ch == SERIAL_ERROR)
@ -373,7 +387,10 @@ mips_readchar (timeout)
state = 0;
mips_error ("Remote board reset");
/* At this point, about the only thing we can do is abort the command
in progress and get back to command level as quickly as possible. */
error ("Remote board reset, debug protocol re-initialized.");
}
if (ch == nextstate[state])
@ -874,7 +891,7 @@ mips_request (cmd, addr, data, perr, timeout)
char rcmd;
int rerrflg;
int rresponse;
if (cmd != '\0')
{
if (mips_need_reply)
@ -1031,6 +1048,18 @@ device is attached to the target board (e.g., /dev/ttya).");
ptype = mips_read_processor_type ();
if (ptype)
mips_set_processor_type_command (strsave (ptype), 0);
/* This is really the job of start_remote however, that makes an assumption
that the target is about to print out a status message of some sort. That
doesn't happen here (in fact, it may not be possible to get the monitor to
send the appropriate packet). */
flush_cached_frames ();
registers_changed ();
stop_pc = read_pc ();
set_current_frame (create_new_frame (read_fp (), stop_pc));
select_frame (get_current_frame (), 0);
print_stack_frame (selected_frame, -1, 1);
}
/* Close a connection to the remote board. */

View File

@ -28,6 +28,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "defs.h"
#include "gdbcmd.h"
#include "serial.h"
#include <string.h>
#include "inferior.h"
#include "wait.h"
@ -229,6 +231,10 @@ static int nrom_load_sock = -1;
static int nrom_targ_sock = -1;
static int nrom_ctrl_sock = -1;
static serial_t load_desc = NULL;
static serial_t targ_desc = NULL;
static serial_t ctrl_desc = NULL;
/* For binding to the socket we ned a sockaddr_in structure. */
static struct sockaddr_in nrom_sin;
@ -256,6 +262,8 @@ static int bufindex = 0;
static char workbuf[NROM_BUF_SIZE];
static char sendbuf[NROM_BUF_SIZE];
static char nrom_hostname[100];
/* Forward data declaration. */
extern struct target_ops nrom_ops;
@ -404,68 +412,75 @@ mem2hex (mem, buf, count)
return buf;
}
/* Scan input from the remote system, until STRING is found. If BUF is non-
zero, then collect input until we have collected either STRING or BUFLEN-1
chars. In either case we terminate BUF with a 0. If input overflows BUF
because STRING can't be found, return -1, else return number of chars in BUF
(minus the terminating NUL). Note that in the non-overflow case, STRING
will be at the end of BUF. */
static int
expect (string)
char *string;
{
char *p = string;
int c;
immediate_quit = 1;
while (1)
{
c = SERIAL_READCHAR (ctrl_desc, 5);
if (c == *p++)
{
if (*p == '\0')
{
immediate_quit = 0;
return 0;
}
}
else
{
fputc_unfiltered (c, gdb_stdout);
p = string;
if (c == *p)
p++;
}
}
}
static int
nrom_control_send (s, nbytes)
char *s;
int nbytes;
{
long len;
char buf[10];
SERIAL_WRITE (ctrl_desc, s, nbytes);
/* clear leading characters */
/* FIXME: The ioctl uses here seem bogus to me. -sts */
len = 1;
while (len > 0)
{
if (ioctl (nrom_ctrl_sock, FIONREAD, &len) < 0)
{
perror ("nrom_control_send ioctl");
return (-1);
}
if (len > 0)
{
if (read (nrom_ctrl_sock, buf, 1) < 0)
{
perror ("nrom_control_send read");
return (-1);
}
}
}
if (remote_debug)
printf_filtered ("nrom_control_send: sending '%s' (%d bytes) to NetROM\n",
s, nbytes);
if (writen (nrom_ctrl_sock, s, nbytes) < 0)
{
perror ("nrom_control_send");
return (-1);
}
/* clear trailing characters */
len = 1;
while (len > 0)
{
if (ioctl (nrom_ctrl_sock, FIONREAD, &len) < 0)
{
perror ("nrom_control_send ioctl");
return (-1);
}
if (len > 0)
{
if (read (nrom_ctrl_sock, buf, 1) < 0)
{
perror ("nrom_control_send read");
return (-1);
}
}
}
return 0;
}
static void
nrom_kill ()
{
nrom_close (0);
}
static serial_t
open_socket (name, port)
char *name;
int port;
{
char sockname[100];
serial_t desc;
sprintf (sockname, "%s:%d", name, port);
desc = SERIAL_OPEN (sockname);
if (!desc)
perror_with_name (sockname);
return desc;
}
/* Download a file specified in ARGS to the netROM. */
@ -485,20 +500,9 @@ nrom_load (args, fromtty)
if (nrom_control_send (downloadstring, strlen (downloadstring)) < 0)
error ("nrom_load: control_send() of `%s' failed", downloadstring);
/* Wait for the download daemon to start up. */
sleep (1);
expect ("Waiting for a connection...\n");
nrom_load_sock = socket (AF_INET, SOCK_STREAM, 0);
if (nrom_load_sock == -1)
error ("Could not create download socket, error %d", errno);
memset (&sin, 0, sizeof(struct sockaddr_in));
sin.sin_family = AF_INET;
sin.sin_port = htons (load_port);
sin.sin_addr.s_addr = htonl (nrom_ipaddr);
if (connect (nrom_load_sock, &sin, sizeof(sin)) == -1)
error ("Connect failed, error %d", errno);
load_desc = open_socket (nrom_hostname, load_port);
pbfd = bfd_openr (args, 0);
@ -540,7 +544,7 @@ nrom_load (args, fromtty)
bfd_get_section_contents (pbfd, section, buffer, fptr,
count);
writen (nrom_load_sock, buffer, count);
SERIAL_WRITE (load_desc, buffer, count);
section_address += count;
fptr += count;
section_size -= count;
@ -557,7 +561,8 @@ nrom_load (args, fromtty)
else
error ("\"%s\": Could not open", args);
close (nrom_load_sock);
SERIAL_CLOSE (load_desc);
load_desc = NULL;
}
/* This is called not only when we first attach, but also when the
@ -580,52 +585,24 @@ nrom_open (name, from_tty)
{
int errn;
if (name)
nrom_set_ipaddr (name, from_tty);
else if (nrom_ipaddr == 0)
if (!name || strchr (name, '/') || strchr (name, ':'))
error (
"To open a NetROM connection, you must specify the hostname\n\
or IP address of the NetROM device you wish to use.");
strcpy (nrom_hostname, name);
target_preopen (from_tty);
unpush_target (&nrom_ops);
targ_desc = open_socket (nrom_hostname, target_port);
ctrl_desc = open_socket (nrom_hostname, control_port);
push_target (&nrom_ops);
/* Create the socket used for talking with the target. */
nrom_targ_sock = socket (AF_INET, SOCK_STREAM, 0);
/* Bind the socket. */
nrom_sin.sin_family = AF_INET;
nrom_sin.sin_port = htons (target_port);
nrom_sin.sin_addr.S_un.S_addr = htonl (nrom_ipaddr);
/* Connect to the remote host. */
if (connect (nrom_targ_sock, &nrom_sin, sizeof(nrom_sin)) == -1)
error ("Connect failed, error %d", errno);
/* Create the socket used for talking with the debugger services. */
nrom_ctrl_sock = socket (AF_INET, SOCK_STREAM, 0);
/* Bind the socket. */
nrom_sin.sin_family = AF_INET;
nrom_sin.sin_port = htons (control_port);
nrom_sin.sin_addr.S_un.S_addr = htonl (nrom_ipaddr);
/* Connect to the remote host. */
if (connect (nrom_ctrl_sock, &nrom_sin, sizeof(nrom_sin)) == -1)
{
errn = errno;
close (nrom_targ_sock);
error ("Connect control_socket failed, error %d", errn);
}
if (from_tty)
{
unsigned char *i;
printf_filtered ("Connected to NetROM device \"%s\"", name);
i = (unsigned char *) &nrom_ipaddr;
printf_filtered (" (%d.%d.%d.%d)\n",
UC(i[0]), UC(i[1]), UC(i[2]), UC(i[3]));
}
printf_filtered ("Connected to NetROM device \"%s\"\n", nrom_hostname);
}
static int
@ -640,6 +617,16 @@ static void
nrom_close (quitting)
int quitting;
{
if (load_desc)
SERIAL_CLOSE (load_desc);
if (targ_desc)
SERIAL_CLOSE (targ_desc);
if (ctrl_desc)
SERIAL_CLOSE (ctrl_desc);
load_desc = NULL;
targ_desc = NULL;
ctrl_desc = NULL;
}
/* Attach to the target that is already loaded and possibly running */
@ -1312,7 +1299,7 @@ struct target_ops nrom_ops = {
nrom_can_run,
0, /* to_notice_signals */
0,
process_stratum, /* to_stratum */
download_stratum, /* to_stratum */
NULL, /* to_next */
1,
1,

View File

@ -79,28 +79,38 @@ tcp_open(scb, name)
return -1;
}
scb->fd = socket (PF_INET, SOCK_STREAM, 0);
if (scb->fd < 0)
return -1;
/* Allow rapid reuse of this port. */
tmp = 1;
setsockopt (scb->fd, SOL_SOCKET, SO_REUSEADDR, (char *)&tmp, sizeof(tmp));
/* Enable TCP keep alive process. */
tmp = 1;
setsockopt (scb->fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&tmp, sizeof(tmp));
sockaddr.sin_family = PF_INET;
sockaddr.sin_port = htons(port);
memcpy (&sockaddr.sin_addr.s_addr, hostent->h_addr,
sizeof (struct in_addr));
if (connect (scb->fd, (struct sockaddr *) &sockaddr, sizeof(sockaddr)))
for (i = 1; i <= 15; i++)
{
close(scb->fd);
scb->fd = socket (PF_INET, SOCK_STREAM, 0);
if (scb->fd < 0)
return -1;
/* Allow rapid reuse of this port. */
tmp = 1;
setsockopt (scb->fd, SOL_SOCKET, SO_REUSEADDR, (char *)&tmp, sizeof(tmp));
/* Enable TCP keep alive process. */
tmp = 1;
setsockopt (scb->fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&tmp, sizeof(tmp));
sockaddr.sin_family = PF_INET;
sockaddr.sin_port = htons(port);
memcpy (&sockaddr.sin_addr.s_addr, hostent->h_addr,
sizeof (struct in_addr));
if (!connect (scb->fd, (struct sockaddr *) &sockaddr, sizeof(sockaddr)))
break;
close (scb->fd);
scb->fd = -1;
return -1;
/* We retry for ECONNREFUSED because that is often a temporary condition, which
happens when the server is being restarted. */
if (errno != ECONNREFUSED)
return -1;
sleep (1);
}
protoent = getprotobyname ("tcp");

View File

@ -58,6 +58,13 @@ serial_open (name)
serial_t scb;
struct serial_ops *ops;
for (scb = scb_base; scb; scb = scb->next)
if (scb->name && strcmp (scb->name, name) == 0)
{
scb->refcnt++;
return scb;
}
if (strcmp (name, "pc") == 0)
ops = serial_interface_lookup ("pc");
else if (strchr (name, ':'))
@ -81,18 +88,30 @@ serial_open (name)
return NULL;
}
scb->name = strsave (name);
scb->next = scb_base;
scb->refcnt = 1;
scb_base = scb;
last_serial_opened = scb;
return scb;
}
serial_t
serial_fdopen(fd)
serial_fdopen (fd)
const int fd;
{
serial_t scb;
struct serial_ops *ops;
for (scb = scb_base; scb; scb = scb->next)
if (scb->fd == fd)
{
scb->refcnt++;
return scb;
}
ops = serial_interface_lookup ("hardwire");
if (!ops)
@ -107,6 +126,11 @@ serial_fdopen(fd)
scb->fd = fd;
scb->name = NULL;
scb->next = scb_base;
scb->refcnt = 1;
scb_base = scb;
last_serial_opened = scb;
return scb;
@ -116,6 +140,8 @@ void
serial_close(scb)
serial_t scb;
{
serial_t tmp_scb;
last_serial_opened = NULL;
/* This is bogus. It's not our fault if you pass us a bad scb...! Rob, you
@ -124,7 +150,27 @@ serial_close(scb)
if (!scb)
return;
scb->ops->close(scb);
scb->refcnt--;
if (scb->refcnt > 0)
return;
scb->ops->close (scb);
if (scb->name)
free (scb->name);
if (scb_base == scb)
scb_base = scb_base->next;
else
for (tmp_scb = scb_base; tmp_scb; tmp_scb = tmp_scb->next)
{
if (tmp_scb->next != scb)
continue;
tmp_scb->next = tmp_scb->next->next;
break;
}
free(scb);
}

View File

@ -36,10 +36,15 @@ struct _serial_t
/* ser-unix.c termio{,s} only, we still need to wait for this many more
seconds. */
int timeout_remaining;
char *name; /* The name of the device or host */
struct _serial_t *next; /* Pointer to the next serial_t */
int refcnt; /* Number of pointers to this block */
};
typedef struct _serial_t *serial_t;
serial_t scb_base; /* Pointer to list of scb's */
struct serial_ops {
char *name;
struct serial_ops *next;

View File

@ -24,8 +24,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "serial.h"
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h>
#ifndef __GO32__
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>