Line 37... |
Line 37... |
#include <sys/socket.h>
|
#include <sys/socket.h>
|
#include <fcntl.h>
|
#include <fcntl.h>
|
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
#include <poll.h>
|
#include <poll.h>
|
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
|
#include <signal.h>
|
|
|
/* Package includes */
|
/* Package includes */
|
#include "sim-config.h"
|
#include "sim-config.h"
|
#include "except.h"
|
#include "except.h"
|
#include "opcode/or32.h"
|
#include "opcode/or32.h"
|
#include "spr-defs.h"
|
#include "spr-defs.h"
|
#include "execute.h"
|
#include "execute.h"
|
#include "debug-unit.h"
|
#include "debug-unit.h"
|
#include "sprs.h"
|
#include "sprs.h"
|
|
#include "toplevel-support.h"
|
|
|
|
|
/* Define to log each packet */
|
/* Define to log each packet */
|
/* #define RSP_TRACE 1 */
|
/* #define RSP_TRACE 1 */
|
|
|
Line 57... |
Line 59... |
#define OR1KSIM_RSP_SERVICE "or1ksim-rsp"
|
#define OR1KSIM_RSP_SERVICE "or1ksim-rsp"
|
|
|
/*! Protocol used by Or1ksim */
|
/*! Protocol used by Or1ksim */
|
#define OR1KSIM_RSP_PROTOCOL "tcp"
|
#define OR1KSIM_RSP_PROTOCOL "tcp"
|
|
|
|
/*! Thread ID used by Or1ksim */
|
|
#define OR1KSIM_TID 1
|
|
|
/* Indices of GDB registers that are not GPRs. Must match GDB settings! */
|
/* Indices of GDB registers that are not GPRs. Must match GDB settings! */
|
#define PPC_REGNUM (MAX_GPRS + 0) /*!< Previous PC */
|
#define PPC_REGNUM (MAX_GPRS + 0) /*!< Previous PC */
|
#define NPC_REGNUM (MAX_GPRS + 1) /*!< Next PC */
|
#define NPC_REGNUM (MAX_GPRS + 1) /*!< Next PC */
|
#define SR_REGNUM (MAX_GPRS + 2) /*!< Supervision Register */
|
#define SR_REGNUM (MAX_GPRS + 2) /*!< Supervision Register */
|
#define NUM_REGS (MAX_GRPS + 3) /*!< Total GDB registers */
|
#define NUM_REGS (MAX_GRPS + 3) /*!< Total GDB registers */
|
Line 128... |
Line 133... |
/*! Central data for the RSP connection */
|
/*! Central data for the RSP connection */
|
static struct
|
static struct
|
{
|
{
|
int client_waiting; /*!< Is client waiting a response? */
|
int client_waiting; /*!< Is client waiting a response? */
|
int proto_num; /*!< Number of the protocol used */
|
int proto_num; /*!< Number of the protocol used */
|
int server_fd; /*!< FD for new connections */
|
|
int client_fd; /*!< FD for talking to GDB */
|
int client_fd; /*!< FD for talking to GDB */
|
int sigval; /*!< GDB signal for any exception */
|
int sigval; /*!< GDB signal for any exception */
|
unsigned long int start_addr; /*!< Start of last run */
|
unsigned long int start_addr; /*!< Start of last run */
|
struct mp_entry *mp_hash[MP_HASH_SIZE]; /*!< Matchpoint hash table */
|
struct mp_entry *mp_hash[MP_HASH_SIZE]; /*!< Matchpoint hash table */
|
} rsp;
|
} rsp;
|
|
|
/* Forward declarations of static functions */
|
/* Forward declarations of static functions */
|
static void rsp_server_request ();
|
static void rsp_get_client ();
|
static void rsp_client_request ();
|
static void rsp_client_request ();
|
static void rsp_server_close ();
|
|
static void rsp_client_close ();
|
static void rsp_client_close ();
|
static void put_packet (struct rsp_buf *buf);
|
static void put_packet (struct rsp_buf *buf);
|
static void put_str_packet (const char *str);
|
static void put_str_packet (const char *str);
|
static struct rsp_buf *get_packet ();
|
static struct rsp_buf *get_packet ();
|
static void put_rsp_char (char c);
|
static void put_rsp_char (char c);
|
Line 192... |
Line 195... |
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Initialize the Remote Serial Protocol connection
|
/*!Initialize the Remote Serial Protocol connection
|
|
|
This involves setting up a socket to listen on a socket for attempted
|
Set up the central data structures. */
|
connections from a single GDB instance (we couldn't be talking to multiple
|
|
GDBs at once!).
|
|
|
|
The service is specified either as a port number in the Or1ksim configuration
|
|
(parameter rsp_port in section debug, default 51000) or as a service name
|
|
in the constant OR1KSIM_RSP_SERVICE.
|
|
|
|
The protocol used for communication is specified in OR1KSIM_RSP_PROTOCOL. */
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
void
|
void
|
rsp_init ()
|
rsp_init ()
|
{
|
{
|
struct protoent *protocol; /* Protocol number */
|
|
struct hostent *host_entry; /* Our host entry */
|
|
struct sockaddr_in sock_addr; /* Socket address */
|
|
|
|
int optval; /* Socket options */
|
|
int flags; /* Socket flags */
|
|
char name[256]; /* Our name */
|
|
|
|
/* Clear out the central data structure */
|
/* Clear out the central data structure */
|
rsp.client_waiting = 0; /* GDB client is not waiting for us */
|
rsp.client_waiting = 0; /* GDB client is not waiting for us */
|
rsp.proto_num = -1; /* i.e. invalid */
|
|
rsp.server_fd = -1; /* i.e. invalid */
|
|
rsp.client_fd = -1; /* i.e. invalid */
|
rsp.client_fd = -1; /* i.e. invalid */
|
rsp.sigval = 0; /* No exception */
|
rsp.sigval = 0; /* No exception */
|
rsp.start_addr = EXCEPT_RESET; /* Default restart point */
|
rsp.start_addr = EXCEPT_RESET; /* Default restart point */
|
|
|
/* Set up the matchpoint hash table */
|
/* Set up the matchpoint hash table */
|
mp_hash_init ();
|
mp_hash_init ();
|
|
|
/* Get the protocol number of TCP and save it for future use */
|
|
protocol = getprotobyname (OR1KSIM_RSP_PROTOCOL);
|
|
if (NULL == protocol)
|
|
{
|
|
fprintf (stderr, "Warning: RSP unable to load protocol \"%s\": %s\n",
|
|
OR1KSIM_RSP_PROTOCOL, strerror (errno));
|
|
return;
|
|
}
|
|
|
|
rsp.proto_num = protocol->p_proto; /* Saved for future client use */
|
|
|
|
/* 0 is used as the RSP port number to indicate that we should use the
|
|
service name instead. */
|
|
if (0 == config.debug.rsp_port)
|
|
{
|
|
struct servent *service =
|
|
getservbyname (OR1KSIM_RSP_SERVICE, protocol->p_name);
|
|
|
|
if (NULL == service)
|
|
{
|
|
fprintf (stderr, "Warning: RSP unable to find service \"%s\": %s\n",
|
|
OR1KSIM_RSP_SERVICE, strerror (errno));
|
|
return;
|
|
}
|
|
|
|
config.debug.rsp_port = ntohs (service->s_port);
|
|
}
|
|
|
|
/* Create the socket using the TCP protocol */
|
|
rsp.server_fd = socket (PF_INET, SOCK_STREAM, protocol->p_proto);
|
|
if (rsp.server_fd < 0)
|
|
{
|
|
fprintf (stderr, "Warning: RSP could not create server socket: %s\n",
|
|
strerror (errno));
|
|
return;
|
|
}
|
|
|
|
/* Set this socket to reuse its address. This allows the server to keep
|
|
trying before a GDB session has got going. */
|
|
optval = 1;
|
|
if (setsockopt(rsp.server_fd, SOL_SOCKET,
|
|
SO_REUSEADDR, &optval, sizeof (optval)) < 0)
|
|
{
|
|
fprintf (stderr, "Cannot set SO_REUSEADDR option on server socket %d: "
|
|
"%s\n", rsp.server_fd, strerror (errno));
|
|
rsp_server_close();
|
|
return;
|
|
}
|
|
|
|
/* The server should be non-blocking. Get the current flags and then set the
|
|
non-blocking flags */
|
|
flags = fcntl (rsp.server_fd, F_GETFL);
|
|
if (flags < 0)
|
|
{
|
|
fprintf (stderr, "Warning: Unable to get flags for RSP server socket "
|
|
"%d: %s\n", rsp.server_fd, strerror (errno));
|
|
rsp_server_close();
|
|
return;
|
|
}
|
|
|
|
flags |= O_NONBLOCK;
|
|
if (fcntl (rsp.server_fd, F_SETFL, flags) < 0)
|
|
{
|
|
fprintf (stderr, "Warning: Unable to set flags for RSP server socket "
|
|
"%d to 0x%08x: %s\n", rsp.server_fd, flags, strerror (errno));
|
|
rsp_server_close();
|
|
return;
|
|
}
|
|
|
|
/* Find out what our name is */
|
|
if (gethostname (name, sizeof (name)) < 0)
|
|
{
|
|
fprintf (stderr, "Warning: Unable to get hostname for RSP server: %s\n",
|
|
strerror (errno));
|
|
rsp_server_close();
|
|
return;
|
|
}
|
|
|
|
/* Find out what our address is */
|
|
host_entry = gethostbyname (name);
|
|
if (NULL == host_entry)
|
|
{
|
|
fprintf (stderr, "Warning: Unable to get host entry for RSP server: "
|
|
"%s\n", strerror (errno));
|
|
rsp_server_close();
|
|
return;
|
|
}
|
|
|
|
/* Bind our socket to the appropriate address */
|
|
memset (&sock_addr, 0, sizeof (sock_addr));
|
|
sock_addr.sin_family = host_entry->h_addrtype;
|
|
sock_addr.sin_port = htons (config.debug.rsp_port);
|
|
|
|
if (bind (rsp.server_fd,
|
|
(struct sockaddr *)&sock_addr, sizeof (sock_addr)) < 0)
|
|
{
|
|
fprintf (stderr, "Warning: Unable to bind RSP server socket %d to port "
|
|
"%d: %s\n", rsp.server_fd, config.debug.rsp_port,
|
|
strerror (errno));
|
|
rsp_server_close();
|
|
return;
|
|
}
|
|
|
|
/* Mark us as a passive port, with a maximum backlog of 1 connection (we
|
|
never connect simultaneously to more than one RSP client!) */
|
|
if (listen (rsp.server_fd, 1) < 0)
|
|
{
|
|
fprintf (stderr, "Warning: Unable to set RSP backlog on server socket "
|
|
"%d to %d: %s\n", rsp.server_fd, 1, strerror (errno));
|
|
rsp_server_close();
|
|
return;
|
|
}
|
|
} /* rsp_init () */
|
} /* rsp_init () */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Look for action on RSP
|
/*!Look for action on RSP
|
|
|
This function is called when the processor has stalled, which, except for
|
This function is called when the processor has stalled, which, except for
|
initialization, must be due to an interrupt.
|
initialization, must be due to an interrupt.
|
|
|
If we have no RSP client, we poll the RSP server for a client requesting to
|
If we have no RSP client, we get one. We can make no progress until the
|
join. We can make no progress until the client is available.
|
client is available.
|
|
|
Then if the cause is an interrupt, and the interrupt not been notified to
|
|
GDB, a packet reporting the cause of the interrupt is sent.
|
|
|
|
The function then polls the RSP client port (if open)
|
|
for available input. It then processes the GDB RSP request and return.
|
|
|
|
If an error occurs when polling the RSP server, other than an interrupt, a
|
|
warning message is printed out and the RSP server and client (if open)
|
|
connections are closed.
|
|
|
|
If an error occurs when polling the RSP client, other than an interrupt, a
|
Then if the cause is an exception following a step or continue command, and
|
warning message is printed out and the RSP client connection is closed.
|
the exception not been notified to GDB, a packet reporting the cause of the
|
|
exception is sent.
|
|
|
Polling is always blocking (i.e. timeout -1). */
|
The next client request is then processed. */
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
void
|
void
|
handle_rsp ()
|
handle_rsp ()
|
{
|
{
|
struct pollfd fds[1]; /* The FD to poll for */
|
/* If we have no RSP client, wait until we get one. */
|
|
|
/* Give up if no RSP server port (this should not occur) */
|
|
if (-1 == rsp.server_fd)
|
|
{
|
|
fprintf (stderr, "Warning: No RSP server port open\n");
|
|
return;
|
|
}
|
|
|
|
/* If we have no RSP client, poll the server until we get one. */
|
|
while (-1 == rsp.client_fd)
|
while (-1 == rsp.client_fd)
|
{
|
{
|
/* Poll for a client on the RSP server socket */
|
rsp_get_client ();
|
fds[0].fd = rsp.server_fd; /* FD for the server socket */
|
|
fds[0].events = POLLIN; /* Poll for input activity */
|
|
|
|
/* Poll is always blocking. We can't do anything more until something
|
|
happens here. */
|
|
switch (poll (fds, 1, -1))
|
|
{
|
|
case -1:
|
|
/* Error. Only one we ignore is an interrupt */
|
|
if (EINTR != errno)
|
|
{
|
|
fprintf (stderr, "Warning: poll for RSP failed: closing "
|
|
"server connection: %s\n", strerror (errno));
|
|
rsp_client_close();
|
|
rsp_server_close();
|
|
return;
|
|
}
|
|
break;
|
|
|
|
case 0:
|
|
/* Timeout. This can't occur! */
|
|
fprintf (stderr, "Warning: Unexpected RSP server poll timeout\n");
|
|
break;
|
|
|
|
default:
|
|
/* Is the poll due to input available? If we succeed ignore any
|
|
outstanding reports of exceptions. */
|
|
if (POLLIN == (fds[0].revents & POLLIN))
|
|
{
|
|
rsp_server_request ();
|
|
rsp.client_waiting = 0; /* No longer waiting */
|
rsp.client_waiting = 0; /* No longer waiting */
|
}
|
}
|
else
|
|
{
|
|
/* Error leads to closing the client and server */
|
|
fprintf (stderr, "Warning: RSP server received flags "
|
|
"0x%08x: closing server connection\n", fds[0].revents);
|
|
rsp_client_close();
|
|
rsp_server_close();
|
|
}
|
|
}
|
|
}
|
|
|
|
/* If we have an unacknowledged exception and a client is available, tell
|
/* If we have an unacknowledged exception tell the GDB client. If this
|
GDB. If this exception was a trap due to a memory breakpoint, then
|
exception was a trap due to a memory breakpoint, then adjust the NPC. */
|
adjust the NPC. */
|
|
if (rsp.client_waiting)
|
if (rsp.client_waiting)
|
{
|
{
|
if ((TARGET_SIGNAL_TRAP == rsp.sigval) &&
|
if ((TARGET_SIGNAL_TRAP == rsp.sigval) &&
|
(NULL != mp_hash_lookup (BP_MEMORY, cpu_state.sprs[SPR_PPC])))
|
(NULL != mp_hash_lookup (BP_MEMORY, cpu_state.sprs[SPR_PPC])))
|
{
|
{
|
Line 437... |
Line 251... |
|
|
rsp_report_exception();
|
rsp_report_exception();
|
rsp.client_waiting = 0; /* No longer waiting */
|
rsp.client_waiting = 0; /* No longer waiting */
|
}
|
}
|
|
|
/* Poll the RSP client socket for a message from GDB */
|
/* Get a RSP client request */
|
fds[0].fd = rsp.client_fd; /* FD for the client socket */
|
|
fds[0].events = POLLIN; /* Poll for input activity */
|
|
|
|
/* Poll is always blocking. We can't do anything more until something
|
|
happens here. */
|
|
switch (poll (fds, 1, -1))
|
|
{
|
|
case -1:
|
|
/* Error. Only one we ignore is an interrupt */
|
|
if (EINTR != errno)
|
|
{
|
|
fprintf (stderr, "Warning: poll for RSP failed: closing "
|
|
"server connection: %s\n", strerror (errno));
|
|
rsp_client_close();
|
|
rsp_server_close();
|
|
}
|
|
|
|
return;
|
|
|
|
case 0:
|
|
/* Timeout. This can't occur! */
|
|
fprintf (stderr, "Warning: Unexpected RSP client poll timeout\n");
|
|
return;
|
|
|
|
default:
|
|
/* Is the client activity due to input available? */
|
|
if (POLLIN == (fds[0].revents & POLLIN))
|
|
{
|
|
rsp_client_request ();
|
rsp_client_request ();
|
}
|
|
else
|
|
{
|
|
/* Error leads to closing the client, but not the server. */
|
|
fprintf (stderr, "Warning: RSP client received flags "
|
|
"0x%08x: closing client connection\n", fds[0].revents);
|
|
rsp_client_close();
|
|
}
|
|
}
|
|
} /* handle_rsp () */
|
} /* handle_rsp () */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Note an exception for future processing
|
/*!Note an exception for future processing
|
Line 530... |
Line 308... |
|
|
} /* rsp_exception () */
|
} /* rsp_exception () */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Handle a request to the server for a new client
|
/*!Get a new client connection.
|
|
|
|
Blocks until the client connection is available.
|
|
|
|
A lot of this code is copied from remote_open in gdbserver remote-utils.c.
|
|
|
|
This involves setting up a socket to listen on a socket for attempted
|
|
connections from a single GDB instance (we couldn't be talking to multiple
|
|
GDBs at once!).
|
|
|
We may already have a client. If we do, we will accept an immediately close
|
The service is specified either as a port number in the Or1ksim configuration
|
the new client. */
|
(parameter rsp_port in section debug, default 51000) or as a service name
|
|
in the constant OR1KSIM_RSP_SERVICE.
|
|
|
|
The protocol used for communication is specified in OR1KSIM_RSP_PROTOCOL. */
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
static void
|
static void
|
rsp_server_request ()
|
rsp_get_client ()
|
{
|
{
|
struct sockaddr_in sock_addr; /* The socket address */
|
int tmp_fd; /* Temporary descriptor for socket */
|
|
int optval; /* Socket options */
|
|
struct sockaddr_in sock_addr; /* Socket address */
|
socklen_t len; /* Size of the socket address */
|
socklen_t len; /* Size of the socket address */
|
int fd; /* The client FD */
|
|
int flags; /* fcntl () flags */
|
|
int optval; /* Option value for setsockopt () */
|
|
|
|
/* Get the client FD */
|
|
len = sizeof (sock_addr);
|
|
fd = accept (rsp.server_fd, (struct sockaddr *)&sock_addr, &len);
|
|
if (fd < 0)
|
|
{
|
|
/* This is can happen, because a connection could have started, and then
|
|
terminated due to a protocol error or user initiation before the
|
|
accept could take place.
|
|
|
|
Two of the errors we can ignore (a retry is permissible). All other
|
/* 0 is used as the RSP port number to indicate that we should use the
|
errors, we assume the server port has gone tits up and close. */
|
service name instead. */
|
|
if (0 == config.debug.rsp_port)
|
|
{
|
|
struct servent *service =
|
|
getservbyname (OR1KSIM_RSP_SERVICE, "tcp");
|
|
|
if ((errno != EWOULDBLOCK) && (errno != EAGAIN))
|
if (NULL == service)
|
{
|
{
|
fprintf (stderr, "Warning: RSP server error creating client: "
|
fprintf (stderr, "Warning: RSP unable to find service \"%s\": %s\n",
|
"closing connection %s\n", strerror (errno));
|
OR1KSIM_RSP_SERVICE, strerror (errno));
|
rsp_client_close ();
|
return;
|
rsp_server_close ();
|
|
}
|
}
|
|
|
return;
|
config.debug.rsp_port = ntohs (service->s_port);
|
}
|
}
|
|
|
/* If we already have a client, then immediately close the new one */
|
/* Open a socket on which we'll listen for clients */
|
if (-1 != rsp.client_fd)
|
tmp_fd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
|
if (tmp_fd < 0)
|
{
|
{
|
fprintf (stderr, "Warning: Additional RSP client request refused\n");
|
fprintf (stderr, "ERROR: Cannot open RSP socket\n");
|
close (fd);
|
sim_done ();
|
return;
|
|
}
|
}
|
|
|
/* We have a new client, which should be non-blocking. Get the current flags
|
/* Allow rapid reuse of the port on this socket */
|
and then set the non-blocking flags */
|
optval = 1;
|
flags = fcntl (fd, F_GETFL);
|
setsockopt (tmp_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&optval,
|
if (flags < 0)
|
sizeof (optval));
|
|
|
|
/* Bind the port to the socket */
|
|
sock_addr.sin_family = PF_INET;
|
|
sock_addr.sin_port = htons (config.debug.rsp_port);
|
|
sock_addr.sin_addr.s_addr = INADDR_ANY;
|
|
if (bind (tmp_fd, (struct sockaddr *) &sock_addr, sizeof (sock_addr)))
|
{
|
{
|
fprintf (stderr, "Warning: Unable to get flags for RSP client socket "
|
fprintf (stderr, "ERROR: Cannot bind to RSP socket\n");
|
"%d: %s\n", fd, strerror (errno));
|
sim_done ();
|
close (fd);
|
|
return;
|
|
}
|
}
|
|
|
flags |= O_NONBLOCK;
|
/* Listen for (at most one) client */
|
if (fcntl (fd, F_SETFL, flags) < 0)
|
if (listen (tmp_fd, 1))
|
{
|
{
|
fprintf (stderr, "Warning: Unable to set flags for RSP client socket "
|
fprintf (stderr, "ERROR: Cannot listen on RSP socket\n");
|
"%d to 0x%08x: %s\n", fd, flags, strerror (errno));
|
sim_done ();
|
close (fd);
|
|
return;
|
|
}
|
}
|
|
|
/* Turn of Nagel's algorithm for the client socket. This means the client
|
printf ("Listening for RSP on port %d\n", config.debug.rsp_port);
|
sends stuff immediately, it doesn't wait to fill up a packet. */
|
fflush (stdout);
|
optval = 0;
|
|
len = sizeof (optval);
|
/* Accept a client which connects */
|
if (setsockopt (fd, rsp.proto_num, TCP_NODELAY, &optval, len) < 0)
|
rsp.client_fd = accept (tmp_fd, (struct sockaddr *)&sock_addr, &len);
|
|
|
|
if (-1 == rsp.client_fd)
|
{
|
{
|
fprintf (stderr, "Warning: Unable to disable Nagel's algorithm for "
|
fprintf (stderr, "Warning: Failed to accept RSP client\n");
|
"RSP client socket %d: %s\n", fd, strerror (errno));
|
|
close (fd);
|
|
return;
|
return;
|
}
|
}
|
|
|
/* We have a new client socket */
|
/* Enable TCP keep alive process */
|
rsp.client_fd = fd;
|
optval = 1;
|
|
setsockopt (rsp.client_fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&optval,
|
|
sizeof (optval));
|
|
|
|
/* Don't delay small packets, for better interactive response (disable
|
|
Nagel's algorithm) */
|
|
optval = 1;
|
|
setsockopt (rsp.client_fd, IPPROTO_TCP, TCP_NODELAY, (char *)&optval,
|
|
sizeof (optval));
|
|
|
|
/* Socket is no longer needed */
|
|
close (tmp_fd); /* No longer need this */
|
|
signal (SIGPIPE, SIG_IGN); /* So we don't exit if client dies */
|
|
|
|
printf ("Remote debugging from host %s\n", inet_ntoa (sock_addr.sin_addr));
|
|
|
|
/* If fcntl () is available, use it to enable async I/O
|
|
#if defined(F_SETFL) && defined (FASYNC)
|
|
save_fcntl_flags = fcntl (remote_desc, F_GETFL, 0);
|
|
fcntl (remote_desc, F_SETFL, save_fcntl_flags | FASYNC);
|
|
#if defined (F_SETOWN)
|
|
fcntl (remote_desc, F_SETOWN, getpid ());
|
|
#endif
|
|
#endif */
|
|
|
} /* rsp_server_request () */
|
} /* rsp_get_client () */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Deal with a request from the GDB client session
|
/*!Deal with a request from the GDB client session
|
|
|
Line 691... |
Line 498... |
meaning? Or does it just mean that only vAttach will be recognized
|
meaning? Or does it just mean that only vAttach will be recognized
|
after this? */
|
after this? */
|
put_str_packet ("OK");
|
put_str_packet ("OK");
|
rsp_client_close ();
|
rsp_client_close ();
|
set_stall_state (0);
|
set_stall_state (0);
|
|
rsp.sigval = TARGET_SIGNAL_NONE; /* No signal now */
|
return;
|
return;
|
|
|
case 'F':
|
case 'F':
|
/* File I/O is not currently supported */
|
/* File I/O is not currently supported */
|
fprintf (stderr, "Warning: RSP file I/O not currently supported: 'F' "
|
fprintf (stderr, "Warning: RSP file I/O not currently supported: 'F' "
|
Line 825... |
Line 633... |
}
|
}
|
} /* rsp_client_request () */
|
} /* rsp_client_request () */
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Close the server if it is open */
|
/*!Close the connection to the client if it is open */
|
/*---------------------------------------------------------------------------*/
|
|
static void
|
|
rsp_server_close ()
|
|
{
|
|
if (-1 != rsp.server_fd)
|
|
{
|
|
close (rsp.server_fd);
|
|
rsp.server_fd = -1;
|
|
}
|
|
} /* rsp_server_close () */
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/*!Close the client if it is open */
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
static void
|
static void
|
rsp_client_close ()
|
rsp_client_close ()
|
{
|
{
|
if (-1 != rsp.client_fd)
|
if (-1 != rsp.client_fd)
|
Line 1127... |
Line 921... |
@return The character read, or -1 on failure */
|
@return The character read, or -1 on failure */
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
static int
|
static int
|
get_rsp_char ()
|
get_rsp_char ()
|
{
|
{
|
unsigned char c; /* The character read */
|
|
|
|
if (-1 == rsp.client_fd)
|
if (-1 == rsp.client_fd)
|
{
|
{
|
fprintf (stderr, "Warning: Attempt to read from unopened RSP "
|
fprintf (stderr, "Warning: Attempt to read from unopened RSP "
|
"client: Ignored\n");
|
"client: Ignored\n");
|
return -1;
|
return -1;
|
}
|
}
|
|
|
/* Read until successful (we retry after interrupts) or catastrophic
|
/* Non-blocking read until successful (we retry after interrupts) or
|
failure. */
|
catastrophic failure. */
|
while (1)
|
while (1)
|
{
|
{
|
|
unsigned char c;
|
|
|
switch (read (rsp.client_fd, &c, sizeof (c)))
|
switch (read (rsp.client_fd, &c, sizeof (c)))
|
{
|
{
|
case -1:
|
case -1:
|
/* Error: only allow interrupts or would block */
|
/* Error: only allow interrupts */
|
if ((EAGAIN != errno) && (EINTR != errno))
|
if ((EAGAIN != errno) && (EINTR != errno))
|
{
|
{
|
fprintf (stderr, "Warning: Failed to read from RSP client: "
|
fprintf (stderr, "Warning: Failed to read from RSP client: "
|
"Closing client connection: %s\n",
|
"Closing client connection: %s\n",
|
strerror (errno));
|
strerror (errno));
|
Line 1609... |
Line 1403... |
cpu_state.sprs[SPR_DSR] |= SPR_DSR_TE;
|
cpu_state.sprs[SPR_DSR] |= SPR_DSR_TE;
|
|
|
/* Unstall the processor */
|
/* Unstall the processor */
|
set_stall_state (0);
|
set_stall_state (0);
|
|
|
|
/* Any signal is cleared. */
|
|
rsp.sigval = TARGET_SIGNAL_NONE;
|
|
|
/* Note the GDB client is now waiting for a reply. */
|
/* Note the GDB client is now waiting for a reply. */
|
rsp.client_waiting = 1;
|
rsp.client_waiting = 1;
|
|
|
} /* rsp_continue_generic () */
|
} /* rsp_continue_generic () */
|
|
|
Line 1844... |
Line 1641... |
rsp_read_reg (struct rsp_buf *buf)
|
rsp_read_reg (struct rsp_buf *buf)
|
{
|
{
|
unsigned int regnum;
|
unsigned int regnum;
|
|
|
/* Break out the fields from the data */
|
/* Break out the fields from the data */
|
if (2 != sscanf (buf->data, "p%x", ®num))
|
if (1 != sscanf (buf->data, "p%x", ®num))
|
{
|
{
|
fprintf (stderr, "Warning: Failed to recognize RSP read register "
|
fprintf (stderr, "Warning: Failed to recognize RSP read register "
|
"command: %s\n", buf->data);
|
"command: %s\n", buf->data);
|
put_str_packet ("E01");
|
put_str_packet ("E01");
|
return;
|
return;
|
Line 1944... |
Line 1741... |
|
|
|
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
/*!Handle a RSP query request
|
/*!Handle a RSP query request
|
|
|
@param[in] buf The request */
|
@param[in] buf The request. Reused for any packets that need to be sent
|
|
back. */
|
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
static void
|
static void
|
rsp_query (struct rsp_buf *buf)
|
rsp_query (struct rsp_buf *buf)
|
{
|
{
|
if (0 == strcmp ("qC", buf->data))
|
if (0 == strcmp ("qC", buf->data))
|
{
|
{
|
/* Return the current thread ID (unsigned hex). A null response
|
/* Return the current thread ID (unsigned hex). A null response
|
indicates to use the previously selected thread. Since we do not
|
indicates to use the previously selected thread. We use the constant
|
support a thread concept, this is the appropriate response. */
|
OR1KSIM_TID to represent our single thread of control. */
|
put_str_packet ("");
|
sprintf (buf->data, "QC%x", OR1KSIM_TID);
|
|
buf->len = strlen (buf->data);
|
|
put_packet (buf);
|
}
|
}
|
else if (0 == strncmp ("qCRC", buf->data, strlen ("qCRC")))
|
else if (0 == strncmp ("qCRC", buf->data, strlen ("qCRC")))
|
{
|
{
|
/* Return CRC of memory area */
|
/* Return CRC of memory area */
|
fprintf (stderr, "Warning: RSP CRC query not supported\n");
|
fprintf (stderr, "Warning: RSP CRC query not supported\n");
|
put_str_packet ("E01");
|
put_str_packet ("E01");
|
}
|
}
|
else if (0 == strcmp ("qfThreadInfo", buf->data))
|
else if (0 == strcmp ("qfThreadInfo", buf->data))
|
{
|
{
|
/* Return info about active threads. We return just '-1' */
|
/* Return info about active threads. We return just the constant
|
put_str_packet ("m-1");
|
OR1KSIM_TID to represent our single thread of control. */
|
|
sprintf (buf->data, "m%x", OR1KSIM_TID);
|
|
buf->len = strlen (buf->data);
|
|
put_packet (buf);
|
}
|
}
|
else if (0 == strcmp ("qsThreadInfo", buf->data))
|
else if (0 == strcmp ("qsThreadInfo", buf->data))
|
{
|
{
|
/* Return info about more active threads. We have no more, so return the
|
/* Return info about more active threads. We have no more, so return the
|
end of list marker, 'l' */
|
end of list marker, 'l' */
|
Line 2082... |
Line 1885... |
put_str_packet ("E01");
|
put_str_packet ("E01");
|
return;
|
return;
|
}
|
}
|
|
|
/* Construct the reply */
|
/* Construct the reply */
|
sprintf (cmd, "%8x", mfspr (regno));
|
sprintf (cmd, "%8lx", (unsigned long int)mfspr (regno));
|
ascii2hex (buf->data, cmd);
|
ascii2hex (buf->data, cmd);
|
buf->len = strlen (buf->data);
|
buf->len = strlen (buf->data);
|
put_packet (buf);
|
put_packet (buf);
|
}
|
}
|
else if (0 == strncmp ("writespr ", cmd, strlen ("writespr")))
|
else if (0 == strncmp ("writespr ", cmd, strlen ("writespr")))
|
Line 2242... |
Line 2045... |
cpu_state.sprs[SPR_DSR] |= SPR_DSR_TE;
|
cpu_state.sprs[SPR_DSR] |= SPR_DSR_TE;
|
|
|
/* Unstall the processor */
|
/* Unstall the processor */
|
set_stall_state (0);
|
set_stall_state (0);
|
|
|
|
/* Any signal is cleared. */
|
|
rsp.sigval = TARGET_SIGNAL_NONE;
|
|
|
/* Note the GDB client is now waiting for a reply. */
|
/* Note the GDB client is now waiting for a reply. */
|
rsp.client_waiting = 1;
|
rsp.client_waiting = 1;
|
|
|
} /* rsp_step_generic () */
|
} /* rsp_step_generic () */
|
|
|
Line 2391... |
Line 2197... |
put_str_packet ("E01");
|
put_str_packet ("E01");
|
return;
|
return;
|
}
|
}
|
else
|
else
|
{
|
{
|
// circumvent the read-only check usually done for mem accesses
|
// Circumvent the read-only check usually done for mem accesses
|
// data is in host order, because that's what set_direct32 needs
|
|
set_program8 (addr + off, bindat[off]);
|
set_program8 (addr + off, bindat[off]);
|
}
|
}
|
}
|
}
|
|
|
put_str_packet ("OK");
|
put_str_packet ("OK");
|