/* See the GDB User Guide for details of the GDB remote protocol. */
#include "defs.h"
-#include "gdb_string.h"
+#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include "inferior.h"
#include "remote-fileio.h"
#include "gdb/fileio.h"
-#include "gdb_stat.h"
+#include <sys/stat.h>
#include "xml-support.h"
#include "memory-map.h"
static void remote_async (void (*callback) (enum inferior_event_type event_type,
void *context), void *context);
-static void remote_detach (struct target_ops *ops, char *args, int from_tty);
-
static void sync_remote_interrupt_twice (int signo);
static void interrupt_query (void);
static void stop_reply_xfree (struct stop_reply *);
static void remote_parse_stop_reply (char *, struct stop_reply *);
static void push_stop_reply (struct stop_reply *);
-static void discard_pending_stop_replies (struct inferior *);
+static void discard_pending_stop_replies_in_queue (struct remote_state *);
static int peek_stop_reply (ptid_t ptid);
static void remote_async_inferior_event_handler (gdb_client_data);
threadref echo_nextthread;
threadref nextthread;
threadref resultthreadlist[MAXTHREADLISTRESULTS];
+
+ /* The state of remote notification. */
+ struct remote_notif_state *notif_state;
};
/* Private data that we'll store in (struct thread_info)->private. */
inferior_ptid = null_ptid;
discard_all_inferiors ();
- /* Stop replies may from inferiors which are still unknown to GDB.
- We are closing the remote target, so we should discard
- everything, including the stop replies from GDB-unknown
- inferiors. */
- discard_pending_stop_replies (NULL);
+ /* We are closing the remote target, so we should discard
+ everything of this target. */
+ discard_pending_stop_replies_in_queue (rs);
if (remote_async_inferior_event_token)
delete_async_event_handler (&remote_async_inferior_event_token);
- remote_notif_unregister_async_event_handler ();
+ remote_notif_state_xfree (rs->notif_state);
trace_reset_local_state ();
}
/* remote_notif_get_pending_replies acks this one, and gets
the rest out. */
- notif_client_stop.pending_event
+ rs->notif_state->pending_event[notif_client_stop.id]
= remote_notif_parse (notif, rs->buf);
remote_notif_get_pending_events (notif);
remote_async_inferior_event_token
= create_async_event_handler (remote_async_inferior_event_handler,
NULL);
- remote_notif_register_async_event_handler ();
+ rs->notif_state = remote_notif_state_allocate ();
/* Reset the target state; these things will be queried either by
remote_query_supported or as they are needed. */
die when it hits one. */
static void
-remote_detach_1 (char *args, int from_tty, int extended)
+remote_detach_1 (const char *args, int from_tty, int extended)
{
int pid = ptid_get_pid (inferior_ptid);
struct remote_state *rs = get_remote_state ();
}
static void
-remote_detach (struct target_ops *ops, char *args, int from_tty)
+remote_detach (struct target_ops *ops, const char *args, int from_tty)
{
remote_detach_1 (args, from_tty, 0);
}
static void
-extended_remote_detach (struct target_ops *ops, char *args, int from_tty)
+extended_remote_detach (struct target_ops *ops, const char *args, int from_tty)
{
remote_detach_1 (args, from_tty, 1);
}
before resuming inferior, because inferior was stopped and no RSP
traffic at that moment. */
if (!non_stop)
- remote_notif_process (¬if_client_stop);
+ remote_notif_process (rs->notif_state, ¬if_client_stop);
rs->last_sent_signal = siggnal;
rs->last_sent_step = step;
/* The identifier of the thread about this event */
ptid_t ptid;
+ /* The remote state this event is associated with. When the remote
+ connection, represented by a remote_state object, is closed,
+ all the associated stop_reply events should be released. */
+ struct remote_state *rs;
+
struct target_waitstatus ws;
/* Expedited registers. This makes remote debugging a bit more
static void
stop_reply_xfree (struct stop_reply *r)
{
- if (r != NULL)
- {
- VEC_free (cached_reg_t, r->regcache);
- xfree (r);
- }
+ notif_event_xfree ((struct notif_event *) r);
}
static void
remote_notif_stop_ack,
remote_notif_stop_can_get_pending_events,
remote_notif_stop_alloc_reply,
- NULL,
+ REMOTE_NOTIF_STOP,
};
/* A parameter to pass data in and out. */
struct stop_reply *output;
};
-/* Remove all queue elements meet the condition it checks. */
+/* Remove stop replies in the queue if its pid is equal to the given
+ inferior's pid. */
static int
-remote_notif_remove_all (QUEUE (stop_reply_p) *q,
- QUEUE_ITER (stop_reply_p) *iter,
- stop_reply_p event,
- void *data)
+remove_stop_reply_for_inferior (QUEUE (stop_reply_p) *q,
+ QUEUE_ITER (stop_reply_p) *iter,
+ stop_reply_p event,
+ void *data)
{
struct queue_iter_param *param = data;
struct inferior *inf = param->input;
- if (inf == NULL || ptid_get_pid (event->ptid) == inf->pid)
+ if (ptid_get_pid (event->ptid) == inf->pid)
{
stop_reply_xfree (event);
QUEUE_remove_elem (stop_reply_p, q, iter);
return 1;
}
-/* Discard all pending stop replies of inferior INF. If INF is NULL,
- discard everything. */
+/* Discard all pending stop replies of inferior INF. */
static void
discard_pending_stop_replies (struct inferior *inf)
{
int i;
struct queue_iter_param param;
- struct stop_reply *reply
- = (struct stop_reply *) notif_client_stop.pending_event;
+ struct stop_reply *reply;
+ struct remote_state *rs = get_remote_state ();
+ struct remote_notif_state *rns = rs->notif_state;
+
+ /* This function can be notified when an inferior exists. When the
+ target is not remote, the notification state is NULL. */
+ if (rs->remote_desc == NULL)
+ return;
+
+ reply = (struct stop_reply *) rns->pending_event[notif_client_stop.id];
/* Discard the in-flight notification. */
- if (reply != NULL
- && (inf == NULL
- || ptid_get_pid (reply->ptid) == inf->pid))
+ if (reply != NULL && ptid_get_pid (reply->ptid) == inf->pid)
{
stop_reply_xfree (reply);
- notif_client_stop.pending_event = NULL;
+ rns->pending_event[notif_client_stop.id] = NULL;
}
param.input = inf;
/* Discard the stop replies we have already pulled with
vStopped. */
QUEUE_iterate (stop_reply_p, stop_reply_queue,
- remote_notif_remove_all, ¶m);
+ remove_stop_reply_for_inferior, ¶m);
+}
+
+/* If its remote state is equal to the given remote state,
+ remove EVENT from the stop reply queue. */
+
+static int
+remove_stop_reply_of_remote_state (QUEUE (stop_reply_p) *q,
+ QUEUE_ITER (stop_reply_p) *iter,
+ stop_reply_p event,
+ void *data)
+{
+ struct queue_iter_param *param = data;
+ struct remote_state *rs = param->input;
+
+ if (event->rs == rs)
+ {
+ stop_reply_xfree (event);
+ QUEUE_remove_elem (stop_reply_p, q, iter);
+ }
+
+ return 1;
+}
+
+/* Discard the stop replies for RS in stop_reply_queue. */
+
+static void
+discard_pending_stop_replies_in_queue (struct remote_state *rs)
+{
+ struct queue_iter_param param;
+
+ param.input = rs;
+ param.output = NULL;
+ /* Discard the stop replies we have already pulled with
+ vStopped. */
+ QUEUE_iterate (stop_reply_p, stop_reply_queue,
+ remove_stop_reply_of_remote_state, ¶m);
}
/* A parameter to pass data in and out. */
char *p;
event->ptid = null_ptid;
+ event->rs = get_remote_state ();
event->ws.kind = TARGET_WAITKIND_IGNORE;
event->ws.value.integer = 0;
event->stopped_by_watchpoint_p = 0;
/* fall through */
case 'S': /* Old style status, just signal only. */
- event->ws.kind = TARGET_WAITKIND_STOPPED;
- event->ws.value.sig = (enum gdb_signal)
- (((fromhex (buf[1])) << 4) + (fromhex (buf[2])));
+ {
+ int sig;
+
+ event->ws.kind = TARGET_WAITKIND_STOPPED;
+ sig = (fromhex (buf[1]) << 4) + fromhex (buf[2]);
+ if (GDB_SIGNAL_FIRST <= sig && sig < GDB_SIGNAL_LAST)
+ event->ws.value.sig = (enum gdb_signal) sig;
+ else
+ event->ws.value.sig = GDB_SIGNAL_UNKNOWN;
+ }
break;
case 'W': /* Target exited. */
case 'X':
{
/* The remote process exited with a signal. */
event->ws.kind = TARGET_WAITKIND_SIGNALLED;
- event->ws.value.sig = (enum gdb_signal) value;
+ if (GDB_SIGNAL_FIRST <= value && value < GDB_SIGNAL_LAST)
+ event->ws.value.sig = (enum gdb_signal) value;
+ else
+ event->ws.value.sig = GDB_SIGNAL_UNKNOWN;
}
/* If no process is specified, assume inferior_ptid. */
{
struct remote_state *rs = get_remote_state ();
- if (nc->pending_event)
+ if (rs->notif_state->pending_event[nc->id] != NULL)
{
if (notif_debug)
fprintf_unfiltered (gdb_stdlog,
nc->name);
/* acknowledge */
- nc->ack (nc, rs->buf, nc->pending_event);
- nc->pending_event = NULL;
+ nc->ack (nc, rs->buf, rs->notif_state->pending_event[nc->id]);
+ rs->notif_state->pending_event[nc->id] = NULL;
while (1)
{
/* Acknowledge a pending stop reply that may have arrived in the
mean time. */
- if (notif_client_stop.pending_event != NULL)
+ if (rs->notif_state->pending_event[notif_client_stop.id] != NULL)
remote_notif_get_pending_events (¬if_client_stop);
/* If indeed we noticed a stop reply, we're done. */
str);
do_cleanups (old_chain);
}
- handle_notification (rs->buf);
+ handle_notification (rs->notif_state, rs->buf);
/* We're in sync now, rewait for the ack. */
tcount = 0;
}
if (is_notif != NULL)
*is_notif = 1;
- handle_notification (*buf);
+ handle_notification (rs->notif_state, *buf);
/* Notifications require no acknowledgement. */
int
remote_filename_p (const char *filename)
{
- return strncmp (filename, "remote:", 7) == 0;
+ return strncmp (filename,
+ REMOTE_SYSROOT_PREFIX,
+ sizeof (REMOTE_SYSROOT_PREFIX) - 1) == 0;
}
bfd *
{
char *text;
+ /* If current traceframe is not selected, don't bother the remote
+ stub. */
+ if (get_traceframe_number () < 0)
+ return NULL;
+
text = target_read_stralloc (¤t_target,
TARGET_OBJECT_TRACEFRAME_INFO, NULL);
if (text != NULL)