static char *target_buf;
static long target_buf_size;
+/* Per-program-space data key. */
+static const struct program_space_data *remote_pspace_data;
+
+/* The variable registered as the control variable used by the
+ remote exec-file commands. While the remote exec-file setting is
+ per-program-space, the set/show machinery uses this as the
+ location of the remote exec-file value. */
+static char *remote_exec_file_var;
+
/* The size to align memory write packets, when practical. The protocol
does not guarantee any alignment, and gdb will generate short
writes and unaligned writes, but even as a best-effort attempt this
static void remote_async (struct target_ops *ops, int enable);
+static void remote_thread_events (struct target_ops *ops, int enable);
+
static void sync_remote_interrupt_twice (int signo);
static void interrupt_query (void);
/* vCont;r */
int r;
+
+ /* vCont;s */
+ int s;
+
+ /* vCont;S */
+ int S;
};
/* Controls whether GDB is willing to use range stepping. */
int use_threadinfo_query;
int use_threadextra_query;
- /* This is set to the data address of the access causing the target
- to stop for a watchpoint. */
- CORE_ADDR remote_watch_data_address;
-
- /* Whether the target stopped for a breakpoint/watchpoint. */
- enum target_stop_reason stop_reason;
-
threadref echo_nextthread;
threadref nextthread;
threadref resultthreadlist[MAXTHREADLISTRESULTS];
struct private_thread_info
{
char *extra;
+ char *name;
int core;
+
+ /* Whether the target stopped for a breakpoint/watchpoint. */
+ enum target_stop_reason stop_reason;
+
+ /* This is set to the data address of the access causing the target
+ to stop for a watchpoint. */
+ CORE_ADDR watch_data_address;
};
static void
free_private_thread_info (struct private_thread_info *info)
{
xfree (info->extra);
+ xfree (info->name);
xfree (info);
}
/* The default buffer size is unimportant; it will be expanded
whenever a larger buffer is needed. */
result->buf_size = 400;
- result->buf = xmalloc (result->buf_size);
+ result->buf = (char *) xmalloc (result->buf_size);
result->remote_traceframe_number = -1;
result->last_sent_signal = GDB_SIGNAL_0;
result->fs_pid = -1;
static struct remote_arch_state *
get_remote_arch_state (void)
{
- return gdbarch_data (target_gdbarch (), remote_gdbarch_data_handle);
+ gdb_assert (target_gdbarch () != NULL);
+ return ((struct remote_arch_state *)
+ gdbarch_data (target_gdbarch (), remote_gdbarch_data_handle));
}
/* Fetch the global remote target state. */
return get_remote_state_raw ();
}
+/* Cleanup routine for the remote module's pspace data. */
+
+static void
+remote_pspace_data_cleanup (struct program_space *pspace, void *arg)
+{
+ char *remote_exec_file = (char *) arg;
+
+ xfree (remote_exec_file);
+}
+
+/* Fetch the remote exec-file from the current program space. */
+
+static const char *
+get_remote_exec_file (void)
+{
+ char *remote_exec_file;
+
+ remote_exec_file
+ = (char *) program_space_data (current_program_space,
+ remote_pspace_data);
+ if (remote_exec_file == NULL)
+ return "";
+
+ return remote_exec_file;
+}
+
+/* Set the remote exec file for PSPACE. */
+
+static void
+set_pspace_remote_exec_file (struct program_space *pspace,
+ char *remote_exec_file)
+{
+ char *old_file = (char *) program_space_data (pspace, remote_pspace_data);
+
+ xfree (old_file);
+ set_program_space_data (pspace, remote_pspace_data,
+ xstrdup (remote_exec_file));
+}
+
+/* The "set/show remote exec-file" set command hook. */
+
+static void
+set_remote_exec_file (char *ignored, int from_tty,
+ struct cmd_list_element *c)
+{
+ gdb_assert (remote_exec_file_var != NULL);
+ set_pspace_remote_exec_file (current_program_space, remote_exec_file_var);
+}
+
+/* The "set/show remote exec-file" show command hook. */
+
+static void
+show_remote_exec_file (struct ui_file *file, int from_tty,
+ struct cmd_list_element *cmd, const char *value)
+{
+ fprintf_filtered (file, "%s\n", remote_exec_file_var);
+}
+
static int
compare_pnums (const void *lhs_, const void *rhs_)
{
- const struct packet_reg * const *lhs = lhs_;
- const struct packet_reg * const *rhs = rhs_;
+ const struct packet_reg * const *lhs
+ = (const struct packet_reg * const *) lhs_;
+ const struct packet_reg * const *rhs
+ = (const struct packet_reg * const *) rhs_;
if ((*lhs)->pnum < (*rhs)->pnum)
return -1;
with a remote protocol number, in order of ascending protocol
number. */
- remote_regs = alloca (gdbarch_num_regs (gdbarch)
- * sizeof (struct packet_reg *));
+ remote_regs = XALLOCAVEC (struct packet_reg *, gdbarch_num_regs (gdbarch));
for (num_remote_regs = 0, regnum = 0;
regnum < gdbarch_num_regs (gdbarch);
regnum++)
gdb_assert (regnum < gdbarch_num_regs (gdbarch));
- regs = xcalloc (gdbarch_num_regs (gdbarch), sizeof (struct packet_reg));
+ regs = XCNEWVEC (struct packet_reg, gdbarch_num_regs (gdbarch));
old_chain = make_cleanup (xfree, regs);
sizeof_g_packet = map_regcache_remote_table (gdbarch, regs);
if (rs->buf_size < rsa->remote_packet_size)
{
rs->buf_size = 2 * rsa->remote_packet_size;
- rs->buf = xrealloc (rs->buf, rs->buf_size);
+ rs->buf = (char *) xrealloc (rs->buf, rs->buf_size);
}
return rsa;
static int remote_async_terminal_ours_p;
-/* The executable file to use for "run" on the remote side. */
-
-static char *remote_exec_file = "";
-
\f
/* User configurable variables for the number of characters in a
memory read/write packet. MIN (rsa->remote_packet_size,
int fixed_p;
};
+/* The default max memory-write-packet-size. The 16k is historical.
+ (It came from older GDB's using alloca for buffers and the
+ knowledge (folklore?) that some hosts don't cope very well with
+ large alloca calls.) */
+#define DEFAULT_MAX_MEMORY_PACKET_SIZE 16384
+
+/* The minimum remote packet size for memory transfers. Ensures we
+ can write at least one byte. */
+#define MIN_MEMORY_PACKET_SIZE 20
+
/* Compute the current size of a read/write packet. Since this makes
use of ``actual_register_packet_size'' the computation is dynamic. */
struct remote_state *rs = get_remote_state ();
struct remote_arch_state *rsa = get_remote_arch_state ();
- /* NOTE: The somewhat arbitrary 16k comes from the knowledge (folk
- law?) that some hosts don't cope very well with large alloca()
- calls. Eventually the alloca() code will be replaced by calls to
- xmalloc() and make_cleanups() allowing this restriction to either
- be lifted or removed. */
-#ifndef MAX_REMOTE_PACKET_SIZE
-#define MAX_REMOTE_PACKET_SIZE 16384
-#endif
- /* NOTE: 20 ensures we can write at least one byte. */
-#ifndef MIN_REMOTE_PACKET_SIZE
-#define MIN_REMOTE_PACKET_SIZE 20
-#endif
long what_they_get;
if (config->fixed_p)
{
if (config->size <= 0)
- what_they_get = MAX_REMOTE_PACKET_SIZE;
+ what_they_get = DEFAULT_MAX_MEMORY_PACKET_SIZE;
else
what_they_get = config->size;
}
&& what_they_get > rsa->actual_register_packet_size)
what_they_get = rsa->actual_register_packet_size;
}
- if (what_they_get > MAX_REMOTE_PACKET_SIZE)
- what_they_get = MAX_REMOTE_PACKET_SIZE;
- if (what_they_get < MIN_REMOTE_PACKET_SIZE)
- what_they_get = MIN_REMOTE_PACKET_SIZE;
+ if (what_they_get < MIN_MEMORY_PACKET_SIZE)
+ what_they_get = MIN_MEMORY_PACKET_SIZE;
/* Make sure there is room in the global buffer for this packet
(including its trailing NUL byte). */
if (rs->buf_size < what_they_get + 1)
{
rs->buf_size = 2 * what_they_get;
- rs->buf = xrealloc (rs->buf, 2 * what_they_get);
+ rs->buf = (char *) xrealloc (rs->buf, 2 * what_they_get);
}
return what_they_get;
size = strtoul (args, &end, 0);
if (args == end)
error (_("Invalid %s (bad syntax)."), config->name);
-#if 0
- /* Instead of explicitly capping the size of a packet to
- MAX_REMOTE_PACKET_SIZE or dissallowing it, the user is
- instead allowed to set the size to something arbitrarily
- large. */
- if (size > MAX_REMOTE_PACKET_SIZE)
- error (_("Invalid %s (too large)."), config->name);
-#endif
+
+ /* Instead of explicitly capping the size of a packet to or
+ disallowing it, the user is allowed to set the size to
+ something arbitrarily large. */
}
+
+ /* So that the query shows the correct value. */
+ if (size <= 0)
+ size = DEFAULT_MAX_MEMORY_PACKET_SIZE;
+
/* Extra checks? */
if (fixed_p && !config->fixed_p)
{
/* Support for the QNonStop packet. */
PACKET_QNonStop,
+ /* Support for the QThreadEvents packet. */
+ PACKET_QThreadEvents,
+
/* Support for multi-process extensions. */
PACKET_multiprocess_feature,
/* Support for the Qbtrace-conf:pt:size packet. */
PACKET_Qbtrace_conf_pt_size,
+ /* Support for exec events. */
+ PACKET_exec_event_feature,
+
+ /* Support for query supported vCont actions. */
+ PACKET_vContSupported,
+
+ /* Support remote CTRL-C. */
+ PACKET_vCtrlC,
+
PACKET_MAX
};
return packet_support (PACKET_vfork_event_feature) == PACKET_ENABLE;
}
+/* Returns true if exec events are supported. */
+
+static int
+remote_exec_event_p (struct remote_state *rs)
+{
+ return packet_support (PACKET_exec_event_feature) == PACKET_ENABLE;
+}
+
/* Insert fork catchpoint target routine. If fork events are enabled
then return success, nothing more to do. */
return 0;
}
+/* Insert exec catchpoint target routine. If exec events are
+ enabled, just return success. */
+
+static int
+remote_insert_exec_catchpoint (struct target_ops *ops, int pid)
+{
+ struct remote_state *rs = get_remote_state ();
+
+ return !remote_exec_event_p (rs);
+}
+
+/* Remove exec catchpoint target routine. Nothing to do, just
+ return success. */
+
+static int
+remote_remove_exec_catchpoint (struct target_ops *ops, int pid)
+{
+ return 0;
+}
+
/* Tokens for use by the asynchronous signal handlers for SIGINT. */
static struct async_signal_handler *async_sigint_remote_twice_token;
static struct async_signal_handler *async_sigint_remote_token;
{
struct remote_state *rs = get_remote_state ();
- if (non_stop || !rs->starting_up)
+ if (!rs->starting_up)
notice_new_inferior (currthread, running, 0);
}
}
if (!info->priv)
{
- info->priv = xmalloc (sizeof (*(info->priv)));
+ info->priv = XNEW (struct private_thread_info);
info->private_dtor = free_private_thread_info;
info->priv->core = -1;
info->priv->extra = 0;
if (pass_signals[i])
count++;
}
- pass_packet = xmalloc (count * 3 + strlen ("QPassSignals:") + 1);
+ pass_packet = (char *) xmalloc (count * 3 + strlen ("QPassSignals:") + 1);
strcpy (pass_packet, "QPassSignals:");
p = pass_packet + strlen (pass_packet);
for (i = 0; i < numsigs; i++)
if (signals[i])
count++;
}
- packet = xmalloc (count * 3 + strlen ("QProgramSignals:") + 1);
+ packet = (char *) xmalloc (count * 3 + strlen ("QProgramSignals:") + 1);
strcpy (packet, "QProgramSignals:");
p = packet + strlen (packet);
for (i = 0; i < numsigs; i++)
return (rs->buf[0] == 'O' && rs->buf[1] == 'K');
}
+/* Return a pointer to a thread name if we know it and NULL otherwise.
+ The thread_info object owns the memory for the name. */
+
+static const char *
+remote_thread_name (struct target_ops *ops, struct thread_info *info)
+{
+ if (info->priv != NULL)
+ return info->priv->name;
+
+ return NULL;
+}
+
/* About these extended threadlist and threadinfo packets. They are
variable length packets but, the fields within them are often fixed
length. They are redundent enough to send over UDP as is the
/* The thread's extra info. May be NULL. */
char *extra;
+ /* The thread's name. May be NULL. */
+ char *name;
+
/* The core the thread was running on. -1 if not known. */
int core;
} thread_item_t;
static void
clear_threads_listing_context (void *p)
{
- struct threads_listing_context *context = p;
+ struct threads_listing_context *context
+ = (struct threads_listing_context *) p;
int i;
struct thread_item *item;
for (i = 0; VEC_iterate (thread_item_t, context->items, i, item); ++i)
- xfree (item->extra);
+ {
+ xfree (item->extra);
+ xfree (item->name);
+ }
VEC_free (thread_item_t, context->items);
}
static int
remote_newthread_step (threadref *ref, void *data)
{
- struct threads_listing_context *context = data;
+ struct threads_listing_context *context
+ = (struct threads_listing_context *) data;
struct thread_item item;
int pid = ptid_get_pid (inferior_ptid);
const struct gdb_xml_element *element,
void *user_data, VEC(gdb_xml_value_s) *attributes)
{
- struct threads_listing_context *data = user_data;
+ struct threads_listing_context *data
+ = (struct threads_listing_context *) user_data;
struct thread_item item;
char *id;
struct gdb_xml_value *attr;
- id = xml_find_attribute (attributes, "id")->value;
+ id = (char *) xml_find_attribute (attributes, "id")->value;
item.ptid = read_ptid (id, NULL);
attr = xml_find_attribute (attributes, "core");
else
item.core = -1;
+ attr = xml_find_attribute (attributes, "name");
+ item.name = attr != NULL ? xstrdup ((const char *) attr->value) : NULL;
+
item.extra = 0;
VEC_safe_push (thread_item_t, data->items, &item);
const struct gdb_xml_element *element,
void *user_data, const char *body_text)
{
- struct threads_listing_context *data = user_data;
+ struct threads_listing_context *data
+ = (struct threads_listing_context *) user_data;
if (body_text && *body_text)
VEC_last (thread_item_t, data->items)->extra = xstrdup (body_text);
const struct gdb_xml_attribute thread_attributes[] = {
{ "id", GDB_XML_AF_NONE, NULL, NULL },
{ "core", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL },
+ { "name", GDB_XML_AF_OPTIONAL, NULL, NULL },
{ NULL, GDB_XML_AF_NONE, NULL, NULL }
};
running until proven otherwise with a stop reply. In
all-stop, we can only get here if all threads are
stopped. */
- int running = non_stop ? 1 : 0;
+ int running = target_is_non_stop_p () ? 1 : 0;
remote_notice_new_inferior (item->ptid, running);
info->core = item->core;
info->extra = item->extra;
item->extra = NULL;
+ info->name = item->name;
+ item->name = NULL;
}
}
}
add_thread_silent (inferior_ptid);
}
+/* Print info about a thread that was found already stopped on
+ connection. */
+
+static void
+print_one_stopped_thread (struct thread_info *thread)
+{
+ struct target_waitstatus *ws = &thread->suspend.waitstatus;
+
+ switch_to_thread (thread->ptid);
+ stop_pc = get_frame_pc (get_current_frame ());
+ set_current_sal_from_frame (get_current_frame ());
+
+ thread->suspend.waitstatus_pending_p = 0;
+
+ if (ws->kind == TARGET_WAITKIND_STOPPED)
+ {
+ enum gdb_signal sig = ws->value.sig;
+
+ if (signal_print_state (sig))
+ observer_notify_signal_received (sig);
+ }
+ observer_notify_normal_stop (NULL, 1);
+}
+
/* Process all initial stop replies the remote side sent in response
to the ? packet. These indicate threads that were already stopped
on initial connection. We mark these threads as stopped and print
their current frame before giving the user the prompt. */
static void
-process_initial_stop_replies (void)
+process_initial_stop_replies (int from_tty)
{
int pending_stop_replies = stop_reply_queue_length ();
+ struct inferior *inf;
+ struct thread_info *thread;
+ struct thread_info *selected = NULL;
+ struct thread_info *lowest_stopped = NULL;
+ struct thread_info *first = NULL;
/* Consume the initial pending events. */
while (pending_stop_replies-- > 0)
ptid_t event_ptid;
struct target_waitstatus ws;
int ignore_event = 0;
+ struct thread_info *thread;
memset (&ws, 0, sizeof (ws));
event_ptid = target_wait (waiton_ptid, &ws, TARGET_WNOHANG);
if (ignore_event)
continue;
- switch_to_thread (event_ptid);
- set_executing (event_ptid, 0);
- set_running (event_ptid, 0);
-
- stop_pc = get_frame_pc (get_current_frame ());
- set_current_sal_from_frame (get_current_frame ());
+ thread = find_thread_ptid (event_ptid);
if (ws.kind == TARGET_WAITKIND_STOPPED)
{
instead of signal 0. Suppress it. */
if (sig == GDB_SIGNAL_TRAP)
sig = GDB_SIGNAL_0;
- inferior_thread ()->suspend.stop_signal = sig;
+ thread->suspend.stop_signal = sig;
+ ws.value.sig = sig;
+ }
- if (signal_print_state (sig))
- observer_notify_signal_received (sig);
- }
+ thread->suspend.waitstatus = ws;
- print_stop_event (&ws);
- observer_notify_normal_stop (NULL, 1);
+ if (ws.kind != TARGET_WAITKIND_STOPPED
+ || ws.value.sig != GDB_SIGNAL_0)
+ thread->suspend.waitstatus_pending_p = 1;
+
+ set_executing (event_ptid, 0);
+ set_running (event_ptid, 0);
}
+
+ /* "Notice" the new inferiors before anything related to
+ registers/memory. */
+ ALL_INFERIORS (inf)
+ {
+ if (inf->pid == 0)
+ continue;
+
+ inf->needs_setup = 1;
+
+ if (non_stop)
+ {
+ thread = any_live_thread_of_process (inf->pid);
+ notice_new_inferior (thread->ptid,
+ thread->state == THREAD_RUNNING,
+ from_tty);
+ }
+ }
+
+ /* If all-stop on top of non-stop, pause all threads. Note this
+ records the threads' stop pc, so must be done after "noticing"
+ the inferiors. */
+ if (!non_stop)
+ {
+ stop_all_threads ();
+
+ /* If all threads of an inferior were already stopped, we
+ haven't setup the inferior yet. */
+ ALL_INFERIORS (inf)
+ {
+ if (inf->pid == 0)
+ continue;
+
+ if (inf->needs_setup)
+ {
+ thread = any_live_thread_of_process (inf->pid);
+ switch_to_thread_no_regs (thread);
+ setup_inferior (0);
+ }
+ }
+ }
+
+ /* Now go over all threads that are stopped, and print their current
+ frame. If all-stop, then if there's a signalled thread, pick
+ that as current. */
+ ALL_NON_EXITED_THREADS (thread)
+ {
+ struct target_waitstatus *ws;
+
+ if (first == NULL)
+ first = thread;
+
+ if (!non_stop)
+ set_running (thread->ptid, 0);
+ else if (thread->state != THREAD_STOPPED)
+ continue;
+
+ ws = &thread->suspend.waitstatus;
+
+ if (selected == NULL
+ && thread->suspend.waitstatus_pending_p)
+ selected = thread;
+
+ if (lowest_stopped == NULL || thread->num < lowest_stopped->num)
+ lowest_stopped = thread;
+
+ if (non_stop)
+ print_one_stopped_thread (thread);
+ }
+
+ /* In all-stop, we only print the status of one thread, and leave
+ others with their status pending. */
+ if (!non_stop)
+ {
+ thread = selected;
+ if (thread == NULL)
+ thread = lowest_stopped;
+ if (thread == NULL)
+ thread = first;
+
+ print_one_stopped_thread (thread);
+ }
+
+ /* For "info program". */
+ thread = inferior_thread ();
+ if (thread->state == THREAD_STOPPED)
+ set_last_target_status (inferior_ptid, thread->suspend.waitstatus);
}
static void
if (gdbarch_has_global_solist (target_gdbarch ()))
solib_add (NULL, from_tty, target, auto_solib_add);
- if (non_stop)
+ if (target_is_non_stop_p ())
{
if (packet_support (PACKET_QNonStop) != PACKET_ENABLE)
error (_("Non-stop mode requested, but remote "
putpkt ("?");
getpkt (&rs->buf, &rs->buf_size, 0);
- if (!non_stop)
+ if (!target_is_non_stop_p ())
{
ptid_t ptid;
int fake_pid_p = 0;
else
{
/* Save the reply for later. */
- wait_status = alloca (strlen (rs->buf) + 1);
+ wait_status = (char *) alloca (strlen (rs->buf) + 1);
strcpy (wait_status, rs->buf);
}
}
else
{
- ptid_t current_ptid;
-
/* Clear WFI global state. Do this before finding about new
threads and inferiors, and setting the current inferior.
Otherwise we would clear the proceed status of the current
return;
}
- /* Let the stub know that we want it to return the thread. */
-
- /* Force the stub to choose a thread. */
- set_general_thread (null_ptid);
-
- /* Query it. */
- current_ptid = remote_current_thread (minus_one_ptid);
- if (ptid_equal (inferior_ptid, minus_one_ptid))
- error (_("remote didn't report the current thread in non-stop mode"));
-
- inferior_ptid = current_ptid;
- get_offsets (); /* Get text, data & bss offsets. */
-
/* In non-stop mode, any cached wait status will be stored in
the stop reply queue. */
gdb_assert (wait_status == NULL);
/* If there are already stopped threads, mark them stopped and
report their stops before giving the prompt to the user. */
- process_initial_stop_replies ();
-
- switch_to_thread (current_ptid);
+ process_initial_stop_replies (from_tty);
if (target_can_async_p ())
target_async (1);
char *msg, *reply, *tmp;
struct bound_minimal_symbol sym;
int end;
+ struct cleanup *old_chain;
/* The remote side has no concept of inferiors that aren't running
yet, it only knows about running processes. If we're connected
/* Allocate a message buffer. We can't reuse the input buffer in RS,
because we need both at the same time. */
- msg = alloca (get_remote_packet_size ());
+ msg = (char *) xmalloc (get_remote_packet_size ());
+ old_chain = make_cleanup (xfree, msg);
/* Invite target to request symbol lookups. */
getpkt (&rs->buf, &rs->buf_size, 0);
reply = rs->buf;
}
+
+ do_cleanups (old_chain);
}
static struct serial *
return;
}
- if (packet_size > MAX_REMOTE_PACKET_SIZE)
- {
- warning (_("limiting remote suggested packet size (%d bytes) to %d"),
- packet_size, MAX_REMOTE_PACKET_SIZE);
- packet_size = MAX_REMOTE_PACKET_SIZE;
- }
-
/* Record the new maximum packet size. */
rs->explicit_packet_size = packet_size;
}
PACKET_fork_event_feature },
{ "vfork-events", PACKET_DISABLE, remote_supported_packet,
PACKET_vfork_event_feature },
+ { "exec-events", PACKET_DISABLE, remote_supported_packet,
+ PACKET_exec_event_feature },
{ "Qbtrace-conf:pt:size", PACKET_DISABLE, remote_supported_packet,
- PACKET_Qbtrace_conf_pt_size }
+ PACKET_Qbtrace_conf_pt_size },
+ { "vContSupported", PACKET_DISABLE, remote_supported_packet, PACKET_vContSupported },
+ { "QThreadEvents", PACKET_DISABLE, remote_supported_packet, PACKET_QThreadEvents },
};
static char *remote_support_xml;
char *q = NULL;
struct cleanup *old_chain = make_cleanup (free_current_contents, &q);
- q = remote_query_supported_append (q, "multiprocess+");
+ if (packet_set_cmd_state (PACKET_multiprocess_feature) != AUTO_BOOLEAN_FALSE)
+ q = remote_query_supported_append (q, "multiprocess+");
if (packet_set_cmd_state (PACKET_swbreak_feature) != AUTO_BOOLEAN_FALSE)
q = remote_query_supported_append (q, "swbreak+");
if (packet_set_cmd_state (PACKET_hwbreak_feature) != AUTO_BOOLEAN_FALSE)
q = remote_query_supported_append (q, "hwbreak+");
- if (remote_support_xml)
- q = remote_query_supported_append (q, remote_support_xml);
-
q = remote_query_supported_append (q, "qRelocInsn+");
if (rs->extended)
if (packet_set_cmd_state (PACKET_vfork_event_feature)
!= AUTO_BOOLEAN_FALSE)
q = remote_query_supported_append (q, "vfork-events+");
+ if (packet_set_cmd_state (PACKET_exec_event_feature)
+ != AUTO_BOOLEAN_FALSE)
+ q = remote_query_supported_append (q, "exec-events+");
}
+ if (packet_set_cmd_state (PACKET_vContSupported) != AUTO_BOOLEAN_FALSE)
+ q = remote_query_supported_append (q, "vContSupported+");
+
+ if (packet_set_cmd_state (PACKET_QThreadEvents) != AUTO_BOOLEAN_FALSE)
+ q = remote_query_supported_append (q, "QThreadEvents+");
+
+ /* Keep this one last to work around a gdbserver <= 7.10 bug in
+ the qSupported:xmlRegisters=i386 handling. */
+ if (remote_support_xml != NULL)
+ q = remote_query_supported_append (q, remote_support_xml);
+
q = reconcat (q, "qSupported:", q, (char *) NULL);
putpkt (q);
if (rs->buf_size < rs->explicit_packet_size)
{
rs->buf_size = rs->explicit_packet_size;
- rs->buf = xrealloc (rs->buf, rs->buf_size);
+ rs->buf = (char *) xrealloc (rs->buf, rs->buf_size);
}
/* Handle the defaults for unmentioned features. */
static void
remote_unpush_target (void)
{
- pop_all_targets_above (process_stratum - 1);
+ pop_all_targets_at_and_above (process_stratum);
}
static void
return 0;
}
+/* Target follow-exec function for remote targets. Save EXECD_PATHNAME
+ in the program space of the new inferior. On entry and at return the
+ current inferior is the exec'ing inferior. INF is the new exec'd
+ inferior, which may be the same as the exec'ing inferior unless
+ follow-exec-mode is "new". */
+
+static void
+remote_follow_exec (struct target_ops *ops,
+ struct inferior *inf, char *execd_pathname)
+{
+ /* We know that this is a target file name, so if it has the "target:"
+ prefix we strip it off before saving it in the program space. */
+ if (is_target_filename (execd_pathname))
+ execd_pathname += strlen (TARGET_SYSROOT_PREFIX);
+
+ set_pspace_remote_exec_file (inf->pspace, execd_pathname);
+}
+
/* Same as remote_detach, but don't send the "D" packet; just disconnect. */
static void
&remote_protocol_packets[PACKET_vAttach]))
{
case PACKET_OK:
- if (!non_stop)
+ if (!target_is_non_stop_p ())
{
/* Save the reply for later. */
- wait_status = alloca (strlen (rs->buf) + 1);
+ wait_status = (char *) alloca (strlen (rs->buf) + 1);
strcpy (wait_status, rs->buf);
}
else if (strcmp (rs->buf, "OK") != 0)
inferior_ptid = pid_to_ptid (pid);
- if (non_stop)
+ if (target_is_non_stop_p ())
{
struct thread_info *thread;
this before anything involving memory or registers. */
target_find_description ();
- if (!non_stop)
+ if (!target_is_non_stop_p ())
{
/* Use the previously fetched status. */
gdb_assert (wait_status != NULL);
static void
extended_remote_post_attach (struct target_ops *ops, int pid)
{
+ /* Get text, data & bss offsets. */
+ get_offsets ();
+
/* In certain cases GDB might not have had the chance to start
symbol lookup up until now. This could happen if the debugged
binary is not using shared libraries, the vsyscall page is not
if (startswith (buf, "vCont"))
{
char *p = &buf[5];
- int support_s, support_S, support_c, support_C;
+ int support_c, support_C;
- support_s = 0;
- support_S = 0;
+ rs->supports_vCont.s = 0;
+ rs->supports_vCont.S = 0;
support_c = 0;
support_C = 0;
rs->supports_vCont.t = 0;
{
p++;
if (*p == 's' && (*(p + 1) == ';' || *(p + 1) == 0))
- support_s = 1;
+ rs->supports_vCont.s = 1;
else if (*p == 'S' && (*(p + 1) == ';' || *(p + 1) == 0))
- support_S = 1;
+ rs->supports_vCont.S = 1;
else if (*p == 'c' && (*(p + 1) == ';' || *(p + 1) == 0))
support_c = 1;
else if (*p == 'C' && (*(p + 1) == ';' || *(p + 1) == 0))
p = strchr (p, ';');
}
- /* If s, S, c, and C are not all supported, we can't use vCont. Clearing
- BUF will make packet_ok disable the packet. */
- if (!support_s || !support_S || !support_c || !support_C)
+ /* If c, and C are not all supported, we can't use vCont. Clearing
+ BUF will make packet_ok disable the packet. */
+ if (!support_c || !support_C)
buf[0] = 0;
}
return p;
}
+/* Clear the thread's private info on resume. */
+
+static void
+resume_clear_thread_private_info (struct thread_info *thread)
+{
+ if (thread->priv != NULL)
+ {
+ thread->priv->stop_reason = TARGET_STOPPED_BY_NO_REASON;
+ thread->priv->watch_data_address = 0;
+ }
+}
+
/* Append a vCont continue-with-signal action for threads that have a
non-zero stop signal. */
p = append_resumption (p, endp, thread->ptid,
0, thread->suspend.stop_signal);
thread->suspend.stop_signal = GDB_SIGNAL_0;
+ resume_clear_thread_private_info (thread);
}
return p;
gdb_assert (strlen (rs->buf) < get_remote_packet_size ());
putpkt (rs->buf);
- if (non_stop)
+ if (target_is_non_stop_p ())
{
/* In non-stop, the stub replies to vCont with "OK". The stop
reply will be reported asynchronously by means of a `%Stop'
{
struct remote_state *rs = get_remote_state ();
char *buf;
+ struct thread_info *thread;
/* In all-stop, we can't mark REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN
(explained in remote-notif.c:handle_notification) so
it is safe to start a 'vNotif' sequence. It is good to do it
before resuming inferior, because inferior was stopped and no RSP
traffic at that moment. */
- if (!non_stop)
+ if (!target_is_non_stop_p ())
remote_notif_process (rs->notif_state, ¬if_client_stop);
rs->last_sent_signal = siggnal;
else
set_continue_thread (ptid);
+ ALL_NON_EXITED_THREADS (thread)
+ resume_clear_thread_private_info (thread);
+
buf = rs->buf;
if (execution_direction == EXEC_REVERSE)
{
only to the base all-stop protocol, however. In non-stop (which
only supports vCont), the stub replies with an "OK", and is
immediate able to process further serial input. */
- if (!non_stop)
+ if (!target_is_non_stop_p ())
rs->waiting_for_stop_reply = 1;
}
\f
gdb_call_async_signal_handler (async_sigint_remote_twice_token, 0);
}
+/* Implementation of to_check_pending_interrupt. */
+
+static void
+remote_check_pending_interrupt (struct target_ops *self)
+{
+ struct async_signal_handler *token = async_sigint_remote_twice_token;
+
+ if (async_signal_handler_is_marked (token))
+ {
+ clear_async_signal_handler (token);
+ call_async_signal_handler (token);
+ }
+}
+
/* Perform the real interruption of the target execution, in response
to a ^C. */
static void
if (remote_debug)
fprintf_unfiltered (gdb_stdlog, "async_remote_interrupt called\n");
- target_stop (inferior_ptid);
+ target_interrupt (inferior_ptid);
}
/* Perform interrupt, if the first attempt did not succeed. Just give
process reports the interrupt. */
static void
-remote_interrupt_as (ptid_t ptid)
+remote_interrupt_as (void)
{
struct remote_state *rs = get_remote_state ();
send_interrupt_sequence ();
}
+/* Non-stop version of target_interrupt. Uses `vCtrlC' to interrupt
+ the remote target. It is undefined which thread of which process
+ reports the interrupt. Returns true if the packet is supported by
+ the server, false otherwise. */
+
+static int
+remote_interrupt_ns (void)
+{
+ struct remote_state *rs = get_remote_state ();
+ char *p = rs->buf;
+ char *endp = rs->buf + get_remote_packet_size ();
+
+ xsnprintf (p, endp - p, "vCtrlC");
+
+ /* In non-stop, we get an immediate OK reply. The stop reply will
+ come in asynchronously by notification. */
+ putpkt (rs->buf);
+ getpkt (&rs->buf, &rs->buf_size, 0);
+
+ switch (packet_ok (rs->buf, &remote_protocol_packets[PACKET_vCtrlC]))
+ {
+ case PACKET_OK:
+ break;
+ case PACKET_UNKNOWN:
+ return 0;
+ case PACKET_ERROR:
+ error (_("Interrupting target failed: %s"), rs->buf);
+ }
+
+ return 1;
+}
+
/* Implement the to_stop function for the remote targets. */
static void
if (remote_debug)
fprintf_unfiltered (gdb_stdlog, "remote_stop called\n");
- if (non_stop)
+ if (target_is_non_stop_p ())
remote_stop_ns (ptid);
else
{
/* We don't currently have a way to transparently pause the
remote target in all-stop mode. Interrupt it instead. */
- remote_interrupt_as (ptid);
+ remote_interrupt_as ();
}
}
if (non_stop)
{
- /* We don't currently have a way to ^C the remote target in
- non-stop mode. Stop it (with no signal) instead. */
+ /* In non-stop mode, we always stop with no signal instead. */
remote_stop_ns (ptid);
}
else
- remote_interrupt_as (ptid);
+ {
+ /* In all-stop, we emulate ^C-ing the remote target's
+ terminal. */
+ if (target_is_non_stop_p ())
+ {
+ if (!remote_interrupt_ns ())
+ {
+ /* No support for ^C-ing the remote target. Stop it
+ (with no signal) instead. */
+ remote_stop_ns (ptid);
+ }
+ }
+ else
+ remote_interrupt_as ();
+ }
}
/* Ask the user what to do when an interrupt is received. */
static void
interrupt_query (void)
{
+ struct remote_state *rs = get_remote_state ();
+ struct cleanup *old_chain;
+
+ old_chain = make_cleanup_restore_target_terminal ();
target_terminal_ours ();
- if (target_is_async_p ())
- {
- signal (SIGINT, handle_sigint);
- quit ();
- }
- else
+ if (rs->waiting_for_stop_reply && rs->ctrlc_pending_p)
{
- if (query (_("Interrupted while waiting for the program.\n\
-Give up (and stop debugging it)? ")))
+ if (query (_("The target is not responding to interrupt requests.\n"
+ "Stop debugging it? ")))
{
remote_unpush_target ();
- quit ();
+ throw_error (TARGET_CLOSE_ERROR, _("Disconnected from target."));
}
}
+ else
+ {
+ if (query (_("Interrupted while waiting for the program.\n"
+ "Give up waiting? ")))
+ quit ();
+ }
- target_terminal_inferior ();
+ do_cleanups (old_chain);
}
/* Enable/disable target terminal ownership. Most targets can use
static struct notif_event *
remote_notif_stop_alloc_reply (void)
{
- struct notif_event *r
- = (struct notif_event *) XNEW (struct stop_reply);
+ /* We cast to a pointer to the "base class". */
+ struct notif_event *r = (struct notif_event *) XNEW (struct stop_reply);
r->dtr = stop_reply_dtr;
stop_reply_p event,
void *data)
{
- struct queue_iter_param *param = data;
- struct threads_listing_context *context = param->input;
+ struct queue_iter_param *param = (struct queue_iter_param *) data;
+ struct threads_listing_context *context
+ = (struct threads_listing_context *) param->input;
if (event->ws.kind == TARGET_WAITKIND_FORKED
- || event->ws.kind == TARGET_WAITKIND_VFORKED)
- {
- threads_listing_context_remove (&event->ws, context);
- }
+ || event->ws.kind == TARGET_WAITKIND_VFORKED
+ || event->ws.kind == TARGET_WAITKIND_THREAD_EXITED)
+ threads_listing_context_remove (&event->ws, context);
return 1;
}
stop_reply_p event,
void *data)
{
- struct queue_iter_param *param = data;
- struct inferior *inf = param->input;
+ struct queue_iter_param *param = (struct queue_iter_param *) data;
+ struct inferior *inf = (struct inferior *) param->input;
if (ptid_get_pid (event->ptid) == inf->pid)
{
stop_reply_p event,
void *data)
{
- struct queue_iter_param *param = data;
- struct remote_state *rs = param->input;
+ struct queue_iter_param *param = (struct queue_iter_param *) data;
+ struct remote_state *rs = (struct remote_state *) param->input;
if (event->rs == rs)
{
stop_reply_p event,
void *data)
{
- struct queue_iter_param *param = data;
- ptid_t *ptid = param->input;
+ struct queue_iter_param *param = (struct queue_iter_param *) data;
+ ptid_t *ptid = (ptid_t *) param->input;
if (ptid_match (event->ptid, *ptid))
{
struct stop_reply *event,
void *data)
{
- ptid_t *ptid = data;
+ ptid_t *ptid = (ptid_t *) data;
return !(ptid_equal (*ptid, event->ptid)
&& event->ws.kind == TARGET_WAITKIND_STOPPED);
struct remote_arch_state *rsa = get_remote_arch_state ();
ULONGEST addr;
char *p;
+ int skipregs = 0;
event->ptid = null_ptid;
event->rs = get_remote_state ();
event->ws.kind = TARGET_WAITKIND_VFORK_DONE;
p = skip_to_semicolon (p1 + 1);
}
+ else if (strprefix (p, p1, "exec"))
+ {
+ ULONGEST ignored;
+ char pathname[PATH_MAX];
+ int pathlen;
+
+ /* Determine the length of the execd pathname. */
+ p = unpack_varlen_hex (++p1, &ignored);
+ pathlen = (p - p1) / 2;
+
+ /* Save the pathname for event reporting and for
+ the next run command. */
+ hex2bin (p1, (gdb_byte *) pathname, pathlen);
+ pathname[pathlen] = '\0';
+
+ /* This is freed during event handling. */
+ event->ws.value.execd_pathname = xstrdup (pathname);
+ event->ws.kind = TARGET_WAITKIND_EXECD;
+
+ /* Skip the registers included in this packet, since
+ they may be for an architecture different from the
+ one used by the original program. */
+ skipregs = 1;
+ }
+ else if (strprefix (p, p1, "create"))
+ {
+ event->ws.kind = TARGET_WAITKIND_THREAD_CREATED;
+ p = skip_to_semicolon (p1 + 1);
+ }
else
{
ULONGEST pnum;
char *p_temp;
+ if (skipregs)
+ {
+ p = skip_to_semicolon (p1 + 1);
+ p++;
+ continue;
+ }
+
/* Maybe a real ``P'' register number. */
p_temp = unpack_varlen_hex (p, &pnum);
/* If the first invalid character is the colon, we got a
event->ws.value.sig = GDB_SIGNAL_UNKNOWN;
}
break;
+ case 'w': /* Thread exited. */
+ {
+ char *p;
+ ULONGEST value;
+
+ event->ws.kind = TARGET_WAITKIND_THREAD_EXITED;
+ p = unpack_varlen_hex (&buf[1], &value);
+ event->ws.value.integer = value;
+ if (*p != ';')
+ error (_("stop reply packet badly formatted: %s"), buf);
+ event->ptid = read_ptid (++p, &p);
+ break;
+ }
case 'W': /* Target exited. */
case 'X':
{
break;
}
- if (non_stop && ptid_equal (event->ptid, null_ptid))
+ if (target_is_non_stop_p () && ptid_equal (event->ptid, null_ptid))
error (_("No process or thread specified in stop reply: %s"), buf);
}
&& status->kind != TARGET_WAITKIND_SIGNALLED)
{
struct remote_state *rs = get_remote_state ();
+ struct private_thread_info *remote_thr;
/* Expedited registers. */
if (stop_reply->regcache)
VEC_free (cached_reg_t, stop_reply->regcache);
}
- rs->stop_reason = stop_reply->stop_reason;
- rs->remote_watch_data_address = stop_reply->watch_data_address;
-
remote_notice_new_inferior (ptid, 0);
- demand_private_info (ptid)->core = stop_reply->core;
+ remote_thr = demand_private_info (ptid);
+ remote_thr->core = stop_reply->core;
+ remote_thr->stop_reason = stop_reply->stop_reason;
+ remote_thr->watch_data_address = stop_reply->watch_data_address;
}
stop_reply_xfree (stop_reply);
buf = rs->buf;
- rs->stop_reason = TARGET_STOPPED_BY_NO_REASON;
-
- /* We got something. */
- rs->waiting_for_stop_reply = 0;
-
/* Assume that the target has acknowledged Ctrl-C unless we receive
an 'F' or 'O' packet. */
if (buf[0] != 'F' && buf[0] != 'O')
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. */
+ rs->waiting_for_stop_reply = 0;
+
warning (_("Remote failure reply: %s"), buf);
status->kind = TARGET_WAITKIND_STOPPED;
status->value.sig = GDB_SIGNAL_0;
break;
case 'T': case 'S': case 'X': case 'W':
{
- struct stop_reply *stop_reply
+ struct stop_reply *stop_reply;
+
+ /* There is a stop reply to handle. */
+ rs->waiting_for_stop_reply = 0;
+
+ stop_reply
= (struct stop_reply *) remote_notif_parse (¬if_client_stop,
rs->buf);
}
case 'O': /* Console output. */
remote_console_output (buf + 1);
-
- /* The target didn't really stop; keep waiting. */
- rs->waiting_for_stop_reply = 1;
-
break;
case '\0':
if (rs->last_sent_signal != GDB_SIGNAL_0)
strcpy ((char *) buf, rs->last_sent_step ? "s" : "c");
putpkt ((char *) buf);
-
- /* We just told the target to resume, so a stop reply is in
- order. */
- rs->waiting_for_stop_reply = 1;
break;
}
/* else fallthrough */
default:
warning (_("Invalid remote reply: %s"), buf);
- /* Keep waiting. */
- rs->waiting_for_stop_reply = 1;
break;
}
{
ptid_t event_ptid;
- if (non_stop)
+ if (target_is_non_stop_p ())
event_ptid = remote_wait_ns (ptid, status, options);
else
event_ptid = remote_wait_as (ptid, status, options);
}
}
- regs = alloca (rsa->sizeof_g_packet);
+ regs = (char *) alloca (rsa->sizeof_g_packet);
/* Unimplemented registers read as all bits zero. */
memset (regs, 0, rsa->sizeof_g_packet);
{
int i;
- regs = alloca (rsa->sizeof_g_packet);
+ regs = (gdb_byte *) alloca (rsa->sizeof_g_packet);
memset (regs, 0, rsa->sizeof_g_packet);
for (i = 0; i < gdbarch_num_regs (get_regcache_arch (regcache)); i++)
{
struct remote_state *rs = get_remote_state ();
int i;
unsigned char csum = 0;
- char *buf2 = alloca (cnt + 6);
+ char *buf2 = (char *) xmalloc (cnt + 6);
+ struct cleanup *old_chain = make_cleanup (xfree, buf2);
int ch;
int tcount = 0;
case it's not possible to issue a command while the target is
running. This is not a problem in non-stop mode, because in that
case, the stub is always ready to process serial input. */
- if (!non_stop && target_is_async_p () && rs->waiting_for_stop_reply)
+ if (!target_is_non_stop_p ()
+ && target_is_async_p ()
+ && rs->waiting_for_stop_reply)
{
error (_("Cannot execute this command while the target is running.\n"
"Use the \"interrupt\" command to stop the target\n"
case '+':
if (remote_debug)
fprintf_unfiltered (gdb_stdlog, "Ack\n");
+ do_cleanups (old_chain);
return 1;
case '-':
if (remote_debug)
case SERIAL_TIMEOUT:
tcount++;
if (tcount > 3)
- return 0;
+ {
+ do_cleanups (old_chain);
+ return 0;
+ }
break; /* Retransmit buffer. */
case '$':
{
}
#endif
}
+
+ do_cleanups (old_chain);
return 0;
}
{
/* Make some more room in the buffer. */
*sizeof_buf += repeat;
- *buf_p = xrealloc (*buf_p, *sizeof_buf);
+ *buf_p = (char *) xrealloc (*buf_p, *sizeof_buf);
buf = *buf_p;
}
{
/* Make some more room in the buffer. */
*sizeof_buf *= 2;
- *buf_p = xrealloc (*buf_p, *sizeof_buf);
+ *buf_p = (char *) xrealloc (*buf_p, *sizeof_buf);
buf = *buf_p;
}
stop_reply_p event,
void *data)
{
- struct queue_iter_param *param = data;
+ struct queue_iter_param *param = (struct queue_iter_param *) data;
int parent_pid = *(int *) param->input;
if (is_pending_fork_parent (&event->ws, parent_pid, event->ptid))
{
struct remote_state *rs = get_remote_state ();
int len;
+ const char *remote_exec_file = get_remote_exec_file ();
/* If the user has disabled vRun support, or we have detected that
support is not available, do not try it. */
int run_worked;
char *stop_reply;
struct remote_state *rs = get_remote_state ();
+ const char *remote_exec_file = get_remote_exec_file ();
/* If running asynchronously, register the target file descriptor
with the event loop. */
static int
remote_stopped_by_sw_breakpoint (struct target_ops *ops)
{
- struct remote_state *rs = get_remote_state ();
+ struct thread_info *thread = inferior_thread ();
- return rs->stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT;
+ return (thread->priv != NULL
+ && thread->priv->stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT);
}
/* The to_supports_stopped_by_sw_breakpoint method of target
static int
remote_stopped_by_hw_breakpoint (struct target_ops *ops)
{
- struct remote_state *rs = get_remote_state ();
+ struct thread_info *thread = inferior_thread ();
- return rs->stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT;
+ return (thread->priv != NULL
+ && thread->priv->stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT);
}
/* The to_supports_stopped_by_hw_breakpoint method of target
static int
remote_stopped_by_watchpoint (struct target_ops *ops)
{
- struct remote_state *rs = get_remote_state ();
+ struct thread_info *thread = inferior_thread ();
- return rs->stop_reason == TARGET_STOPPED_BY_WATCHPOINT;
+ return (thread->priv != NULL
+ && thread->priv->stop_reason == TARGET_STOPPED_BY_WATCHPOINT);
}
static int
remote_stopped_data_address (struct target_ops *target, CORE_ADDR *addr_p)
{
- struct remote_state *rs = get_remote_state ();
- int rc = 0;
+ struct thread_info *thread = inferior_thread ();
- if (remote_stopped_by_watchpoint (target))
+ if (thread->priv != NULL
+ && thread->priv->stop_reason == TARGET_STOPPED_BY_WATCHPOINT)
{
- *addr_p = rs->remote_watch_data_address;
- rc = 1;
+ *addr_p = thread->priv->watch_data_address;
+ return 1;
}
- return rc;
+ return 0;
}
matched = 1; /* Do this section. */
lma = s->lma;
- sectdata = xmalloc (size);
+ sectdata = (gdb_byte *) xmalloc (size);
old_chain = make_cleanup (xfree, sectdata);
bfd_get_section_contents (exec_bfd, s, sectdata, 0, size);
const struct target_desc *tdesc)
{
struct remote_g_packet_data *data
- = gdbarch_data (gdbarch, remote_g_packet_data_handle);
+ = ((struct remote_g_packet_data *)
+ gdbarch_data (gdbarch, remote_g_packet_data_handle));
struct remote_g_packet_guess new_guess, *guess;
int ix;
remote_read_description_p (struct target_ops *target)
{
struct remote_g_packet_data *data
- = gdbarch_data (target_gdbarch (), remote_g_packet_data_handle);
+ = ((struct remote_g_packet_data *)
+ gdbarch_data (target_gdbarch (), remote_g_packet_data_handle));
if (!VEC_empty (remote_g_packet_guess_s, data->guesses))
return 1;
remote_read_description (struct target_ops *target)
{
struct remote_g_packet_data *data
- = gdbarch_data (target_gdbarch (), remote_g_packet_data_handle);
+ = ((struct remote_g_packet_data *)
+ gdbarch_data (target_gdbarch (), remote_g_packet_data_handle));
/* Do not try this during initial connection, when we do not know
whether there is a running but stopped thread. */
cache->fd = fd;
cache->offset = offset;
cache->bufsize = get_remote_packet_size ();
- cache->buf = xrealloc (cache->buf, cache->bufsize);
+ cache->buf = (gdb_byte *) xrealloc (cache->buf, cache->bufsize);
ret = remote_hostio_pread_vFile (self, cache->fd, cache->buf, cache->bufsize,
cache->offset, remote_errno);
if (len < 0)
return NULL;
- ret = xmalloc (len + 1);
+ ret = (char *) xmalloc (len + 1);
read_len = remote_unescape_input ((gdb_byte *) attachment, attachment_len,
(gdb_byte *) ret, len);
/* Send up to this many bytes at once. They won't all fit in the
remote packet limit, so we'll transfer slightly fewer. */
io_size = get_remote_packet_size ();
- buffer = xmalloc (io_size);
+ buffer = (gdb_byte *) xmalloc (io_size);
make_cleanup (xfree, buffer);
close_cleanup = make_cleanup (remote_hostio_close_cleanup, &fd);
/* Send up to this many bytes at once. They won't all fit in the
remote packet limit, so we'll transfer slightly fewer. */
io_size = get_remote_packet_size ();
- buffer = xmalloc (io_size);
+ buffer = (gdb_byte *) xmalloc (io_size);
make_cleanup (xfree, buffer);
close_cleanup = make_cleanup (remote_hostio_close_cleanup, &fd);
static void
free_actions_list_cleanup_wrapper (void *al)
{
- free_actions_list (al);
+ free_actions_list ((char **) al);
}
static void
target_pid_to_str (ptid));
}
- tinfo = xzalloc (sizeof (*tinfo));
+ tinfo = XCNEW (struct btrace_target_info);
tinfo->ptid = ptid;
/* If we fail to read the configuration, we lose some information, but the
{
const int annex_size = 9;
- annex = alloca (annex_size);
+ annex = (char *) alloca (annex_size);
xsnprintf (annex, annex_size, "%x", pid);
}
return filename;
}
+/* Implement the to_can_do_single_step target_ops method. */
+
+static int
+remote_can_do_single_step (struct target_ops *ops)
+{
+ /* We can only tell whether target supports single step or not by
+ supported s and S vCont actions if the stub supports vContSupported
+ feature. If the stub doesn't support vContSupported feature,
+ we have conservatively to think target doesn't supports single
+ step. */
+ if (packet_support (PACKET_vContSupported) == PACKET_ENABLE)
+ {
+ struct remote_state *rs = get_remote_state ();
+
+ if (packet_support (PACKET_vCont) == PACKET_SUPPORT_UNKNOWN)
+ remote_vcont_probe (rs);
+
+ return rs->supports_vCont.s && rs->supports_vCont.S;
+ }
+ else
+ return 0;
+}
+
static void
init_remote_ops (void)
{
remote_ops.to_pass_signals = remote_pass_signals;
remote_ops.to_program_signals = remote_program_signals;
remote_ops.to_thread_alive = remote_thread_alive;
+ remote_ops.to_thread_name = remote_thread_name;
remote_ops.to_update_thread_list = remote_update_thread_list;
remote_ops.to_pid_to_str = remote_pid_to_str;
remote_ops.to_extra_thread_info = remote_threads_extra_info;
remote_ops.to_get_ada_task_ptid = remote_get_ada_task_ptid;
remote_ops.to_stop = remote_stop;
remote_ops.to_interrupt = remote_interrupt;
+ remote_ops.to_check_pending_interrupt = remote_check_pending_interrupt;
remote_ops.to_xfer_partial = remote_xfer_partial;
remote_ops.to_rcmd = remote_rcmd;
remote_ops.to_pid_to_exec_file = remote_pid_to_exec_file;
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_thread_events = remote_thread_events;
+ remote_ops.to_can_do_single_step = remote_can_do_single_step;
remote_ops.to_terminal_inferior = remote_terminal_inferior;
remote_ops.to_terminal_ours = remote_terminal_ours;
remote_ops.to_supports_non_stop = remote_supports_non_stop;
extended_remote_ops.to_supports_disable_randomization
= extended_remote_supports_disable_randomization;
extended_remote_ops.to_follow_fork = remote_follow_fork;
+ extended_remote_ops.to_follow_exec = remote_follow_exec;
extended_remote_ops.to_insert_fork_catchpoint
= remote_insert_fork_catchpoint;
extended_remote_ops.to_remove_fork_catchpoint
= remote_insert_vfork_catchpoint;
extended_remote_ops.to_remove_vfork_catchpoint
= remote_remove_vfork_catchpoint;
+ extended_remote_ops.to_insert_exec_catchpoint
+ = remote_insert_exec_catchpoint;
+ extended_remote_ops.to_remove_exec_catchpoint
+ = remote_remove_exec_catchpoint;
}
static int
static void
remote_async_serial_handler (struct serial *scb, void *context)
{
- struct remote_state *rs = context;
+ struct remote_state *rs = (struct remote_state *) context;
/* Don't propogate error information up to the client. Instead let
the client find out about the error by querying the target. */
event loop to process them. */
if (!QUEUE_is_empty (stop_reply_p, stop_reply_queue))
mark_async_event_handler (remote_async_inferior_event_token);
+ /* For simplicity, below we clear the pending events token
+ without remembering whether it is marked, so here we always
+ mark it. If there's actually no pending notification to
+ process, this ends up being a no-op (other than a spurious
+ event-loop wakeup). */
+ if (target_is_non_stop_p ())
+ mark_async_event_handler (rs->notif_state->get_pending_events_token);
}
else
{
serial_async (rs->remote_desc, NULL, NULL);
+ /* If the core is disabling async, it doesn't want to be
+ disturbed with target events. Clear all async event sources
+ too. */
clear_async_event_handler (remote_async_inferior_event_token);
+ if (target_is_non_stop_p ())
+ clear_async_event_handler (rs->notif_state->get_pending_events_token);
+ }
+}
+
+/* Implementation of the to_thread_events method. */
+
+static void
+remote_thread_events (struct target_ops *ops, int enable)
+{
+ struct remote_state *rs = get_remote_state ();
+ size_t size = get_remote_packet_size ();
+ char *p = rs->buf;
+
+ if (packet_support (PACKET_QThreadEvents) == PACKET_DISABLE)
+ return;
+
+ xsnprintf (rs->buf, size, "QThreadEvents:%x", enable ? 1 : 0);
+ putpkt (rs->buf);
+ getpkt (&rs->buf, &rs->buf_size, 0);
+
+ switch (packet_ok (rs->buf,
+ &remote_protocol_packets[PACKET_QThreadEvents]))
+ {
+ case PACKET_OK:
+ if (strcmp (rs->buf, "OK") != 0)
+ error (_("Remote refused setting thread events: %s"), rs->buf);
+ break;
+ case PACKET_ERROR:
+ warning (_("Remote failure reply: %s"), rs->buf);
+ break;
+ case PACKET_UNKNOWN:
+ break;
}
}
remote_g_packet_data_handle =
gdbarch_data_register_pre_init (remote_g_packet_data_init);
+ remote_pspace_data
+ = register_program_space_data_with_cleanup (NULL,
+ remote_pspace_data_cleanup);
+
/* Initialize the per-target state. At the moment there is only one
of these, not one per target. Only one target is active at a
time. */
add_packet_config_cmd (&remote_protocol_packets[PACKET_Qbtrace_conf_bts_size],
"Qbtrace-conf:bts:size", "btrace-conf-bts-size", 0);
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_multiprocess_feature],
+ "multiprocess-feature", "multiprocess-feature", 0);
+
add_packet_config_cmd (&remote_protocol_packets[PACKET_swbreak_feature],
"swbreak-feature", "swbreak-feature", 0);
add_packet_config_cmd (&remote_protocol_packets[PACKET_Qbtrace_conf_pt_size],
"Qbtrace-conf:pt:size", "btrace-conf-pt-size", 0);
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_vContSupported],
+ "vContSupported", "verbose-resume-supported", 0);
+
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_exec_event_feature],
+ "exec-event-feature", "exec-event-feature", 0);
+
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_vCtrlC],
+ "vCtrlC", "ctrl-c", 0);
+
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_QThreadEvents],
+ "QThreadEvents", "thread-events", 0);
+
/* Assert that we've registered "set remote foo-packet" commands
for all packet configs. */
{
switch (i)
{
case PACKET_QNonStop:
- case PACKET_multiprocess_feature:
case PACKET_EnableDisableTracepoints_feature:
case PACKET_tracenz_feature:
case PACKET_DisconnectedTracing_feature:
_("Delete a remote file."),
&remote_cmdlist);
- remote_exec_file = xstrdup ("");
add_setshow_string_noescape_cmd ("exec-file", class_files,
- &remote_exec_file, _("\
+ &remote_exec_file_var, _("\
Set the remote pathname for \"run\""), _("\
-Show the remote pathname for \"run\""), NULL, NULL, NULL,
- &remote_set_cmdlist, &remote_show_cmdlist);
+Show the remote pathname for \"run\""), NULL,
+ set_remote_exec_file,
+ show_remote_exec_file,
+ &remote_set_cmdlist,
+ &remote_show_cmdlist);
add_setshow_boolean_cmd ("range-stepping", class_run,
&use_range_stepping, _("\
any_thread_ptid = ptid_build (42000, 0, 1);
target_buf_size = 2048;
- target_buf = xmalloc (target_buf_size);
+ target_buf = (char *) xmalloc (target_buf_size);
}