#include "remote-fileio.h"
#include "gdb/fileio.h"
+#include "gdb_stat.h"
#include "memory-map.h"
static void remote_resume (ptid_t ptid, int step,
enum target_signal siggnal);
-static void remote_async_resume (ptid_t ptid, int step,
- enum target_signal siggnal);
static void remote_open (char *name, int from_tty);
-static void remote_async_open (char *name, int from_tty);
static void extended_remote_open (char *name, int from_tty);
-static void extended_remote_async_open (char *name, int from_tty);
-static void remote_open_1 (char *, int, struct target_ops *, int extended_p,
- int async_p);
+static void remote_open_1 (char *, int, struct target_ops *, int extended_p);
static void remote_close (int quitting);
static void remote_store_registers (struct regcache *regcache, int regno);
static void remote_mourn (void);
-static void remote_async_mourn (void);
static void extended_remote_restart (void);
static int readchar (int timeout);
static ptid_t remote_wait (ptid_t ptid,
- struct target_waitstatus *status);
-static ptid_t remote_async_wait (ptid_t ptid,
- struct target_waitstatus *status);
+ struct target_waitstatus *status);
static void remote_kill (void);
-static void remote_async_kill (void);
static int tohex (int nib);
+static int remote_can_async_p (void);
+
+static int remote_is_async_p (void);
+
+static void remote_async (void (*callback) (enum inferior_event_type event_type,
+ void *context), void *context);
+
+static int remote_async_mask (int new_mask);
+
static void remote_detach (char *args, int from_tty);
static void remote_interrupt (int signo);
static void interrupt_query (void);
-static void set_thread (int, int);
+static void set_general_thread (struct ptid ptid);
+static void set_continue_thread (struct ptid ptid);
static int remote_thread_alive (ptid_t);
static void init_extended_remote_ops (void);
-static void remote_stop (void);
+static void remote_stop (ptid_t);
static int ishex (int ch, int *val);
static void remote_find_new_threads (void);
-static void record_currthread (int currthread);
+static void record_currthread (ptid_t currthread);
static int fromhex (int a);
skip calling getpkt. This flag is set when BUF contains a
stop reply packet and the target is not waiting. */
int cached_wait_status;
+
+ /* True, if in no ack mode. That is, neither GDB nor the stub will
+ expect acks from each other. The connection is assumed to be
+ reliable. */
+ int noack_mode;
};
/* This data could be associated with a target, but we do not always
long regnum; /* GDB's internal register number. */
LONGEST pnum; /* Remote protocol register number. */
int in_g_packet; /* Always part of G packet. */
- /* long size in bytes; == register_size (current_gdbarch, regnum);
+ /* long size in bytes; == register_size (target_gdbarch, regnum);
at present. */
- /* char *name; == gdbarch_register_name (current_gdbarch, regnum);
+ /* char *name; == gdbarch_register_name (target_gdbarch, regnum);
at present. */
};
static struct remote_arch_state *
get_remote_arch_state (void)
{
- return gdbarch_data (current_gdbarch, remote_gdbarch_data_handle);
+ return gdbarch_data (target_gdbarch, remote_gdbarch_data_handle);
}
/* Fetch the global remote target state. */
static struct packet_reg *
packet_reg_from_regnum (struct remote_arch_state *rsa, long regnum)
{
- if (regnum < 0 && regnum >= gdbarch_num_regs (current_gdbarch))
+ if (regnum < 0 && regnum >= gdbarch_num_regs (target_gdbarch))
return NULL;
else
{
packet_reg_from_pnum (struct remote_arch_state *rsa, LONGEST pnum)
{
int i;
- for (i = 0; i < gdbarch_num_regs (current_gdbarch); i++)
+ for (i = 0; i < gdbarch_num_regs (target_gdbarch); i++)
{
struct packet_reg *r = &rsa->regs[i];
if (r->pnum == pnum)
static struct target_ops extended_remote_ops;
-/* Temporary target ops. Just like the remote_ops and
- extended_remote_ops, but with asynchronous support. */
-static struct target_ops remote_async_ops;
-
-static struct target_ops extended_async_remote_ops;
+static int remote_async_mask_value = 1;
/* FIXME: cagney/1999-09-23: Even though getpkt was called with
``forever'' still use the normal timeout mechanism. This is
static int remote_address_size;
-/* Tempoary to track who currently owns the terminal. See
- target_async_terminal_* for more details. */
+/* Temporary to track who currently owns the terminal. See
+ remote_terminal_* for more details. */
static int remote_async_terminal_ours_p;
PACKET_qGetTLSAddr,
PACKET_qSupported,
PACKET_QPassSignals,
+ PACKET_qSearch_memory,
PACKET_vAttach,
PACKET_vRun,
+ PACKET_QStartNoAckMode,
PACKET_MAX
};
static struct async_signal_handler *sigint_remote_twice_token;
static struct async_signal_handler *sigint_remote_token;
-/* These are pointers to hook functions that may be set in order to
- modify resume/wait behavior for a particular architecture. */
-
-void (*deprecated_target_resume_hook) (void);
-void (*deprecated_target_wait_loop_hook) (void);
\f
+static ptid_t magic_null_ptid;
+static ptid_t not_sent_ptid;
+static ptid_t any_thread_ptid;
+
+/* These are the threads which we last sent to the remote system. The
+ TID member will be -1 for all or -2 for not sent yet. */
+
+static ptid_t general_thread;
+static ptid_t continue_thread;
-/* These are the threads which we last sent to the remote system.
- -1 for all or -2 for not sent yet. */
-static int general_thread;
-static int continue_thread;
/* Call this function as a result of
1) A halt indication (T packet) containing a thread id
*/
static void
-record_currthread (int currthread)
+record_currthread (ptid_t currthread)
{
general_thread = currthread;
/* If this is a new thread, add it to GDB's thread list.
If we leave it up to WFI to do this, bad things will happen. */
- if (!in_thread_list (pid_to_ptid (currthread)))
- add_thread (pid_to_ptid (currthread));
+ if (!in_thread_list (currthread))
+ {
+ if (ptid_equal (pid_to_ptid (ptid_get_pid (currthread)), inferior_ptid))
+ {
+ /* inferior_ptid has no thread member yet. This can happen
+ with the vAttach -> remote_wait,"TAAthread:" path if the
+ stub doesn't support qC. This is the first stop reported
+ after an attach, so this is the main thread. Update the
+ ptid in the thread list. */
+ struct thread_info *th = find_thread_pid (inferior_ptid);
+ inferior_ptid = th->ptid = currthread;
+ }
+ else if (ptid_equal (magic_null_ptid, inferior_ptid))
+ {
+ /* inferior_ptid is not set yet. This can happen with the
+ vRun -> remote_wait,"TAAthread:" path if the stub
+ doesn't support qC. This is the first stop reported
+ after an attach, so this is the main thread. Update the
+ ptid in the thread list. */
+ struct thread_info *th = find_thread_pid (inferior_ptid);
+ inferior_ptid = th->ptid = currthread;
+ }
+ else
+ /* This is really a new thread. Add it. */
+ add_thread (currthread);
+ }
}
static char *last_pass_packet;
}
}
-#define MAGIC_NULL_PID 42000
-
+/* If PTID is MAGIC_NULL_PTID, don't set any thread. If PTID is
+ MINUS_ONE_PTID, set the thread to -1, so the stub returns the
+ thread. If GEN is set, set the general thread, if not, then set
+ the step/continue thread. */
static void
-set_thread (int th, int gen)
+set_thread (struct ptid ptid, int gen)
{
struct remote_state *rs = get_remote_state ();
+ ptid_t state = gen ? general_thread : continue_thread;
char *buf = rs->buf;
- int state = gen ? general_thread : continue_thread;
+ char *endbuf = rs->buf + get_remote_packet_size ();
- if (state == th)
+ if (ptid_equal (state, ptid))
return;
- buf[0] = 'H';
- buf[1] = gen ? 'g' : 'c';
- if (th == MAGIC_NULL_PID)
+ *buf++ = 'H';
+ *buf++ = gen ? 'g' : 'c';
+ if (ptid_equal (ptid, magic_null_ptid))
+ xsnprintf (buf, endbuf - buf, "0");
+ else if (ptid_equal (ptid, any_thread_ptid))
+ xsnprintf (buf, endbuf - buf, "0");
+ else if (ptid_equal (ptid, minus_one_ptid))
+ xsnprintf (buf, endbuf - buf, "-1");
+ else
{
- buf[2] = '0';
- buf[3] = '\0';
+ int tid = ptid_get_tid (ptid);
+ if (tid < 0)
+ xsnprintf (buf, endbuf - buf, "-%x", -tid);
+ else
+ xsnprintf (buf, endbuf - buf, "%x", tid);
}
- else if (th < 0)
- xsnprintf (&buf[2], get_remote_packet_size () - 2, "-%x", -th);
- else
- xsnprintf (&buf[2], get_remote_packet_size () - 2, "%x", th);
- putpkt (buf);
+ putpkt (rs->buf);
getpkt (&rs->buf, &rs->buf_size, 0);
if (gen)
- general_thread = th;
+ general_thread = ptid;
else
- continue_thread = th;
+ continue_thread = ptid;
+}
+
+static void
+set_general_thread (struct ptid ptid)
+{
+ set_thread (ptid, 1);
+}
+
+static void
+set_continue_thread (struct ptid ptid)
+{
+ set_thread (ptid, 0);
}
+
\f
-/* Return nonzero if the thread TH is still alive on the remote system. */
+/* Return nonzero if the thread PTID is still alive on the remote
+ system. */
static int
remote_thread_alive (ptid_t ptid)
{
struct remote_state *rs = get_remote_state ();
- int tid = PIDGET (ptid);
+ int tid = ptid_get_tid (ptid);
+
+ if (ptid_equal (ptid, magic_null_ptid))
+ /* The main thread is always alive. */
+ return 1;
+
+ if (ptid_get_pid (ptid) != 0 && ptid_get_tid (ptid) == 0)
+ /* The main thread is always alive. This can happen after a
+ vAttach, if the remote side doesn't support
+ multi-threading. */
+ return 1;
if (tid < 0)
xsnprintf (rs->buf, get_remote_packet_size (), "T-%08x", -tid);
/* remote_find_new_threads retrieves the thread list and for each
thread in the list, looks up the thread in GDB's internal list,
- ading the thread if it does not already exist. This involves
+ adding the thread if it does not already exist. This involves
getting partial thread lists from the remote target so, polling the
quit_flag is required. */
static int
remote_newthread_step (threadref *ref, void *context)
{
- ptid_t ptid;
-
- ptid = pid_to_ptid (threadref_to_int (ref));
+ int pid = ptid_get_pid (inferior_ptid);
+ ptid_t ptid = ptid_build (pid, 0, threadref_to_int (ref));
if (!in_thread_list (ptid))
add_thread (ptid);
remote_current_thread (ptid_t oldpid)
{
struct remote_state *rs = get_remote_state ();
+ char *p = rs->buf;
+ int tid;
+ int pid;
putpkt ("qC");
getpkt (&rs->buf, &rs->buf_size, 0);
if (rs->buf[0] == 'Q' && rs->buf[1] == 'C')
- /* Use strtoul here, so we'll correctly parse values whose highest
- bit is set. The protocol carries them as a simple series of
- hex digits; in the absence of a sign, strtol will see such
- values as positive numbers out of range for signed 'long', and
- return LONG_MAX to indicate an overflow. */
- return pid_to_ptid (strtoul (&rs->buf[2], NULL, 16));
+ {
+ /* Use strtoul here, so we'll correctly parse values whose
+ highest bit is set. The protocol carries them as a simple
+ series of hex digits; in the absence of a sign, strtol will
+ see such values as positive numbers out of range for signed
+ 'long', and return LONG_MAX to indicate an overflow. */
+ tid = strtoul (&rs->buf[2], NULL, 16);
+ pid = ptid_get_pid (oldpid);
+ return ptid_build (pid, 0, tid);
+ }
else
return oldpid;
}
{
remote_threadlist_iterator (remote_newthread_step, 0,
CRAZY_MAX_THREADS);
- if (PIDGET (inferior_ptid) == MAGIC_NULL_PID) /* ack ack ack */
- inferior_ptid = remote_current_thread (inferior_ptid);
}
/*
struct remote_state *rs = get_remote_state ();
char *bufp;
int tid;
+ int pid;
+ ptid_t new_thread;
if (remote_desc == 0) /* paranoia */
error (_("Command can only be used when connected to the remote target."));
positive numbers out of range for signed 'long',
and return LONG_MAX to indicate an overflow. */
tid = strtoul (bufp, &bufp, 16);
- if (tid != 0 && !in_thread_list (pid_to_ptid (tid)))
- add_thread (pid_to_ptid (tid));
+ pid = ptid_get_pid (inferior_ptid);
+ new_thread = ptid_build (pid, 0, tid);
+ if (tid != 0 && !in_thread_list (new_thread))
+ add_thread (new_thread);
}
while (*bufp++ == ','); /* comma-separated list */
putpkt ("qsThreadInfo");
internal_error (__FILE__, __LINE__,
_("remote_threads_extra_info"));
+ if (ptid_equal (tp->ptid, magic_null_ptid)
+ || (ptid_get_pid (tp->ptid) != 0 && ptid_get_tid (tp->ptid) == 0))
+ /* This is the main thread which was added by GDB. The remote
+ server doesn't know about it. */
+ return NULL;
+
if (use_threadextra_query)
{
- xsnprintf (rs->buf, get_remote_packet_size (), "qThreadExtraInfo,%x",
- PIDGET (tp->ptid));
+ xsnprintf (rs->buf, get_remote_packet_size (), "qThreadExtraInfo,%lx",
+ ptid_get_tid (tp->ptid));
putpkt (rs->buf);
getpkt (&rs->buf, &rs->buf_size, 0);
if (rs->buf[0] != 0)
use_threadextra_query = 0;
set = TAG_THREADID | TAG_EXISTS | TAG_THREADNAME
| TAG_MOREDISPLAY | TAG_DISPLAY;
- int_to_threadref (&id, PIDGET (tp->ptid));
+ int_to_threadref (&id, ptid_get_tid (tp->ptid));
if (remote_get_threadinfo (&id, set, &threadinfo))
if (threadinfo.active)
{
segments[1] = data->segment_bases[1] + data_addr;
num_segments = 2;
}
+ /* If the object file has only one segment, assume that it is text
+ rather than data; main programs with no writable data are rare,
+ but programs with no code are useless. Of course the code might
+ have ended up in the data segment... to detect that we would need
+ the permissions here. */
+ else if (data && data->num_segments == 1)
+ {
+ segments[0] = data->segment_bases[0] + text_addr;
+ num_segments = 1;
+ }
/* There's no way to relocate by segment. */
else
do_segments = 0;
immediate_quit++; /* Allow user to interrupt it. */
- /* Ack any packet which the remote side has already sent. */
- serial_write (remote_desc, "+", 1);
-
/* Check whether the target is running now. */
putpkt ("?");
getpkt (&rs->buf, &rs->buf_size, 0);
strcpy (wait_status, rs->buf);
}
+ /* Start afresh. */
+ init_thread_list ();
+
/* Let the stub know that we want it to return the thread. */
- set_thread (-1, 0);
+ set_continue_thread (minus_one_ptid);
/* Without this, some commands which require an active target
(such as kill) won't work. This variable serves (at least)
These functions should be split out into seperate variables,
especially since GDB will someday have a notion of debugging
several processes. */
- inferior_ptid = pid_to_ptid (MAGIC_NULL_PID);
+ inferior_ptid = magic_null_ptid;
/* Now, if we have thread information, update inferior_ptid. */
inferior_ptid = remote_current_thread (inferior_ptid);
+ /* Always add the main thread. */
+ add_thread_silent (inferior_ptid);
+
get_offsets (); /* Get text, data & bss offsets. */
/* Use the previously fetched status. */
static void
remote_open (char *name, int from_tty)
{
- remote_open_1 (name, from_tty, &remote_ops, 0, 0);
-}
-
-/* Just like remote_open, but with asynchronous support. */
-static void
-remote_async_open (char *name, int from_tty)
-{
- remote_open_1 (name, from_tty, &remote_async_ops, 0, 1);
+ remote_open_1 (name, from_tty, &remote_ops, 0);
}
/* Open a connection to a remote debugger using the extended
static void
extended_remote_open (char *name, int from_tty)
{
- remote_open_1 (name, from_tty, &extended_remote_ops, 1 /*extended_p */,
- 0 /* async_p */);
-}
-
-/* Just like extended_remote_open, but with asynchronous support. */
-static void
-extended_remote_async_open (char *name, int from_tty)
-{
- remote_open_1 (name, from_tty, &extended_async_remote_ops,
- 1 /*extended_p */, 1 /* async_p */);
+ remote_open_1 (name, from_tty, &extended_remote_ops, 1 /*extended_p */);
}
/* Generic code for opening a connection to a remote target. */
/* If this is a function address, return the start of code
instead of any data function descriptor. */
- sym_addr = gdbarch_convert_from_func_ptr_addr (current_gdbarch,
+ sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch,
sym_addr,
¤t_target);
PACKET_qXfer_spu_write },
{ "QPassSignals", PACKET_DISABLE, remote_supported_packet,
PACKET_QPassSignals },
+ { "QStartNoAckMode", PACKET_DISABLE, remote_supported_packet,
+ PACKET_QStartNoAckMode },
};
static void
static void
-remote_open_1 (char *name, int from_tty, struct target_ops *target,
- int extended_p, int async_p)
+remote_open_1 (char *name, int from_tty, struct target_ops *target, int extended_p)
{
struct remote_state *rs = get_remote_state ();
+ struct packet_config *noack_config;
+
if (name == 0)
error (_("To open a remote debug connection, you need to specify what\n"
"serial device is attached to the remote system\n"
"(e.g. /dev/ttyS0, /dev/ttya, COM1, etc.)."));
/* See FIXME above. */
- if (!async_p)
+ if (!target_async_permitted)
wait_forever_enabled_p = 1;
/* If we're connected to a running target, target_preopen will kill it.
remote_query_supported or as they are needed. */
init_all_packet_configs ();
rs->explicit_packet_size = 0;
+ rs->noack_mode = 0;
- general_thread = -2;
- continue_thread = -2;
+ general_thread = not_sent_ptid;
+ continue_thread = not_sent_ptid;
/* Probe for ability to use "ThreadInfo" query, as required. */
use_threadinfo_query = 1;
use_threadextra_query = 1;
+ /* Ack any packet which the remote side has already sent. */
+ serial_write (remote_desc, "+", 1);
+
/* The first packet we send to the target is the optional "supported
packets" request. If the target can answer this, it will tell us
which later probes to skip. */
remote_query_supported ();
+ /* Next, we possibly activate noack mode.
+
+ If the QStartNoAckMode packet configuration is set to AUTO,
+ enable noack mode if the stub reported a wish for it with
+ qSupported.
+
+ If set to TRUE, then enable noack mode even if the stub didn't
+ report it in qSupported. If the stub doesn't reply OK, the
+ session ends with an error.
+
+ If FALSE, then don't activate noack mode, regardless of what the
+ stub claimed should be the default with qSupported. */
+
+ noack_config = &remote_protocol_packets[PACKET_QStartNoAckMode];
+
+ if (noack_config->detect == AUTO_BOOLEAN_TRUE
+ || (noack_config->detect == AUTO_BOOLEAN_AUTO
+ && noack_config->support == PACKET_ENABLE))
+ {
+ putpkt ("QStartNoAckMode");
+ getpkt (&rs->buf, &rs->buf_size, 0);
+ if (packet_ok (rs->buf, noack_config) == PACKET_OK)
+ rs->noack_mode = 1;
+ }
+
/* Next, if the target can specify a description, read it. We do
this before anything involving memory or registers. */
target_find_description ();
- if (async_p)
+ if (target_async_permitted)
{
/* With this target we start out by owning the terminal. */
remote_async_terminal_ours_p = 1;
if (ex.reason < 0)
{
pop_target ();
- if (async_p)
+ if (target_async_permitted)
wait_forever_enabled_p = 1;
throw_exception (ex);
}
}
- if (async_p)
+ if (target_async_permitted)
wait_forever_enabled_p = 1;
if (extended_p)
extended_remote_attach_1 (struct target_ops *target, char *args, int from_tty)
{
struct remote_state *rs = get_remote_state ();
- pid_t pid;
+ int pid;
char *dummy;
+ char *wait_status = NULL;
if (!args)
error_no_arg (_("process-id to attach"));
printf_unfiltered (_("Attached to %s\n"),
target_pid_to_str (pid_to_ptid (pid)));
- /* We have a wait response; reuse it. */
- rs->cached_wait_status = 1;
+ /* Save the reply for later. */
+ wait_status = alloca (strlen (rs->buf) + 1);
+ strcpy (wait_status, rs->buf);
}
else if (remote_protocol_packets[PACKET_vAttach].support == PACKET_DISABLE)
error (_("This target does not support attaching to a process"));
target_mark_running (target);
inferior_ptid = pid_to_ptid (pid);
+
+ /* Now, if we have thread information, update inferior_ptid. */
+ inferior_ptid = remote_current_thread (inferior_ptid);
+
+ /* Now, add the main thread to the thread list. */
+ add_thread_silent (inferior_ptid);
+
attach_flag = 1;
+
+ /* Next, if the target can specify a description, read it. We do
+ this before anything involving memory or registers. */
+ target_find_description ();
+
+ /* Use the previously fetched status. */
+ gdb_assert (wait_status != NULL);
+ strcpy (rs->buf, wait_status);
+ rs->cached_wait_status = 1;
}
static void
extended_remote_attach_1 (&extended_remote_ops, args, from_tty);
}
-static void
-extended_async_remote_attach (char *args, int from_tty)
-{
- extended_remote_attach_1 (&extended_async_remote_ops, args, from_tty);
-}
-
/* Convert hex digit A to a number. */
static int
/* Resume the remote inferior by using a "vCont" packet. The thread
to be resumed is PTID; STEP and SIGGNAL indicate whether the
- resumed thread should be single-stepped and/or signalled. If PTID's
- PID is -1, then all threads are resumed; the thread to be stepped and/or
- signalled is given in the global INFERIOR_PTID. This function returns
- non-zero iff it resumes the inferior.
+ resumed thread should be single-stepped and/or signalled. If PTID
+ equals minus_one_ptid, then all threads are resumed; the thread to
+ be stepped and/or signalled is given in the global INFERIOR_PTID.
+ This function returns non-zero iff it resumes the inferior.
This function issues a strict subset of all possible vCont commands at the
moment. */
remote_vcont_resume (ptid_t ptid, int step, enum target_signal siggnal)
{
struct remote_state *rs = get_remote_state ();
- int pid = PIDGET (ptid);
char *outbuf;
struct cleanup *old_cleanup;
about overflowing BUF. Should there be a generic
"multi-part-packet" packet? */
- if (PIDGET (inferior_ptid) == MAGIC_NULL_PID)
+ if (ptid_equal (ptid, magic_null_ptid))
{
- /* MAGIC_NULL_PTID means that we don't have any active threads, so we
- don't have any PID numbers the inferior will understand. Make sure
- to only send forms that do not specify a PID. */
+ /* MAGIC_NULL_PTID means that we don't have any active threads,
+ so we don't have any TID numbers the inferior will
+ understand. Make sure to only send forms that do not specify
+ a TID. */
if (step && siggnal != TARGET_SIGNAL_0)
outbuf = xstrprintf ("vCont;S%02x", siggnal);
else if (step)
else
outbuf = xstrprintf ("vCont;c");
}
- else if (pid == -1)
+ else if (ptid_equal (ptid, minus_one_ptid))
{
/* Resume all threads, with preference for INFERIOR_PTID. */
+ int tid = ptid_get_tid (inferior_ptid);
if (step && siggnal != TARGET_SIGNAL_0)
- outbuf = xstrprintf ("vCont;S%02x:%x;c", siggnal,
- PIDGET (inferior_ptid));
+ outbuf = xstrprintf ("vCont;S%02x:%x;c", siggnal, tid);
else if (step)
- outbuf = xstrprintf ("vCont;s:%x;c", PIDGET (inferior_ptid));
+ outbuf = xstrprintf ("vCont;s:%x;c", tid);
else if (siggnal != TARGET_SIGNAL_0)
- outbuf = xstrprintf ("vCont;C%02x:%x;c", siggnal,
- PIDGET (inferior_ptid));
+ outbuf = xstrprintf ("vCont;C%02x:%x;c", siggnal, tid);
else
outbuf = xstrprintf ("vCont;c");
}
else
{
/* Scheduler locking; resume only PTID. */
+ int tid = ptid_get_tid (ptid);
if (step && siggnal != TARGET_SIGNAL_0)
- outbuf = xstrprintf ("vCont;S%02x:%x", siggnal, pid);
+ outbuf = xstrprintf ("vCont;S%02x:%x", siggnal, tid);
else if (step)
- outbuf = xstrprintf ("vCont;s:%x", pid);
+ outbuf = xstrprintf ("vCont;s:%x", tid);
else if (siggnal != TARGET_SIGNAL_0)
- outbuf = xstrprintf ("vCont;C%02x:%x", siggnal, pid);
+ outbuf = xstrprintf ("vCont;C%02x:%x", siggnal, tid);
else
- outbuf = xstrprintf ("vCont;c:%x", pid);
+ outbuf = xstrprintf ("vCont;c:%x", tid);
}
gdb_assert (outbuf && strlen (outbuf) < get_remote_packet_size ());
{
struct remote_state *rs = get_remote_state ();
char *buf;
- int pid = PIDGET (ptid);
last_sent_signal = siggnal;
last_sent_step = step;
- /* A hook for when we need to do something at the last moment before
- resumption. */
- if (deprecated_target_resume_hook)
- (*deprecated_target_resume_hook) ();
-
/* Update the inferior on signals to silently pass, if they've changed. */
remote_pass_signals ();
/* The vCont packet doesn't need to specify threads via Hc. */
if (remote_vcont_resume (ptid, step, siggnal))
- return;
+ goto done;
- /* All other supported resume packets do use Hc, so call set_thread. */
- if (pid == -1)
- set_thread (0, 0); /* Run any thread. */
+ /* All other supported resume packets do use Hc, so set the continue
+ thread. */
+ if (ptid_equal (ptid, minus_one_ptid))
+ set_continue_thread (any_thread_ptid);
else
- set_thread (pid, 0); /* Run this thread. */
+ set_continue_thread (ptid);
buf = rs->buf;
if (siggnal != TARGET_SIGNAL_0)
strcpy (buf, step ? "s" : "c");
putpkt (buf);
-}
-
-/* Same as remote_resume, but with async support. */
-static void
-remote_async_resume (ptid_t ptid, int step, enum target_signal siggnal)
-{
- remote_resume (ptid, step, siggnal);
+ done:
/* We are about to start executing the inferior, let's register it
with the event loop. NOTE: this is the one place where all the
execution commands end up. We could alternatively do this in each
NOT asynchronously. */
if (target_can_async_p ())
target_async (inferior_event_handler, 0);
- /* Tell the world that the target is now executing. */
- /* FIXME: cagney/1999-09-23: Is it the targets responsibility to set
- this? Instead, should the client of target just assume (for
- async targets) that the target is going to start executing? Is
- this information already found in the continuation block? */
- if (target_is_async_p ())
- target_executing = 1;
}
\f
static void
initialize_sigint_signal_handler (void)
{
- sigint_remote_token =
- create_async_signal_handler (async_remote_interrupt, NULL);
signal (SIGINT, handle_remote_sigint);
}
handle_remote_sigint (int sig)
{
signal (sig, handle_remote_sigint_twice);
- sigint_remote_twice_token =
- create_async_signal_handler (async_remote_interrupt_twice, NULL);
mark_async_signal_handler_wrapper (sigint_remote_token);
}
static void
handle_remote_sigint_twice (int sig)
{
- signal (sig, handle_sigint);
- sigint_remote_twice_token =
- create_async_signal_handler (inferior_event_handler_wrapper, NULL);
+ signal (sig, handle_remote_sigint);
mark_async_signal_handler_wrapper (sigint_remote_twice_token);
}
if (remote_debug)
fprintf_unfiltered (gdb_stdlog, "remote_interrupt called\n");
- target_stop ();
+ target_stop (inferior_ptid);
}
/* Perform interrupt, if the first attempt did not succeed. Just give
{
if (remote_debug)
fprintf_unfiltered (gdb_stdlog, "remote_interrupt_twice called\n");
- /* Do something only if the target was not killed by the previous
- cntl-C. */
- if (target_executing)
- {
- interrupt_query ();
- signal (SIGINT, handle_remote_sigint);
- }
+
+ interrupt_query ();
}
/* Reinstall the usual SIGINT handlers, after the target has
cleanup_sigint_signal_handler (void *dummy)
{
signal (SIGINT, handle_sigint);
- if (sigint_remote_twice_token)
- delete_async_signal_handler (&sigint_remote_twice_token);
- if (sigint_remote_token)
- delete_async_signal_handler (&sigint_remote_token);
}
/* Send ^C to target to halt it. Target will respond, and send us a
/* If this doesn't work, try more severe steps. */
signal (signo, remote_interrupt_twice);
- if (remote_debug)
- fprintf_unfiltered (gdb_stdlog, "remote_interrupt called\n");
-
- target_stop ();
+ gdb_call_async_signal_handler (sigint_remote_token, 1);
}
/* The user typed ^C twice. */
remote_interrupt_twice (int signo)
{
signal (signo, ofunc);
- interrupt_query ();
+ gdb_call_async_signal_handler (sigint_remote_twice_token, 1);
signal (signo, remote_interrupt);
}
interrupt is requested, either by the command line or the GUI, we
will eventually end up here. */
static void
-remote_stop (void)
+remote_stop (ptid_t ptid)
{
/* Send a break or a ^C, depending on user preference. */
if (remote_debug)
Give up (and stop debugging it)? "))
{
target_mourn_inferior ();
+ signal (SIGINT, handle_sigint);
deprecated_throw_reason (RETURN_QUIT);
}
is required. */
static void
-remote_async_terminal_inferior (void)
+remote_terminal_inferior (void)
{
+ if (!target_async_permitted)
+ /* Nothing to do. */
+ return;
+
/* FIXME: cagney/1999-09-27: Shouldn't need to test for
sync_execution here. This function should only be called when
GDB is resuming the inferior in the forground. A background
delete_file_handler (input_fd);
remote_async_terminal_ours_p = 0;
initialize_sigint_signal_handler ();
- /* NOTE: At this point we could also register our selves as the
- recipient of all input. Any characters typed could then be
- passed on down to the target. */
-}
-
-static void
-remote_async_terminal_ours (void)
-{
- /* See FIXME in remote_async_terminal_inferior. */
- if (!sync_execution)
- return;
- /* See FIXME in remote_async_terminal_inferior. */
- if (remote_async_terminal_ours_p)
- return;
- cleanup_sigint_signal_handler (NULL);
- add_file_handler (input_fd, stdin_event_handler, 0);
- remote_async_terminal_ours_p = 1;
-}
-
-/* If nonzero, ignore the next kill. */
-
-int kill_kludge;
-
-void
-remote_console_output (char *msg)
-{
- char *p;
-
- for (p = msg; p[0] && p[1]; p += 2)
- {
- char tb[2];
- char c = fromhex (p[0]) * 16 + fromhex (p[1]);
- tb[0] = c;
- tb[1] = 0;
- fputs_unfiltered (tb, gdb_stdtarg);
- }
- gdb_flush (gdb_stdtarg);
-}
-
-/* Wait until the remote machine stops, then return,
- storing status in STATUS just as `wait' would.
- Returns "pid", which in the case of a multi-threaded
- remote OS, is the thread-id. */
-
-static ptid_t
-remote_wait (ptid_t ptid, struct target_waitstatus *status)
-{
- struct remote_state *rs = get_remote_state ();
- struct remote_arch_state *rsa = get_remote_arch_state ();
- ULONGEST thread_num = -1;
- ULONGEST addr;
- int solibs_changed = 0;
-
- status->kind = TARGET_WAITKIND_EXITED;
- status->value.integer = 0;
-
- while (1)
- {
- char *buf, *p;
-
- if (rs->cached_wait_status)
- /* Use the cached wait status, but only once. */
- rs->cached_wait_status = 0;
- else
- {
- ofunc = signal (SIGINT, remote_interrupt);
- /* If the user hit C-c before this packet, or between packets,
- pretend that it was hit right here. */
- if (quit_flag)
- {
- quit_flag = 0;
- remote_interrupt (SIGINT);
- }
- getpkt (&rs->buf, &rs->buf_size, 1);
- signal (SIGINT, ofunc);
- }
-
- buf = rs->buf;
-
- /* This is a hook for when we need to do something (perhaps the
- collection of trace data) every time the target stops. */
- if (deprecated_target_wait_loop_hook)
- (*deprecated_target_wait_loop_hook) ();
-
- remote_stopped_by_watchpoint_p = 0;
-
- switch (buf[0])
- {
- case 'E': /* Error of some sort. */
- /* We're out of sync with the target now. Did it continue or not?
- Not is more likely, so report a stop. */
- warning (_("Remote failure reply: %s"), buf);
- status->kind = TARGET_WAITKIND_STOPPED;
- status->value.sig = TARGET_SIGNAL_0;
- goto got_status;
- case 'F': /* File-I/O request. */
- remote_fileio_request (buf);
- continue;
- case 'T': /* Status with PC, SP, FP, ... */
- {
- gdb_byte regs[MAX_REGISTER_SIZE];
-
- /* Expedited reply, containing Signal, {regno, reg} repeat. */
- /* format is: 'Tssn...:r...;n...:r...;n...:r...;#cc', where
- ss = signal number
- n... = register number
- r... = register contents
- */
- p = &buf[3]; /* after Txx */
-
- while (*p)
- {
- char *p1;
- char *p_temp;
- int fieldsize;
- LONGEST pnum = 0;
-
- /* If the packet contains a register number save it in
- pnum and set p1 to point to the character following
- it. Otherwise p1 points to p. */
-
- /* If this packet is an awatch packet, don't parse the
- 'a' as a register number. */
-
- if (strncmp (p, "awatch", strlen("awatch")) != 0)
- {
- /* Read the ``P'' register number. */
- pnum = strtol (p, &p_temp, 16);
- p1 = p_temp;
- }
- else
- p1 = p;
-
- if (p1 == p) /* No register number present here. */
- {
- p1 = strchr (p, ':');
- if (p1 == NULL)
- error (_("Malformed packet(a) (missing colon): %s\n\
-Packet: '%s'\n"),
- p, buf);
- if (strncmp (p, "thread", p1 - p) == 0)
- {
- p_temp = unpack_varlen_hex (++p1, &thread_num);
- record_currthread (thread_num);
- p = p_temp;
- }
- else if ((strncmp (p, "watch", p1 - p) == 0)
- || (strncmp (p, "rwatch", p1 - p) == 0)
- || (strncmp (p, "awatch", p1 - p) == 0))
- {
- remote_stopped_by_watchpoint_p = 1;
- p = unpack_varlen_hex (++p1, &addr);
- remote_watch_data_address = (CORE_ADDR)addr;
- }
- else if (strncmp (p, "library", p1 - p) == 0)
- {
- p1++;
- p_temp = p1;
- while (*p_temp && *p_temp != ';')
- p_temp++;
-
- solibs_changed = 1;
- p = p_temp;
- }
- else
- {
- /* Silently skip unknown optional info. */
- p_temp = strchr (p1 + 1, ';');
- if (p_temp)
- p = p_temp;
- }
- }
- else
- {
- struct packet_reg *reg = packet_reg_from_pnum (rsa, pnum);
- p = p1;
-
- if (*p++ != ':')
- error (_("Malformed packet(b) (missing colon): %s\n\
-Packet: '%s'\n"),
- p, buf);
-
- if (reg == NULL)
- error (_("Remote sent bad register number %s: %s\n\
-Packet: '%s'\n"),
- phex_nz (pnum, 0), p, buf);
-
- fieldsize = hex2bin (p, regs,
- register_size (current_gdbarch,
- reg->regnum));
- p += 2 * fieldsize;
- if (fieldsize < register_size (current_gdbarch,
- reg->regnum))
- warning (_("Remote reply is too short: %s"), buf);
- regcache_raw_supply (get_current_regcache (),
- reg->regnum, regs);
- }
-
- if (*p++ != ';')
- error (_("Remote register badly formatted: %s\nhere: %s"),
- buf, p);
- }
- }
- /* fall through */
- case 'S': /* Old style status, just signal only. */
- if (solibs_changed)
- status->kind = TARGET_WAITKIND_LOADED;
- else
- {
- status->kind = TARGET_WAITKIND_STOPPED;
- status->value.sig = (enum target_signal)
- (((fromhex (buf[1])) << 4) + (fromhex (buf[2])));
- }
-
- if (buf[3] == 'p')
- {
- thread_num = strtol ((const char *) &buf[4], NULL, 16);
- record_currthread (thread_num);
- }
- goto got_status;
- case 'W': /* Target exited. */
- {
- /* The remote process exited. */
- status->kind = TARGET_WAITKIND_EXITED;
- status->value.integer = (fromhex (buf[1]) << 4) + fromhex (buf[2]);
- goto got_status;
- }
- case 'X':
- status->kind = TARGET_WAITKIND_SIGNALLED;
- status->value.sig = (enum target_signal)
- (((fromhex (buf[1])) << 4) + (fromhex (buf[2])));
- kill_kludge = 1;
+ /* NOTE: At this point we could also register our selves as the
+ recipient of all input. Any characters typed could then be
+ passed on down to the target. */
+}
- goto got_status;
- case 'O': /* Console output. */
- remote_console_output (buf + 1);
- continue;
- case '\0':
- if (last_sent_signal != TARGET_SIGNAL_0)
- {
- /* Zero length reply means that we tried 'S' or 'C' and
- the remote system doesn't support it. */
- target_terminal_ours_for_output ();
- printf_filtered
- ("Can't send signals to this remote system. %s not sent.\n",
- target_signal_to_name (last_sent_signal));
- last_sent_signal = TARGET_SIGNAL_0;
- target_terminal_inferior ();
+static void
+remote_terminal_ours (void)
+{
+ if (!target_async_permitted)
+ /* Nothing to do. */
+ return;
- strcpy ((char *) buf, last_sent_step ? "s" : "c");
- putpkt ((char *) buf);
- continue;
- }
- /* else fallthrough */
- default:
- warning (_("Invalid remote reply: %s"), buf);
- continue;
- }
- }
-got_status:
- if (thread_num != -1)
+ /* See FIXME in remote_terminal_inferior. */
+ if (!sync_execution)
+ return;
+ /* See FIXME in remote_terminal_inferior. */
+ if (remote_async_terminal_ours_p)
+ return;
+ cleanup_sigint_signal_handler (NULL);
+ add_file_handler (input_fd, stdin_event_handler, 0);
+ remote_async_terminal_ours_p = 1;
+}
+
+void
+remote_console_output (char *msg)
+{
+ char *p;
+
+ for (p = msg; p[0] && p[1]; p += 2)
{
- return pid_to_ptid (thread_num);
+ char tb[2];
+ char c = fromhex (p[0]) * 16 + fromhex (p[1]);
+ tb[0] = c;
+ tb[1] = 0;
+ fputs_unfiltered (tb, gdb_stdtarg);
}
- return inferior_ptid;
+ gdb_flush (gdb_stdtarg);
}
-/* Async version of remote_wait. */
+/* Wait until the remote machine stops, then return,
+ storing status in STATUS just as `wait' would. */
+
static ptid_t
-remote_async_wait (ptid_t ptid, struct target_waitstatus *status)
+remote_wait (ptid_t ptid, struct target_waitstatus *status)
{
struct remote_state *rs = get_remote_state ();
struct remote_arch_state *rsa = get_remote_arch_state ();
ULONGEST thread_num = -1;
+ ULONGEST process_num = -1;
ULONGEST addr;
int solibs_changed = 0;
status->kind = TARGET_WAITKIND_EXITED;
status->value.integer = 0;
- remote_stopped_by_watchpoint_p = 0;
-
while (1)
{
char *buf, *p;
buf = rs->buf;
- /* This is a hook for when we need to do something (perhaps the
- collection of trace data) every time the target stops. */
- if (deprecated_target_wait_loop_hook)
- (*deprecated_target_wait_loop_hook) ();
+ remote_stopped_by_watchpoint_p = 0;
switch (buf[0])
{
char *p1;
char *p_temp;
int fieldsize;
- long pnum = 0;
+ LONGEST pnum = 0;
/* If the packet contains a register number, save it
in pnum and set p1 to point to the character
following it. Otherwise p1 points to p. */
- /* If this packet is an awatch packet, don't parse the 'a'
- as a register number. */
+ /* If this packet is an awatch packet, don't parse the
+ 'a' as a register number. */
if (strncmp (p, "awatch", strlen("awatch")) != 0)
{
- /* Read the register number. */
+ /* Read the ``P'' register number. */
pnum = strtol (p, &p_temp, 16);
p1 = p_temp;
}
if (strncmp (p, "thread", p1 - p) == 0)
{
p_temp = unpack_varlen_hex (++p1, &thread_num);
- record_currthread (thread_num);
p = p_temp;
}
else if ((strncmp (p, "watch", p1 - p) == 0)
p = p_temp;
}
}
-
else
{
struct packet_reg *reg = packet_reg_from_pnum (rsa, pnum);
p = p1;
- if (*p++ != ':')
+
+ if (*p != ':')
error (_("Malformed packet(b) (missing colon): %s\n\
Packet: '%s'\n"),
p, buf);
+ ++p;
if (reg == NULL)
- error (_("Remote sent bad register number %ld: %s\n\
+ error (_("Remote sent bad register number %s: %s\n\
Packet: '%s'\n"),
- pnum, p, buf);
+ phex_nz (pnum, 0), p, buf);
fieldsize = hex2bin (p, regs,
- register_size (current_gdbarch,
+ register_size (target_gdbarch,
reg->regnum));
p += 2 * fieldsize;
- if (fieldsize < register_size (current_gdbarch,
+ if (fieldsize < register_size (target_gdbarch,
reg->regnum))
warning (_("Remote reply is too short: %s"), buf);
regcache_raw_supply (get_current_regcache (),
reg->regnum, regs);
}
- if (*p++ != ';')
+ if (*p != ';')
error (_("Remote register badly formatted: %s\nhere: %s"),
buf, p);
+ ++p;
}
}
/* fall through */
status->value.sig = (enum target_signal)
(((fromhex (buf[1])) << 4) + (fromhex (buf[2])));
}
-
- if (buf[3] == 'p')
- {
- thread_num = strtol ((const char *) &buf[4], NULL, 16);
- record_currthread (thread_num);
- }
goto got_status;
case 'W': /* Target exited. */
{
status->kind = TARGET_WAITKIND_SIGNALLED;
status->value.sig = (enum target_signal)
(((fromhex (buf[1])) << 4) + (fromhex (buf[2])));
- kill_kludge = 1;
goto got_status;
case 'O': /* Console output. */
remote_console_output (buf + 1);
- /* Return immediately to the event loop. The event loop will
- still be waiting on the inferior afterwards. */
- status->kind = TARGET_WAITKIND_IGNORE;
- goto got_status;
+ if (target_can_async_p ())
+ {
+ /* Return immediately to the event loop. The event loop
+ will still be waiting on the inferior afterwards. */
+ status->kind = TARGET_WAITKIND_IGNORE;
+ goto got_status;
+ }
+ else
+ continue;
case '\0':
if (last_sent_signal != TARGET_SIGNAL_0)
{
got_status:
if (thread_num != -1)
{
- return pid_to_ptid (thread_num);
+ ptid_t ptid;
+ ptid = ptid_build (ptid_get_pid (inferior_ptid), 0, thread_num);
+ record_currthread (ptid);
+ return ptid;
}
+
return inferior_ptid;
}
struct remote_arch_state *rsa = get_remote_arch_state ();
int i;
- set_thread (PIDGET (inferior_ptid), 1);
+ set_general_thread (inferior_ptid);
if (regnum >= 0)
{
struct remote_arch_state *rsa = get_remote_arch_state ();
int i;
- set_thread (PIDGET (inferior_ptid), 1);
+ set_general_thread (inferior_ptid);
if (regnum >= 0)
{
int address_size = remote_address_size;
/* If "remoteaddresssize" was not set, default to target address size. */
if (!address_size)
- address_size = gdbarch_addr_bit (current_gdbarch);
+ address_size = gdbarch_addr_bit (target_gdbarch);
if (address_size > 0
&& address_size < (sizeof (ULONGEST) * 8))
if (serial_write (remote_desc, buf2, p - buf2))
perror_with_name (_("putpkt: write failed"));
+ /* If this is a no acks version of the remote protocol, send the
+ packet and move on. */
+ if (rs->noack_mode)
+ break;
+
/* Read until either a timeout occurs (-2) or '+' is read. */
while (1)
{
}
#endif
}
+ return 0;
}
/* Come here after finding the start of a frame when we expected an
long bc;
int c;
char *buf = *buf_p;
+ struct remote_state *rs = get_remote_state ();
csum = 0;
bc = 0;
return -1;
}
+ /* Don't recompute the checksum; with no ack packets we
+ don't have any way to indicate a packet retransmission
+ is necessary. */
+ if (rs->noack_mode)
+ return bc;
+
pktcsum = (fromhex (check_0) << 4) | fromhex (check_1);
if (csum == pktcsum)
return bc;
fputstrn_unfiltered (*buf, val, 0, gdb_stdlog);
fprintf_unfiltered (gdb_stdlog, "\n");
}
- serial_write (remote_desc, "+", 1);
+
+ /* Skip the ack char if we're in no-ack mode. */
+ if (!rs->noack_mode)
+ serial_write (remote_desc, "+", 1);
return val;
}
/* Try the whole thing again. */
retry:
- serial_write (remote_desc, "-", 1);
+ /* Skip the nack char if we're in no-ack mode. */
+ if (!rs->noack_mode)
+ serial_write (remote_desc, "-", 1);
}
/* We have tried hard enough, and just can't receive the packet.
Give up. */
printf_unfiltered (_("Ignoring packet error, continuing...\n"));
- serial_write (remote_desc, "+", 1);
+
+ /* Skip the ack char if we're in no-ack mode. */
+ if (!rs->noack_mode)
+ serial_write (remote_desc, "+", 1);
return -1;
}
\f
static void
remote_kill (void)
-{
- /* For some mysterious reason, wait_for_inferior calls kill instead of
- mourn after it gets TARGET_WAITKIND_SIGNALLED. Work around it. */
- if (kill_kludge)
- {
- kill_kludge = 0;
- target_mourn_inferior ();
- return;
- }
-
- /* Use catch_errors so the user can quit from gdb even when we aren't on
- speaking terms with the remote system. */
- catch_errors ((catch_errors_ftype *) putpkt, "k", "", RETURN_MASK_ERROR);
-
- /* Don't wait for it to die. I'm not really sure it matters whether
- we do or not. For the existing stubs, kill is a noop. */
- target_mourn_inferior ();
-}
-
-/* Async version of remote_kill. */
-static void
-remote_async_kill (void)
{
/* Unregister the file descriptor from the event loop. */
if (target_is_async_p ())
serial_async (remote_desc, NULL, 0);
- /* For some mysterious reason, wait_for_inferior calls kill instead of
- mourn after it gets TARGET_WAITKIND_SIGNALLED. Work around it. */
- if (kill_kludge)
- {
- kill_kludge = 0;
- target_mourn_inferior ();
- return;
- }
-
/* Use catch_errors so the user can quit from gdb even when we
aren't on speaking terms with the remote system. */
catch_errors ((catch_errors_ftype *) putpkt, "k", "", RETURN_MASK_ERROR);
remote_mourn_1 (&remote_ops);
}
-static void
-remote_async_mourn (void)
-{
- remote_mourn_1 (&remote_async_ops);
-}
-
/* Worker function for remote_mourn. */
static void
remote_mourn_1 (struct target_ops *target)
/* Assume that the target has been restarted. Set inferior_ptid
so that bits of core GDB realizes there's something here, e.g.,
so that the user can say "kill" again. */
- inferior_ptid = pid_to_ptid (MAGIC_NULL_PID);
+ inferior_ptid = remote_current_thread (magic_null_ptid);
+ add_thread_silent (inferior_ptid);
}
else
{
extended_remote_mourn_1 (&extended_remote_ops);
}
-static void
-extended_async_remote_mourn (void)
-{
- extended_remote_mourn_1 (&extended_async_remote_ops);
-}
-
static int
extended_remote_run (char *args)
{
static void
extended_remote_create_inferior_1 (char *exec_file, char *args,
- char **env, int from_tty,
- int async_p)
+ char **env, int from_tty)
{
/* If running asynchronously, register the target file descriptor
with the event loop. */
- if (async_p && target_can_async_p ())
+ if (target_can_async_p ())
target_async (inferior_event_handler, 0);
/* Now restart the remote server. */
extended_remote_restart ();
}
+ /* Clean up from the last time we ran, before we mark the target
+ running again. This will mark breakpoints uninserted, and
+ get_offsets may insert breakpoints. */
+ init_thread_list ();
+ init_wait_for_inferior ();
+
/* Now mark the inferior as running before we do anything else. */
attach_flag = 0;
- inferior_ptid = pid_to_ptid (MAGIC_NULL_PID);
- if (async_p)
- target_mark_running (&extended_async_remote_ops);
- else
- target_mark_running (&extended_remote_ops);
+ inferior_ptid = magic_null_ptid;
+
+ add_thread_silent (inferior_ptid);
+
+ target_mark_running (&extended_remote_ops);
/* Get updated offsets, if the stub uses qOffsets. */
get_offsets ();
-
- /* Clean up from the last time we were running. */
- init_thread_list ();
- init_wait_for_inferior ();
}
static void
extended_remote_create_inferior (char *exec_file, char *args,
char **env, int from_tty)
{
- extended_remote_create_inferior_1 (exec_file, args, env, from_tty, 0);
-}
-
-static void
-extended_remote_async_create_inferior (char *exec_file, char *args,
- char **env, int from_tty)
-{
- extended_remote_create_inferior_1 (exec_file, args, env, from_tty, 1);
+ extended_remote_create_inferior_1 (exec_file, args, env, from_tty);
}
\f
static int
remote_insert_breakpoint (struct bp_target_info *bp_tgt)
{
- CORE_ADDR addr = bp_tgt->placed_address;
- struct remote_state *rs = get_remote_state ();
-
/* Try the "Z" s/w breakpoint packet if it is not already disabled.
If it succeeds, then set the support to PACKET_ENABLE. If it
fails, and the user has explicitly requested the Z support then
if (remote_protocol_packets[PACKET_Z0].support != PACKET_DISABLE)
{
- char *p = rs->buf;
+ CORE_ADDR addr = bp_tgt->placed_address;
+ struct remote_state *rs;
+ char *p;
+ int bpsize;
+
+ gdbarch_breakpoint_from_pc (target_gdbarch, &addr, &bpsize);
+
+ rs = get_remote_state ();
+ p = rs->buf;
*(p++) = 'Z';
*(p++) = '0';
*(p++) = ',';
- gdbarch_breakpoint_from_pc
- (current_gdbarch, &bp_tgt->placed_address, &bp_tgt->placed_size);
- addr = (ULONGEST) remote_address_masked (bp_tgt->placed_address);
+ addr = (ULONGEST) remote_address_masked (addr);
p += hexnumstr (p, addr);
- sprintf (p, ",%d", bp_tgt->placed_size);
+ sprintf (p, ",%d", bpsize);
putpkt (rs->buf);
getpkt (&rs->buf, &rs->buf_size, 0);
case PACKET_ERROR:
return -1;
case PACKET_OK:
+ bp_tgt->placed_address = addr;
+ bp_tgt->placed_size = bpsize;
return 0;
case PACKET_UNKNOWN:
break;
remote_insert_hw_breakpoint (struct bp_target_info *bp_tgt)
{
CORE_ADDR addr;
- struct remote_state *rs = get_remote_state ();
- char *p = rs->buf;
+ struct remote_state *rs;
+ char *p;
/* The length field should be set to the size of a breakpoint
instruction, even though we aren't inserting one ourselves. */
gdbarch_breakpoint_from_pc
- (current_gdbarch, &bp_tgt->placed_address, &bp_tgt->placed_size);
+ (target_gdbarch, &bp_tgt->placed_address, &bp_tgt->placed_size);
if (remote_protocol_packets[PACKET_Z1].support == PACKET_DISABLE)
return -1;
+ rs = get_remote_state ();
+ p = rs->buf;
+
*(p++) = 'Z';
*(p++) = '1';
*(p++) = ',';
return strlen ((char *) readbuf);
}
+static int
+remote_search_memory (struct target_ops* ops,
+ CORE_ADDR start_addr, ULONGEST search_space_len,
+ const gdb_byte *pattern, ULONGEST pattern_len,
+ CORE_ADDR *found_addrp)
+{
+ struct remote_state *rs = get_remote_state ();
+ int max_size = get_memory_write_packet_size ();
+ struct packet_config *packet =
+ &remote_protocol_packets[PACKET_qSearch_memory];
+ /* number of packet bytes used to encode the pattern,
+ this could be more than PATTERN_LEN due to escape characters */
+ int escaped_pattern_len;
+ /* amount of pattern that was encodable in the packet */
+ int used_pattern_len;
+ int i;
+ int found;
+ ULONGEST found_addr;
+
+ /* Don't go to the target if we don't have to.
+ This is done before checking packet->support to avoid the possibility that
+ a success for this edge case means the facility works in general. */
+ if (pattern_len > search_space_len)
+ return 0;
+ if (pattern_len == 0)
+ {
+ *found_addrp = start_addr;
+ return 1;
+ }
+
+ /* If we already know the packet isn't supported, fall back to the simple
+ way of searching memory. */
+
+ if (packet->support == PACKET_DISABLE)
+ {
+ /* Target doesn't provided special support, fall back and use the
+ standard support (copy memory and do the search here). */
+ return simple_search_memory (ops, start_addr, search_space_len,
+ pattern, pattern_len, found_addrp);
+ }
+
+ /* Insert header. */
+ i = snprintf (rs->buf, max_size,
+ "qSearch:memory:%s;%s;",
+ paddr_nz (start_addr),
+ phex_nz (search_space_len, sizeof (search_space_len)));
+ max_size -= (i + 1);
+
+ /* Escape as much data as fits into rs->buf. */
+ escaped_pattern_len =
+ remote_escape_output (pattern, pattern_len, (rs->buf + i),
+ &used_pattern_len, max_size);
+
+ /* Bail if the pattern is too large. */
+ if (used_pattern_len != pattern_len)
+ error ("Pattern is too large to transmit to remote target.");
+
+ if (putpkt_binary (rs->buf, i + escaped_pattern_len) < 0
+ || getpkt_sane (&rs->buf, &rs->buf_size, 0) < 0
+ || packet_ok (rs->buf, packet) != PACKET_OK)
+ {
+ /* The request may not have worked because the command is not
+ supported. If so, fall back to the simple way. */
+ if (packet->support == PACKET_DISABLE)
+ {
+ return simple_search_memory (ops, start_addr, search_space_len,
+ pattern, pattern_len, found_addrp);
+ }
+ return -1;
+ }
+
+ if (rs->buf[0] == '0')
+ found = 0;
+ else if (rs->buf[0] == '1')
+ {
+ found = 1;
+ if (rs->buf[1] != ',')
+ error (_("Unknown qSearch:memory reply: %s"), rs->buf);
+ unpack_varlen_hex (rs->buf + 2, &found_addr);
+ *found_addrp = found_addr;
+ }
+ else
+ error (_("Unknown qSearch:memory reply: %s"), rs->buf);
+
+ return found;
+}
+
static void
remote_rcmd (char *command,
struct ui_file *outbuf)
int sample_thread = SAMPLE_THREAD;
printf_filtered (_("Remote threadset test\n"));
- set_thread (sample_thread, 1);
+ set_general_thread (sample_thread);
}
threadalive_test (char *cmd, int tty)
{
int sample_thread = SAMPLE_THREAD;
+ int pid = ptid_get_pid (inferior_ptid);
+ ptid_t ptid = ptid_build (pid, 0, sample_thread);
- if (remote_thread_alive (pid_to_ptid (sample_thread)))
+ if (remote_thread_alive (ptid))
printf_filtered ("PASS: Thread alive test\n");
else
printf_filtered ("FAIL: Thread alive test\n");
static char *
remote_pid_to_str (ptid_t ptid)
{
- static char buf[32];
+ static char buf[64];
- xsnprintf (buf, sizeof buf, "Thread %d", ptid_get_pid (ptid));
- return buf;
+ if (ptid_equal (magic_null_ptid, ptid))
+ {
+ xsnprintf (buf, sizeof buf, "Thread <main>");
+ return buf;
+ }
+ else if (ptid_get_tid (ptid) != 0)
+ {
+ xsnprintf (buf, sizeof buf, "Thread %ld",
+ ptid_get_tid (ptid));
+ return buf;
+ }
+
+ return normal_pid_to_str (ptid);
}
/* Get the address of the thread local variable in OBJFILE which is
strcpy (p, "qGetTLSAddr:");
p += strlen (p);
- p += hexnumstr (p, PIDGET (ptid));
+ p += hexnumstr (p, ptid_get_tid (ptid));
*p++ = ',';
p += hexnumstr (p, offset);
*p++ = ',';
remote_read_description (struct target_ops *target)
{
struct remote_g_packet_data *data
- = gdbarch_data (current_gdbarch, remote_g_packet_data_handle);
+ = gdbarch_data (target_gdbarch, remote_g_packet_data_handle);
if (!VEC_empty (remote_g_packet_guess_s, data->guesses))
{
int ret, bytes_read;
char *attachment_tmp;
- if (remote_protocol_packets[which_packet].support == PACKET_DISABLE)
+ if (!remote_desc
+ || remote_protocol_packets[which_packet].support == PACKET_DISABLE)
{
*remote_errno = FILEIO_ENOSYS;
return -1;
remote_hostio_close (fd, &remote_errno);
}
+
+static void *
+remote_bfd_iovec_open (struct bfd *abfd, void *open_closure)
+{
+ const char *filename = bfd_get_filename (abfd);
+ int fd, remote_errno;
+ int *stream;
+
+ gdb_assert (remote_filename_p (filename));
+
+ fd = remote_hostio_open (filename + 7, FILEIO_O_RDONLY, 0, &remote_errno);
+ if (fd == -1)
+ {
+ errno = remote_fileio_errno_to_host (remote_errno);
+ bfd_set_error (bfd_error_system_call);
+ return NULL;
+ }
+
+ stream = xmalloc (sizeof (int));
+ *stream = fd;
+ return stream;
+}
+
+static int
+remote_bfd_iovec_close (struct bfd *abfd, void *stream)
+{
+ int fd = *(int *)stream;
+ int remote_errno;
+
+ xfree (stream);
+
+ /* Ignore errors on close; these may happen if the remote
+ connection was already torn down. */
+ remote_hostio_close (fd, &remote_errno);
+
+ return 1;
+}
+
+static file_ptr
+remote_bfd_iovec_pread (struct bfd *abfd, void *stream, void *buf,
+ file_ptr nbytes, file_ptr offset)
+{
+ int fd = *(int *)stream;
+ int remote_errno;
+ file_ptr pos, bytes;
+
+ pos = 0;
+ while (nbytes > pos)
+ {
+ bytes = remote_hostio_pread (fd, (char *)buf + pos, nbytes - pos,
+ offset + pos, &remote_errno);
+ if (bytes == 0)
+ /* Success, but no bytes, means end-of-file. */
+ break;
+ if (bytes == -1)
+ {
+ errno = remote_fileio_errno_to_host (remote_errno);
+ bfd_set_error (bfd_error_system_call);
+ return -1;
+ }
+
+ pos += bytes;
+ }
+
+ return pos;
+}
+
+static int
+remote_bfd_iovec_stat (struct bfd *abfd, void *stream, struct stat *sb)
+{
+ /* FIXME: We should probably implement remote_hostio_stat. */
+ sb->st_size = INT_MAX;
+ return 0;
+}
+
+int
+remote_filename_p (const char *filename)
+{
+ return strncmp (filename, "remote:", 7) == 0;
+}
+
+bfd *
+remote_bfd_open (const char *remote_file, const char *target)
+{
+ return bfd_openr_iovec (remote_file, target,
+ remote_bfd_iovec_open, NULL,
+ remote_bfd_iovec_pread,
+ remote_bfd_iovec_close,
+ remote_bfd_iovec_stat);
+}
+
void
remote_file_put (const char *local_file, const char *remote_file, int from_tty)
{
remote_ops.to_flash_erase = remote_flash_erase;
remote_ops.to_flash_done = remote_flash_done;
remote_ops.to_read_description = remote_read_description;
+ remote_ops.to_search_memory = remote_search_memory;
+ remote_ops.to_can_async_p = remote_can_async_p;
+ remote_ops.to_is_async_p = remote_is_async_p;
+ remote_ops.to_async = remote_async;
+ remote_ops.to_async_mask = remote_async_mask;
+ remote_ops.to_terminal_inferior = remote_terminal_inferior;
+ remote_ops.to_terminal_ours = remote_terminal_ours;
}
/* Set up the extended remote vector by making a copy of the standard
"Extended remote serial target in gdb-specific protocol";
extended_remote_ops.to_doc =
"Use a remote computer via a serial line, using a gdb-specific protocol.\n\
-Specify the serial device it is connected to (e.g. /dev/ttya).",
- extended_remote_ops.to_open = extended_remote_open;
+Specify the serial device it is connected to (e.g. /dev/ttya).";
+ extended_remote_ops.to_open = extended_remote_open;
extended_remote_ops.to_create_inferior = extended_remote_create_inferior;
extended_remote_ops.to_mourn_inferior = extended_remote_mourn;
extended_remote_ops.to_detach = extended_remote_detach;
static int
remote_can_async_p (void)
{
+ if (!target_async_permitted)
+ /* We only enable async when the user specifically asks for it. */
+ return 0;
+
/* We're async whenever the serial device is. */
- return (current_target.to_async_mask_value) && serial_can_async_p (remote_desc);
+ return remote_async_mask_value && serial_can_async_p (remote_desc);
}
static int
remote_is_async_p (void)
{
+ if (!target_async_permitted)
+ /* We only enable async when the user specifically asks for it. */
+ return 0;
+
/* We're async whenever the serial device is. */
- return (current_target.to_async_mask_value) && serial_is_async_p (remote_desc);
+ return remote_async_mask_value && serial_is_async_p (remote_desc);
}
/* Pass the SERIAL event on and up to the client. One day this code
remote_async (void (*callback) (enum inferior_event_type event_type,
void *context), void *context)
{
- if (current_target.to_async_mask_value == 0)
+ if (remote_async_mask_value == 0)
internal_error (__FILE__, __LINE__,
_("Calling remote_async when async is masked"));
serial_async (remote_desc, NULL, NULL);
}
-/* Target async and target extended-async.
-
- This are temporary targets, until it is all tested. Eventually
- async support will be incorporated int the usual 'remote'
- target. */
-
-static void
-init_remote_async_ops (void)
-{
- remote_async_ops.to_shortname = "async";
- remote_async_ops.to_longname =
- "Remote serial target in async version of the gdb-specific protocol";
- remote_async_ops.to_doc =
- "Use a remote computer via a serial line, using a gdb-specific protocol.\n\
-Specify the serial device it is connected to (e.g. /dev/ttya).";
- remote_async_ops.to_open = remote_async_open;
- remote_async_ops.to_close = remote_close;
- remote_async_ops.to_detach = remote_detach;
- remote_async_ops.to_disconnect = remote_disconnect;
- remote_async_ops.to_resume = remote_async_resume;
- remote_async_ops.to_wait = remote_async_wait;
- remote_async_ops.to_fetch_registers = remote_fetch_registers;
- remote_async_ops.to_store_registers = remote_store_registers;
- remote_async_ops.to_prepare_to_store = remote_prepare_to_store;
- remote_async_ops.deprecated_xfer_memory = remote_xfer_memory;
- remote_async_ops.to_files_info = remote_files_info;
- remote_async_ops.to_insert_breakpoint = remote_insert_breakpoint;
- remote_async_ops.to_remove_breakpoint = remote_remove_breakpoint;
- remote_async_ops.to_can_use_hw_breakpoint = remote_check_watch_resources;
- remote_async_ops.to_insert_hw_breakpoint = remote_insert_hw_breakpoint;
- remote_async_ops.to_remove_hw_breakpoint = remote_remove_hw_breakpoint;
- remote_async_ops.to_insert_watchpoint = remote_insert_watchpoint;
- remote_async_ops.to_remove_watchpoint = remote_remove_watchpoint;
- remote_async_ops.to_stopped_by_watchpoint = remote_stopped_by_watchpoint;
- remote_async_ops.to_stopped_data_address = remote_stopped_data_address;
- remote_async_ops.to_terminal_inferior = remote_async_terminal_inferior;
- remote_async_ops.to_terminal_ours = remote_async_terminal_ours;
- remote_async_ops.to_kill = remote_async_kill;
- remote_async_ops.to_load = generic_load;
- remote_async_ops.to_mourn_inferior = remote_async_mourn;
- remote_async_ops.to_thread_alive = remote_thread_alive;
- remote_async_ops.to_find_new_threads = remote_threads_info;
- remote_async_ops.to_pid_to_str = remote_pid_to_str;
- remote_async_ops.to_extra_thread_info = remote_threads_extra_info;
- remote_async_ops.to_stop = remote_stop;
- remote_async_ops.to_xfer_partial = remote_xfer_partial;
- remote_async_ops.to_rcmd = remote_rcmd;
- remote_async_ops.to_stratum = process_stratum;
- remote_async_ops.to_has_all_memory = 1;
- remote_async_ops.to_has_memory = 1;
- remote_async_ops.to_has_stack = 1;
- remote_async_ops.to_has_registers = 1;
- remote_async_ops.to_has_execution = 1;
- remote_async_ops.to_has_thread_control = tc_schedlock; /* can lock scheduler */
- remote_async_ops.to_can_async_p = remote_can_async_p;
- remote_async_ops.to_is_async_p = remote_is_async_p;
- remote_async_ops.to_async = remote_async;
- remote_async_ops.to_async_mask_value = 1;
- remote_async_ops.to_magic = OPS_MAGIC;
- remote_async_ops.to_memory_map = remote_memory_map;
- remote_async_ops.to_flash_erase = remote_flash_erase;
- remote_async_ops.to_flash_done = remote_flash_done;
- remote_async_ops.to_read_description = remote_read_description;
-}
-
-/* Set up the async extended remote vector by making a copy of the standard
- remote vector and adding to it. */
-
-static void
-init_extended_async_remote_ops (void)
+static int
+remote_async_mask (int new_mask)
{
- extended_async_remote_ops = remote_async_ops;
-
- extended_async_remote_ops.to_shortname = "extended-async";
- extended_async_remote_ops.to_longname =
- "Extended remote serial target in async gdb-specific protocol";
- extended_async_remote_ops.to_doc =
- "Use a remote computer via a serial line, using an async gdb-specific protocol.\n\
-Specify the serial device it is connected to (e.g. /dev/ttya).",
- extended_async_remote_ops.to_open = extended_remote_async_open;
- extended_async_remote_ops.to_create_inferior = extended_remote_async_create_inferior;
- extended_async_remote_ops.to_mourn_inferior = extended_async_remote_mourn;
- extended_async_remote_ops.to_detach = extended_remote_detach;
- extended_async_remote_ops.to_attach = extended_async_remote_attach;
+ int curr_mask = remote_async_mask_value;
+ remote_async_mask_value = new_mask;
+ return curr_mask;
}
static void
init_extended_remote_ops ();
add_target (&extended_remote_ops);
- init_remote_async_ops ();
- add_target (&remote_async_ops);
-
- init_extended_async_remote_ops ();
- add_target (&extended_async_remote_ops);
-
/* Hook into new objfile notification. */
observer_attach_new_objfile (remote_new_objfile);
+ /* Set up signal handlers. */
+ sigint_remote_token =
+ create_async_signal_handler (async_remote_interrupt, NULL);
+ sigint_remote_twice_token =
+ create_async_signal_handler (inferior_event_handler_wrapper, NULL);
+
#if 0
init_remote_threadtests ();
#endif
add_packet_config_cmd (&remote_protocol_packets[PACKET_qSupported],
"qSupported", "supported-packets", 0);
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_qSearch_memory],
+ "qSearch:memory", "search-memory", 0);
+
add_packet_config_cmd (&remote_protocol_packets[PACKET_vFile_open],
"vFile:open", "hostio-open", 0);
add_packet_config_cmd (&remote_protocol_packets[PACKET_vRun],
"vRun", "run", 0);
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_QStartNoAckMode],
+ "QStartNoAckMode", "noack", 0);
+
/* Keep the old ``set remote Z-packet ...'' working. Each individual
Z sub-packet has its own set and show commands, but users may
have sets to this variable in their .gdbinit files (or in their
/* Eventually initialize fileio. See fileio.c */
initialize_remote_fileio (remote_set_cmdlist, remote_show_cmdlist);
+
+ /* Take advantage of the fact that the LWP field is not used, to tag
+ special ptids with it set to != 0. */
+ magic_null_ptid = ptid_build (0, 1, -1);
+ not_sent_ptid = ptid_build (0, 1, -2);
+ any_thread_ptid = ptid_build (0, 1, 0);
}