/* Remote target communications for serial-line targets in custom GDB protocol
- Copyright (C) 1988-2014 Free Software Foundation, Inc.
+ Copyright (C) 1988-2015 Free Software Foundation, Inc.
This file is part of GDB.
/* See the GDB User Guide for details of the GDB remote protocol. */
#include "defs.h"
-#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include "inferior.h"
+#include "infrun.h"
#include "bfd.h"
#include "symfile.h"
-#include "exceptions.h"
#include "target.h"
/*#include "terminal.h" */
#include "gdbcmd.h"
#include "remote-notif.h"
#include "regcache.h"
#include "value.h"
-#include "gdb_assert.h"
#include "observer.h"
#include "solib.h"
#include "cli/cli-decode.h"
static void remote_prepare_to_store (struct target_ops *self,
struct regcache *regcache);
-static void remote_open (char *name, int from_tty);
-
-static void extended_remote_open (char *name, int from_tty);
-
-static void remote_open_1 (char *, int, struct target_ops *, int extended_p);
+static void remote_open_1 (const char *, int, struct target_ops *,
+ int extended_p);
static void remote_close (struct target_ops *self);
static CORE_ADDR remote_address_masked (CORE_ADDR);
-static void print_packet (char *);
+static void print_packet (const char *);
static void compare_sections_command (char *, int);
static ptid_t remote_current_thread (ptid_t oldptid);
-static void remote_find_new_threads (void);
-
-static int putpkt_binary (char *buf, int cnt);
+static int putpkt_binary (const char *buf, int cnt);
static void check_binary_download (CORE_ADDR addr);
static int remote_can_run_breakpoint_commands (struct target_ops *self);
+static void remote_btrace_reset (void);
+
/* For "remote". */
static struct cmd_list_element *remote_cmdlist;
to stop for a watchpoint. */
CORE_ADDR remote_watch_data_address;
- /* This is non-zero if target stopped for a watchpoint. */
- int remote_stopped_by_watchpoint_p;
+ /* Whether the target stopped for a breakpoint/watchpoint. */
+ enum target_stop_reason stop_reason;
threadref echo_nextthread;
threadref nextthread;
/* The state of remote notification. */
struct remote_notif_state *notif_state;
+
+ /* The branch trace configuration. */
+ struct btrace_config btrace_config;
};
/* Private data that we'll store in (struct thread_info)->private. */
buf = *buf_p;
if (buf[0] == 'E')
trace_error (buf);
- else if (strncmp (buf, "qRelocInsn:", strlen ("qRelocInsn:")) == 0)
+ else if (startswith (buf, "qRelocInsn:"))
{
ULONGEST ul;
CORE_ADDR from, to, org_to;
char *p, *pp;
int adjusted_size = 0;
volatile struct gdb_exception ex;
+ int relocated = 0;
p = buf + strlen ("qRelocInsn:");
pp = unpack_varlen_hex (p, &ul);
TRY_CATCH (ex, RETURN_MASK_ALL)
{
gdbarch_relocate_instruction (target_gdbarch (), &to, from);
+ relocated = 1;
+ }
+ if (ex.reason < 0)
+ {
+ if (ex.error == MEMORY_ERROR)
+ {
+ /* Propagate memory errors silently back to the
+ target. The stub may have limited the range of
+ addresses we can write to, for example. */
+ }
+ else
+ {
+ /* Something unexpectedly bad happened. Be verbose
+ so we can tell what, and propagate the error back
+ to the stub, so it doesn't get stuck waiting for
+ a response. */
+ exception_fprintf (gdb_stderr, ex,
+ _("warning: relocating instruction: "));
+ }
+ putpkt ("E01");
}
- if (ex.reason >= 0)
+
+ if (relocated)
{
adjusted_size = to - org_to;
xsnprintf (buf, *sizeof_buf, "qRelocInsn:%x", adjusted_size);
putpkt (buf);
}
- else if (ex.reason < 0 && ex.error == MEMORY_ERROR)
- {
- /* Propagate memory errors silently back to the target.
- The stub may have limited the range of addresses we
- can write to, for example. */
- putpkt ("E01");
- }
- else
- {
- /* Something unexpectedly bad happened. Be verbose so
- we can tell what, and propagate the error back to the
- stub, so it doesn't get stuck waiting for a
- response. */
- exception_fprintf (gdb_stderr, ex,
- _("warning: relocating instruction: "));
- putpkt ("E01");
- }
}
else if (buf[0] == 'O' && buf[1] != 'K')
remote_console_output (buf + 1); /* 'O' message from stub */
/* If auto, GDB auto-detects support for this packet or feature,
either through qSupported, or by trying the packet and looking
at the response. If true, GDB assumes the target supports this
- packet. If false, the packet is disabled. */
+ packet. If false, the packet is disabled. Configs that don't
+ have an associated command always have this set to auto. */
enum auto_boolean detect;
/* Does the target support this packet? */
config->name = name;
config->title = title;
- config->detect = AUTO_BOOLEAN_AUTO;
- config->support = PACKET_SUPPORT_UNKNOWN;
set_doc = xstrprintf ("Set use of remote protocol `%s' (%s) packet",
name, title);
show_doc = xstrprintf ("Show current use of remote "
PACKET_qTStatus,
PACKET_QPassSignals,
PACKET_QProgramSignals,
+ PACKET_qCRC,
PACKET_qSearch_memory,
PACKET_vAttach,
PACKET_vRun,
/* Support for qXfer:libraries-svr4:read with a non-empty annex. */
PACKET_augmented_libraries_svr4_read_feature,
+ /* Support for the qXfer:btrace-conf:read packet. */
+ PACKET_qXfer_btrace_conf,
+
+ /* Support for the Qbtrace-conf:bts:size packet. */
+ PACKET_Qbtrace_conf_bts_size,
+
+ /* Support for swbreak+ feature. */
+ PACKET_swbreak_feature,
+
+ /* Support for hwbreak+ feature. */
+ PACKET_hwbreak_feature,
+
PACKET_MAX
};
static struct packet_config remote_protocol_packets[PACKET_MAX];
+/* Returns the packet's corresponding "set remote foo-packet" command
+ state. See struct packet_config for more details. */
+
+static enum auto_boolean
+packet_set_cmd_state (int packet)
+{
+ return remote_protocol_packets[packet].detect;
+}
+
/* Returns whether a given packet or feature is supported. This takes
into account the state of the corresponding "set remote foo-packet"
command, which may be used to bypass auto-detection. */
gdb_assert (info);
- if (!info->private)
+ if (!info->priv)
{
- info->private = xmalloc (sizeof (*(info->private)));
+ info->priv = xmalloc (sizeof (*(info->priv)));
info->private_dtor = free_private_thread_info;
- info->private->core = -1;
- info->private->extra = 0;
+ info->priv->core = -1;
+ info->priv->extra = 0;
}
- return info->private;
+ return info->priv;
}
/* Call this function as a result of
}
\f
-/* Return nonzero if the thread PTID is still alive on the remote
- system. */
+/* Return nonzero if this is the main thread that we made up ourselves
+ to model non-threaded targets as single-threaded. */
static int
-remote_thread_alive (struct target_ops *ops, ptid_t ptid)
+remote_thread_always_alive (struct target_ops *ops, ptid_t ptid)
{
struct remote_state *rs = get_remote_state ();
char *p, *endp;
multi-threading. */
return 1;
+ return 0;
+}
+
+/* Return nonzero if the thread PTID is still alive on the remote
+ system. */
+
+static int
+remote_thread_alive (struct target_ops *ops, ptid_t ptid)
+{
+ struct remote_state *rs = get_remote_state ();
+ char *p, *endp;
+
+ /* Check if this is a thread that we made up ourselves to model
+ non-threaded targets as single-threaded. */
+ if (remote_thread_always_alive (ops, ptid))
+ return 1;
+
p = rs->buf;
endp = rs->buf + get_remote_packet_size ();
return resultcount;
}
+/* Fetch the next batch of threads from the remote. Returns -1 if the
+ qL packet is not supported, 0 on error and 1 on success. */
+
static int
remote_get_threadlist (int startflag, threadref *nextthread, int result_limit,
int *done, int *result_count, threadref *threadlist)
pack_threadlist_request (rs->buf, startflag, result_limit, nextthread);
putpkt (rs->buf);
getpkt (&rs->buf, &rs->buf_size, 0);
-
if (*rs->buf == '\0')
- return 0;
- else
- *result_count =
- parse_threadlist_response (rs->buf + 2, result_limit,
- &rs->echo_nextthread, threadlist, done);
+ {
+ /* Packet not supported. */
+ return -1;
+ }
+
+ *result_count =
+ parse_threadlist_response (rs->buf + 2, result_limit,
+ &rs->echo_nextthread, threadlist, done);
if (!threadmatch (&rs->echo_nextthread, nextthread))
{
return result;
}
-/* This is the interface between remote and threads, remotes upper
- interface. */
-
-/* remote_find_new_threads retrieves the thread list and for each
- thread in the list, looks up the thread in GDB's internal list,
- 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. */
-
+/* Fetch the list of remote threads, with the qL packet, and call
+ STEPFUNCTION for each thread found. Stops iterating and returns 1
+ if STEPFUNCTION returns true. Stops iterating and returns 0 if the
+ STEPFUNCTION returns false. If the packet is not supported,
+ returns -1. */
static int
remote_threadlist_iterator (rmt_thread_action stepfunction, void *context,
warning (_("Remote fetch threadlist -infinite loop-."));
break;
}
- if (!remote_get_threadlist (startflag, &rs->nextthread,
- MAXTHREADLISTRESULTS,
- &done, &result_count, rs->resultthreadlist))
- {
- result = 0;
- break;
- }
+ result = remote_get_threadlist (startflag, &rs->nextthread,
+ MAXTHREADLISTRESULTS,
+ &done, &result_count,
+ rs->resultthreadlist);
+ if (result <= 0)
+ break;
/* Clear for later iterations. */
startflag = 0;
/* Setup to resume next batch of thread references, set nextthread. */
&rs->resultthreadlist[result_count - 1]);
i = 0;
while (result_count--)
- if (!(result = (*stepfunction) (&rs->resultthreadlist[i++], context)))
- break;
+ {
+ if (!(*stepfunction) (&rs->resultthreadlist[i++], context))
+ {
+ result = 0;
+ break;
+ }
+ }
}
return result;
}
+/* A thread found on the remote target. */
+
+typedef struct thread_item
+{
+ /* The thread's PTID. */
+ ptid_t ptid;
+
+ /* The thread's extra info. May be NULL. */
+ char *extra;
+
+ /* The core the thread was running on. -1 if not known. */
+ int core;
+} thread_item_t;
+DEF_VEC_O(thread_item_t);
+
+/* Context passed around to the various methods listing remote
+ threads. As new threads are found, they're added to the ITEMS
+ vector. */
+
+struct threads_listing_context
+{
+ /* The threads found on the remote target. */
+ VEC (thread_item_t) *items;
+};
+
+/* Discard the contents of the constructed thread listing context. */
+
+static void
+clear_threads_listing_context (void *p)
+{
+ struct threads_listing_context *context = p;
+ int i;
+ struct thread_item *item;
+
+ for (i = 0; VEC_iterate (thread_item_t, context->items, i, item); ++i)
+ xfree (item->extra);
+
+ VEC_free (thread_item_t, context->items);
+}
+
static int
-remote_newthread_step (threadref *ref, void *context)
+remote_newthread_step (threadref *ref, void *data)
{
+ struct threads_listing_context *context = data;
+ struct thread_item item;
int pid = ptid_get_pid (inferior_ptid);
- ptid_t ptid = ptid_build (pid, threadref_to_int (ref), 0);
- if (!in_thread_list (ptid))
- add_thread (ptid);
+ item.ptid = ptid_build (pid, threadref_to_int (ref), 0);
+ item.core = -1;
+ item.extra = NULL;
+
+ VEC_safe_push (thread_item_t, context->items, &item);
+
return 1; /* continue iterator */
}
return oldpid;
}
-/* Find new threads for info threads command.
- * Original version, using John Metzler's thread protocol.
- */
+/* List remote threads using the deprecated qL packet. */
-static void
-remote_find_new_threads (void)
+static int
+remote_get_threads_with_ql (struct target_ops *ops,
+ struct threads_listing_context *context)
{
- remote_threadlist_iterator (remote_newthread_step, 0,
- CRAZY_MAX_THREADS);
+ if (remote_threadlist_iterator (remote_newthread_step, context,
+ CRAZY_MAX_THREADS) >= 0)
+ return 1;
+
+ return 0;
}
#if defined(HAVE_LIBEXPAT)
-typedef struct thread_item
-{
- ptid_t ptid;
- char *extra;
- int core;
-} thread_item_t;
-DEF_VEC_O(thread_item_t);
-
-struct threads_parsing_context
-{
- VEC (thread_item_t) *items;
-};
-
static void
start_thread (struct gdb_xml_parser *parser,
const struct gdb_xml_element *element,
void *user_data, VEC(gdb_xml_value_s) *attributes)
{
- struct threads_parsing_context *data = user_data;
+ struct threads_listing_context *data = user_data;
struct thread_item item;
char *id;
const struct gdb_xml_element *element,
void *user_data, const char *body_text)
{
- struct threads_parsing_context *data = user_data;
+ struct threads_listing_context *data = user_data;
if (body_text && *body_text)
VEC_last (thread_item_t, data->items)->extra = xstrdup (body_text);
{ NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
};
-/* Discard the contents of the constructed thread info context. */
-
-static void
-clear_threads_parsing_context (void *p)
-{
- struct threads_parsing_context *context = p;
- int i;
- struct thread_item *item;
-
- for (i = 0; VEC_iterate (thread_item_t, context->items, i, item); ++i)
- xfree (item->extra);
-
- VEC_free (thread_item_t, context->items);
-}
-
#endif
-/*
- * Find all threads for info threads command.
- * Uses new thread protocol contributed by Cisco.
- * Falls back and attempts to use the older method (above)
- * if the target doesn't respond to the new method.
- */
+/* List remote threads using qXfer:threads:read. */
-static void
-remote_threads_info (struct target_ops *ops)
+static int
+remote_get_threads_with_qxfer (struct target_ops *ops,
+ struct threads_listing_context *context)
{
- struct remote_state *rs = get_remote_state ();
- char *bufp;
- ptid_t new_thread;
-
- if (rs->remote_desc == 0) /* paranoia */
- error (_("Command can only be used when connected to the remote target."));
-
#if defined(HAVE_LIBEXPAT)
if (packet_support (PACKET_qXfer_threads) == PACKET_ENABLE)
{
- char *xml = target_read_stralloc (¤t_target,
- TARGET_OBJECT_THREADS, NULL);
-
+ char *xml = target_read_stralloc (ops, TARGET_OBJECT_THREADS, NULL);
struct cleanup *back_to = make_cleanup (xfree, xml);
- if (xml && *xml)
+ if (xml != NULL && *xml != '\0')
{
- struct threads_parsing_context context;
-
- context.items = NULL;
- make_cleanup (clear_threads_parsing_context, &context);
-
- if (gdb_xml_parse_quick (_("threads"), "threads.dtd",
- threads_elements, xml, &context) == 0)
- {
- int i;
- struct thread_item *item;
-
- for (i = 0;
- VEC_iterate (thread_item_t, context.items, i, item);
- ++i)
- {
- if (!ptid_equal (item->ptid, null_ptid))
- {
- struct private_thread_info *info;
- /* In non-stop mode, we assume new found threads
- are 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;
-
- remote_notice_new_inferior (item->ptid, running);
-
- info = demand_private_info (item->ptid);
- info->core = item->core;
- info->extra = item->extra;
- item->extra = NULL;
- }
- }
- }
+ gdb_xml_parse_quick (_("threads"), "threads.dtd",
+ threads_elements, xml, context);
}
do_cleanups (back_to);
- return;
+ return 1;
}
#endif
+ return 0;
+}
+
+/* List remote threads using qfThreadInfo/qsThreadInfo. */
+
+static int
+remote_get_threads_with_qthreadinfo (struct target_ops *ops,
+ struct threads_listing_context *context)
+{
+ struct remote_state *rs = get_remote_state ();
+
if (rs->use_threadinfo_query)
{
+ char *bufp;
+
putpkt ("qfThreadInfo");
getpkt (&rs->buf, &rs->buf_size, 0);
bufp = rs->buf;
if (bufp[0] != '\0') /* q packet recognized */
{
- struct cleanup *old_chain;
- char *saved_reply;
-
- /* remote_notice_new_inferior (in the loop below) may make
- new RSP calls, which clobber rs->buf. Work with a
- copy. */
- bufp = saved_reply = xstrdup (rs->buf);
- old_chain = make_cleanup (free_current_contents, &saved_reply);
-
while (*bufp++ == 'm') /* reply contains one or more TID */
{
do
{
- new_thread = read_ptid (bufp, &bufp);
- if (!ptid_equal (new_thread, null_ptid))
- {
- /* In non-stop mode, we assume new found threads
- are 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;
+ struct thread_item item;
- remote_notice_new_inferior (new_thread, running);
- }
+ item.ptid = read_ptid (bufp, &bufp);
+ item.core = -1;
+ item.extra = NULL;
+
+ VEC_safe_push (thread_item_t, context->items, &item);
}
while (*bufp++ == ','); /* comma-separated list */
- free_current_contents (&saved_reply);
putpkt ("qsThreadInfo");
getpkt (&rs->buf, &rs->buf_size, 0);
- bufp = saved_reply = xstrdup (rs->buf);
+ bufp = rs->buf;
}
+ return 1;
+ }
+ else
+ {
+ /* Packet not recognized. */
+ rs->use_threadinfo_query = 0;
+ }
+ }
+
+ return 0;
+}
+
+/* Implement the to_update_thread_list function for the remote
+ targets. */
+
+static void
+remote_update_thread_list (struct target_ops *ops)
+{
+ struct remote_state *rs = get_remote_state ();
+ struct threads_listing_context context;
+ struct cleanup *old_chain;
+ int got_list = 0;
+
+ context.items = NULL;
+ old_chain = make_cleanup (clear_threads_listing_context, &context);
+
+ /* We have a few different mechanisms to fetch the thread list. Try
+ them all, starting with the most preferred one first, falling
+ back to older methods. */
+ if (remote_get_threads_with_qxfer (ops, &context)
+ || remote_get_threads_with_qthreadinfo (ops, &context)
+ || remote_get_threads_with_ql (ops, &context))
+ {
+ int i;
+ struct thread_item *item;
+ struct thread_info *tp, *tmp;
+
+ got_list = 1;
+
+ if (VEC_empty (thread_item_t, context.items)
+ && remote_thread_always_alive (ops, inferior_ptid))
+ {
+ /* Some targets don't really support threads, but still
+ reply an (empty) thread list in response to the thread
+ listing packets, instead of replying "packet not
+ supported". Exit early so we don't delete the main
+ thread. */
do_cleanups (old_chain);
- return; /* done */
+ return;
+ }
+
+ /* CONTEXT now holds the current thread list on the remote
+ target end. Delete GDB-side threads no longer found on the
+ target. */
+ ALL_NON_EXITED_THREADS_SAFE (tp, tmp)
+ {
+ for (i = 0;
+ VEC_iterate (thread_item_t, context.items, i, item);
+ ++i)
+ {
+ if (ptid_equal (item->ptid, tp->ptid))
+ break;
+ }
+
+ if (i == VEC_length (thread_item_t, context.items))
+ {
+ /* Not found. */
+ delete_thread (tp->ptid);
+ }
+ }
+
+ /* And now add threads we don't know about yet to our list. */
+ for (i = 0;
+ VEC_iterate (thread_item_t, context.items, i, item);
+ ++i)
+ {
+ if (!ptid_equal (item->ptid, null_ptid))
+ {
+ struct private_thread_info *info;
+ /* In non-stop mode, we assume new found threads are
+ 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;
+
+ remote_notice_new_inferior (item->ptid, running);
+
+ info = demand_private_info (item->ptid);
+ info->core = item->core;
+ info->extra = item->extra;
+ item->extra = NULL;
+ }
}
}
- /* Only qfThreadInfo is supported in non-stop mode. */
- if (non_stop)
- return;
+ if (!got_list)
+ {
+ /* If no thread listing method is supported, then query whether
+ each known thread is alive, one by one, with the T packet.
+ If the target doesn't support threads at all, then this is a
+ no-op. See remote_thread_alive. */
+ prune_threads ();
+ }
- /* Else fall back to old method based on jmetzler protocol. */
- rs->use_threadinfo_query = 0;
- remote_find_new_threads ();
- return;
+ do_cleanups (old_chain);
}
/*
{
struct thread_info *info = find_thread_ptid (tp->ptid);
- if (info && info->private)
- return info->private->extra;
+ if (info && info->priv)
+ return info->priv->extra;
else
return NULL;
}
ptr = buf;
lose = 0;
- if (strncmp (ptr, "Text=", 5) == 0)
+ if (startswith (ptr, "Text="))
{
ptr += 5;
/* Don't use strtol, could lose on big values. */
while (*ptr && *ptr != ';')
text_addr = (text_addr << 4) + fromhex (*ptr++);
- if (strncmp (ptr, ";Data=", 6) == 0)
+ if (startswith (ptr, ";Data="))
{
ptr += 6;
while (*ptr && *ptr != ';')
else
lose = 1;
- if (!lose && strncmp (ptr, ";Bss=", 5) == 0)
+ if (!lose && startswith (ptr, ";Bss="))
{
ptr += 5;
while (*ptr && *ptr != ';')
else
lose = 1;
}
- else if (strncmp (ptr, "TextSeg=", 8) == 0)
+ else if (startswith (ptr, "TextSeg="))
{
ptr += 8;
/* Don't use strtol, could lose on big values. */
text_addr = (text_addr << 4) + fromhex (*ptr++);
num_segments = 1;
- if (strncmp (ptr, ";DataSeg=", 9) == 0)
+ if (startswith (ptr, ";DataSeg="))
{
ptr += 9;
while (*ptr && *ptr != ';')
controlling. We default to adding them in the running state.
The '?' query below will then tell us about which threads are
stopped. */
- remote_threads_info (target);
+ remote_update_thread_list (target);
}
else if (packet_support (PACKET_QNonStop) == PACKET_ENABLE)
{
}
/* Fetch thread list. */
- target_find_new_threads ();
+ target_update_thread_list ();
/* Let the stub know that we want it to return the thread. */
set_continue_thread (minus_one_ptid);
up. */
rs->starting_up = 0;
- /* If breakpoints are global, insert them now. */
- if (gdbarch_has_global_breakpoints (target_gdbarch ())
- && breakpoints_always_inserted_mode ())
+ /* Maybe breakpoints are global and need to be inserted now. */
+ if (breakpoints_should_be_inserted_now ())
insert_breakpoints ();
}
NAME is the filename used for communication. */
static void
-remote_open (char *name, int from_tty)
+remote_open (const char *name, int from_tty)
{
remote_open_1 (name, from_tty, &remote_ops, 0);
}
remote gdb protocol. NAME is the filename used for communication. */
static void
-extended_remote_open (char *name, int from_tty)
+extended_remote_open (const char *name, int from_tty)
{
remote_open_1 (name, from_tty, &extended_remote_ops, 1 /*extended_p */);
}
-/* Generic code for opening a connection to a remote target. */
+/* Reset all packets back to "unknown support". Called when opening a
+ new connection to a remote target. */
static void
-init_all_packet_configs (void)
+reset_all_packet_configs_support (void)
{
int i;
remote_protocol_packets[i].support = PACKET_SUPPORT_UNKNOWN;
}
+/* Initialize all packet configs. */
+
+static void
+init_all_packet_configs (void)
+{
+ int i;
+
+ for (i = 0; i < PACKET_MAX; i++)
+ {
+ remote_protocol_packets[i].detect = AUTO_BOOLEAN_AUTO;
+ remote_protocol_packets[i].support = PACKET_SUPPORT_UNKNOWN;
+ }
+}
+
/* Symbol look-up. */
static void
packet_ok (rs->buf, &remote_protocol_packets[PACKET_qSymbol]);
reply = rs->buf;
- while (strncmp (reply, "qSymbol:", 8) == 0)
+ while (startswith (reply, "qSymbol:"))
{
struct bound_minimal_symbol sym;
}
static struct serial *
-remote_serial_open (char *name)
+remote_serial_open (const char *name)
{
static int udp_warning = 0;
of in ser-tcp.c, because it is the remote protocol assuming that the
serial connection is reliable and not the serial connection promising
to be. */
- if (!udp_warning && strncmp (name, "udp:", 4) == 0)
+ if (!udp_warning && startswith (name, "udp:"))
{
warning (_("The remote protocol may be unreliable over UDP.\n"
"Some events may be lost, rendering further debugging "
{ "Qbtrace:off", PACKET_DISABLE, remote_supported_packet, PACKET_Qbtrace_off },
{ "Qbtrace:bts", PACKET_DISABLE, remote_supported_packet, PACKET_Qbtrace_bts },
{ "qXfer:btrace:read", PACKET_DISABLE, remote_supported_packet,
- PACKET_qXfer_btrace }
+ PACKET_qXfer_btrace },
+ { "qXfer:btrace-conf:read", PACKET_DISABLE, remote_supported_packet,
+ PACKET_qXfer_btrace_conf },
+ { "Qbtrace-conf:bts:size", PACKET_DISABLE, remote_supported_packet,
+ PACKET_Qbtrace_conf_bts_size },
+ { "swbreak", PACKET_DISABLE, remote_supported_packet, PACKET_swbreak_feature },
+ { "hwbreak", PACKET_DISABLE, remote_supported_packet, PACKET_hwbreak_feature }
};
static char *remote_support_xml;
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);
}
static void
-remote_open_1 (char *name, int from_tty,
+remote_open_1 (const char *name, int from_tty,
struct target_ops *target, int extended_p)
{
struct remote_state *rs = get_remote_state ();
/* Reset the target state; these things will be queried either by
remote_query_supported or as they are needed. */
- init_all_packet_configs ();
+ reset_all_packet_configs_support ();
rs->cached_wait_status = 0;
rs->explicit_packet_size = 0;
rs->noack_mode = 0;
}
}
+ remote_btrace_reset ();
+
if (target_async_permitted)
wait_forever_enabled_p = 1;
}
/* Same as remote_detach, but don't send the "D" packet; just disconnect. */
static void
-remote_disconnect (struct target_ops *target, char *args, int from_tty)
+remote_disconnect (struct target_ops *target, const char *args, int from_tty)
{
if (args)
error (_("Argument given to \"disconnect\" when remotely debugging."));
be chatty about it. */
static void
-extended_remote_attach_1 (struct target_ops *target, char *args, int from_tty)
+extended_remote_attach_1 (struct target_ops *target, const char *args,
+ int from_tty)
{
struct remote_state *rs = get_remote_state ();
int pid;
struct thread_info *thread;
/* Get list of threads. */
- remote_threads_info (target);
+ remote_update_thread_list (target);
thread = first_thread_of_process (pid);
if (thread)
}
static void
-extended_remote_attach (struct target_ops *ops, char *args, int from_tty)
+extended_remote_attach (struct target_ops *ops, const char *args, int from_tty)
{
extended_remote_attach_1 (ops, args, from_tty);
}
+/* Implementation of the to_post_attach method. */
+
+static void
+extended_remote_post_attach (struct target_ops *ops, int pid)
+{
+ /* 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
+ present (on Linux) and the binary itself hadn't changed since the
+ debugging process was started. */
+ if (symfile_objfile != NULL)
+ remote_check_symbols();
+}
+
\f
/* Check for the availability of vCont. This function should also check
the response. */
buf = rs->buf;
/* Make sure that the features we assume are supported. */
- if (strncmp (buf, "vCont", 5) == 0)
+ if (startswith (buf, "vCont"))
{
char *p = &buf[5];
int support_s, support_S, support_c, support_C;
{
struct thread_info *thread;
- ALL_THREADS (thread)
+ ALL_NON_EXITED_THREADS (thread)
if (ptid_match (thread->ptid, ptid)
&& !ptid_equal (inferior_ptid, thread->ptid)
- && thread->suspend.stop_signal != GDB_SIGNAL_0
- && signal_pass_state (thread->suspend.stop_signal))
+ && thread->suspend.stop_signal != GDB_SIGNAL_0)
{
p = append_resumption (p, endp, thread->ptid,
0, thread->suspend.stop_signal);
async_handle_remote_sigint (int sig)
{
signal (sig, async_handle_remote_sigint_twice);
- mark_async_signal_handler (async_sigint_remote_token);
+ /* Note we need to go through gdb_call_async_signal_handler in order
+ to wake up the event loop on Windows. */
+ gdb_call_async_signal_handler (async_sigint_remote_token, 0);
}
/* Signal handler for SIGINT, installed after SIGINT has already been
async_handle_remote_sigint_twice (int sig)
{
signal (sig, async_handle_remote_sigint);
- mark_async_signal_handler (async_sigint_remote_twice_token);
+ /* See note in async_handle_remote_sigint. */
+ gdb_call_async_signal_handler (async_sigint_remote_twice_token, 0);
}
/* Perform the real interruption of the target execution, in response
{
target_terminal_ours ();
- if (target_can_async_p ())
+ if (target_is_async_p ())
{
signal (SIGINT, handle_sigint);
quit ();
fetch them is avoided). */
VEC(cached_reg_t) *regcache;
- int stopped_by_watchpoint_p;
+ enum target_stop_reason stop_reason;
+
CORE_ADDR watch_data_address;
int core;
stop_reply_match_ptid_and_ws, &ptid);
}
+/* Skip PACKET until the next semi-colon (or end of string). */
+
+static char *
+skip_to_semicolon (char *p)
+{
+ while (*p != '\0' && *p != ';')
+ p++;
+ return p;
+}
+
/* Parse the stop reply in BUF. Either the function succeeds, and the
result is stored in EVENT, or throws an error. */
event->rs = get_remote_state ();
event->ws.kind = TARGET_WAITKIND_IGNORE;
event->ws.value.integer = 0;
- event->stopped_by_watchpoint_p = 0;
+ event->stop_reason = TARGET_STOPPED_BY_NO_REASON;
event->regcache = NULL;
event->core = -1;
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. */
+ p1 = strchr (p, ':');
+ if (p1 == NULL)
+ error (_("Malformed packet(a) (missing colon): %s\n\
+Packet: '%s'\n"),
+ p, buf);
+ if (p == p1)
+ error (_("Malformed packet(a) (missing register number): %s\n\
+Packet: '%s'\n"),
+ p, buf);
- /* If this packet is an awatch packet, don't parse the 'a'
- as a register number. */
+ /* Some "registers" are actually extended stop information.
+ Note if you're adding a new entry here: GDB 7.9 and
+ earlier assume that all register "numbers" that start
+ with an hex digit are real register numbers. Make sure
+ the server only sends such a packet if it knows the
+ client understands it. */
- if (strncmp (p, "awatch", strlen("awatch")) != 0
- && strncmp (p, "core", strlen ("core") != 0))
+ if (strncmp (p, "thread", p1 - p) == 0)
+ event->ptid = read_ptid (++p1, &p);
+ else if ((strncmp (p, "watch", p1 - p) == 0)
+ || (strncmp (p, "rwatch", p1 - p) == 0)
+ || (strncmp (p, "awatch", p1 - p) == 0))
{
- /* Read the ``P'' register number. */
- pnum = strtol (p, &p_temp, 16);
- p1 = p_temp;
+ event->stop_reason = TARGET_STOPPED_BY_WATCHPOINT;
+ p = unpack_varlen_hex (++p1, &addr);
+ event->watch_data_address = (CORE_ADDR) addr;
}
- else
- p1 = p;
-
- if (p1 == p) /* No register number present here. */
+ else if (strncmp (p, "swbreak", p1 - p) == 0)
{
- 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)
- event->ptid = read_ptid (++p1, &p);
- else if ((strncmp (p, "watch", p1 - p) == 0)
- || (strncmp (p, "rwatch", p1 - p) == 0)
- || (strncmp (p, "awatch", p1 - p) == 0))
- {
- event->stopped_by_watchpoint_p = 1;
- p = unpack_varlen_hex (++p1, &addr);
- event->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++;
+ event->stop_reason = TARGET_STOPPED_BY_SW_BREAKPOINT;
- event->ws.kind = TARGET_WAITKIND_LOADED;
- p = p_temp;
- }
- else if (strncmp (p, "replaylog", p1 - p) == 0)
- {
- event->ws.kind = TARGET_WAITKIND_NO_HISTORY;
- /* p1 will indicate "begin" or "end", but it makes
- no difference for now, so ignore it. */
- p_temp = strchr (p1 + 1, ';');
- if (p_temp)
- p = p_temp;
- }
- else if (strncmp (p, "core", p1 - p) == 0)
- {
- ULONGEST c;
+ /* Make sure the stub doesn't forget to indicate support
+ with qSupported. */
+ if (packet_support (PACKET_swbreak_feature) != PACKET_ENABLE)
+ error (_("Unexpected swbreak stop reason"));
- p = unpack_varlen_hex (++p1, &c);
- event->core = c;
- }
- else
- {
- /* Silently skip unknown optional info. */
- p_temp = strchr (p1 + 1, ';');
- if (p_temp)
- p = p_temp;
- }
+ /* The value part is documented as "must be empty",
+ though we ignore it, in case we ever decide to make
+ use of it in a backward compatible way. */
+ p = skip_to_semicolon (p1 + 1);
}
- else
+ else if (strncmp (p, "hwbreak", p1 - p) == 0)
{
- struct packet_reg *reg = packet_reg_from_pnum (rsa, pnum);
- cached_reg_t cached_reg;
+ event->stop_reason = TARGET_STOPPED_BY_HW_BREAKPOINT;
- p = p1;
+ /* Make sure the stub doesn't forget to indicate support
+ with qSupported. */
+ if (packet_support (PACKET_hwbreak_feature) != PACKET_ENABLE)
+ error (_("Unexpected hwbreak stop reason"));
- if (*p != ':')
- error (_("Malformed packet(b) (missing colon): %s\n\
-Packet: '%s'\n"),
- p, buf);
- ++p;
+ /* See above. */
+ p = skip_to_semicolon (p1 + 1);
+ }
+ else if (strncmp (p, "library", p1 - p) == 0)
+ {
+ event->ws.kind = TARGET_WAITKIND_LOADED;
+ p = skip_to_semicolon (p1 + 1);
+ }
+ else if (strncmp (p, "replaylog", p1 - p) == 0)
+ {
+ event->ws.kind = TARGET_WAITKIND_NO_HISTORY;
+ /* p1 will indicate "begin" or "end", but it makes
+ no difference for now, so ignore it. */
+ p = skip_to_semicolon (p1 + 1);
+ }
+ else if (strncmp (p, "core", p1 - p) == 0)
+ {
+ ULONGEST c;
- if (reg == NULL)
- error (_("Remote sent bad register number %s: %s\n\
+ p = unpack_varlen_hex (++p1, &c);
+ event->core = c;
+ }
+ else
+ {
+ ULONGEST pnum;
+ char *p_temp;
+
+ /* Maybe a real ``P'' register number. */
+ p_temp = unpack_varlen_hex (p, &pnum);
+ /* If the first invalid character is the colon, we got a
+ register number. Otherwise, it's an unknown stop
+ reason. */
+ if (p_temp == p1)
+ {
+ struct packet_reg *reg = packet_reg_from_pnum (rsa, pnum);
+ cached_reg_t cached_reg;
+
+ if (reg == NULL)
+ error (_("Remote sent bad register number %s: %s\n\
Packet: '%s'\n"),
- hex_string (pnum), p, buf);
+ hex_string (pnum), p, buf);
- cached_reg.num = reg->regnum;
+ cached_reg.num = reg->regnum;
- fieldsize = hex2bin (p, cached_reg.data,
- register_size (target_gdbarch (),
- reg->regnum));
- p += 2 * fieldsize;
- if (fieldsize < register_size (target_gdbarch (),
- reg->regnum))
- warning (_("Remote reply is too short: %s"), buf);
+ p = p1 + 1;
+ fieldsize = hex2bin (p, cached_reg.data,
+ register_size (target_gdbarch (),
+ reg->regnum));
+ p += 2 * fieldsize;
+ if (fieldsize < register_size (target_gdbarch (),
+ reg->regnum))
+ warning (_("Remote reply is too short: %s"), buf);
- VEC_safe_push (cached_reg_t, event->regcache, &cached_reg);
+ VEC_safe_push (cached_reg_t, event->regcache, &cached_reg);
+ }
+ else
+ {
+ /* Not a number. Silently skip unknown optional
+ info. */
+ p = skip_to_semicolon (p1 + 1);
+ }
}
if (*p != ';')
{
p++;
- if (p == '\0')
+ if (*p == '\0')
;
- else if (strncmp (p,
- "process:", sizeof ("process:") - 1) == 0)
+ else if (startswith (p, "process:"))
{
ULONGEST upid;
VEC_free (cached_reg_t, stop_reply->regcache);
}
- rs->remote_stopped_by_watchpoint_p = stop_reply->stopped_by_watchpoint_p;
+ rs->stop_reason = stop_reply->stop_reason;
rs->remote_watch_data_address = stop_reply->watch_data_address;
remote_notice_new_inferior (ptid, 0);
buf = rs->buf;
- rs->remote_stopped_by_watchpoint_p = 0;
+ rs->stop_reason = TARGET_STOPPED_BY_NO_REASON;
/* We got something. */
rs->waiting_for_stop_reply = 0;
else
event_ptid = remote_wait_as (ptid, status, options);
- if (target_can_async_p ())
+ if (target_is_async_p ())
{
/* If there are are events left in the queue tell the event loop
to return here. */
gdb_byte *myaddr, ULONGEST len, ULONGEST *xfered_len)
{
if (len == 0)
- return 0;
+ return TARGET_XFER_EOF;
if (get_traceframe_number () != -1)
{
FORMAT and the remaining arguments, then gets the reply. Returns
whether the packet was a success, a failure, or unknown. */
+static enum packet_result remote_send_printf (const char *format, ...)
+ ATTRIBUTE_PRINTF (1, 2);
+
static enum packet_result
remote_send_printf (const char *format, ...)
{
stb = mem_fileopen ();
old_chain = make_cleanup_ui_file_delete (stb);
- fputstrn_unfiltered (buf, n, 0, stb);
+ fputstrn_unfiltered (buf, n, '\\', stb);
str = ui_file_xstrdup (stb, NULL);
do_cleanups (old_chain);
return str;
string notation. */
static void
-print_packet (char *buf)
+print_packet (const char *buf)
{
puts_filtered ("\"");
fputstr_filtered (buf, '"', gdb_stdout);
}
int
-putpkt (char *buf)
+putpkt (const char *buf)
{
return putpkt_binary (buf, strlen (buf));
}
to print the sent packet as a string. */
static int
-putpkt_binary (char *buf, int cnt)
+putpkt_binary (const char *buf, int cnt)
{
struct remote_state *rs = get_remote_state ();
int i;
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_can_async_p () && rs->waiting_for_stop_reply)
- error (_("Cannot execute this command while the target is running."));
+ if (!non_stop && 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"
+ "and then try again."));
+ }
/* We're sending out a new packet. Make sure we don't look at a
stale cached response. */
char **argv;
argv = gdb_buildargv (args);
- back_to = make_cleanup ((void (*) (void *)) freeargv, argv);
+ back_to = make_cleanup_freeargv (argv);
for (i = 0; argv[i] != NULL; i++)
{
if (strlen (argv[i]) * 2 + 1 + len >= get_remote_packet_size ())
if (packet_support (PACKET_Z0) != PACKET_DISABLE)
{
- CORE_ADDR addr = bp_tgt->placed_address;
+ CORE_ADDR addr = bp_tgt->reqstd_address;
struct remote_state *rs;
char *p, *endbuf;
int bpsize;
return -1;
}
+/* The to_stopped_by_sw_breakpoint method of target remote. */
+
+static int
+remote_stopped_by_sw_breakpoint (struct target_ops *ops)
+{
+ struct remote_state *rs = get_remote_state ();
+
+ return rs->stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT;
+}
+
+/* The to_supports_stopped_by_sw_breakpoint method of target
+ remote. */
+
+static int
+remote_supports_stopped_by_sw_breakpoint (struct target_ops *ops)
+{
+ struct remote_state *rs = get_remote_state ();
+
+ return (packet_support (PACKET_swbreak_feature) == PACKET_ENABLE);
+}
+
+/* The to_stopped_by_hw_breakpoint method of target remote. */
+
+static int
+remote_stopped_by_hw_breakpoint (struct target_ops *ops)
+{
+ struct remote_state *rs = get_remote_state ();
+
+ return rs->stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT;
+}
+
+/* The to_supports_stopped_by_hw_breakpoint method of target
+ remote. */
+
+static int
+remote_supports_stopped_by_hw_breakpoint (struct target_ops *ops)
+{
+ struct remote_state *rs = get_remote_state ();
+
+ return (packet_support (PACKET_hwbreak_feature) == PACKET_ENABLE);
+}
+
static int
remote_stopped_by_watchpoint (struct target_ops *ops)
{
struct remote_state *rs = get_remote_state ();
- return rs->remote_stopped_by_watchpoint_p;
+ return rs->stop_reason == TARGET_STOPPED_BY_WATCHPOINT;
}
static int
remote_insert_hw_breakpoint (struct target_ops *self, struct gdbarch *gdbarch,
struct bp_target_info *bp_tgt)
{
- CORE_ADDR addr;
+ CORE_ADDR addr = bp_tgt->reqstd_address;
struct remote_state *rs;
char *p, *endbuf;
char *message;
+ int bpsize;
/* The length field should be set to the size of a breakpoint
instruction, even though we aren't inserting one ourselves. */
- gdbarch_remote_breakpoint_from_pc
- (gdbarch, &bp_tgt->placed_address, &bp_tgt->placed_size);
+ gdbarch_remote_breakpoint_from_pc (gdbarch, &addr, &bpsize);
if (packet_support (PACKET_Z1) == PACKET_DISABLE)
return -1;
*(p++) = '1';
*(p++) = ',';
- addr = remote_address_masked (bp_tgt->placed_address);
+ addr = remote_address_masked (addr);
p += hexnumstr (p, (ULONGEST) addr);
- xsnprintf (p, endbuf - p, ",%x", bp_tgt->placed_size);
+ xsnprintf (p, endbuf - p, ",%x", bpsize);
if (remote_supports_cond_breakpoints (self))
remote_add_target_side_condition (gdbarch, bp_tgt, p, endbuf);
case PACKET_UNKNOWN:
return -1;
case PACKET_OK:
+ bp_tgt->placed_address = addr;
+ bp_tgt->placed_size = bpsize;
return 0;
}
internal_error (__FILE__, __LINE__,
unsigned long host_crc, target_crc;
char *tmp;
- /* Make sure the remote is pointing at the right process. */
- set_general_process ();
+ /* It doesn't make sense to use qCRC if the remote target is
+ connected but not running. */
+ if (target_has_execution && packet_support (PACKET_qCRC) != PACKET_DISABLE)
+ {
+ enum packet_result result;
- /* FIXME: assumes lma can fit into long. */
- xsnprintf (rs->buf, get_remote_packet_size (), "qCRC:%lx,%lx",
- (long) lma, (long) size);
- putpkt (rs->buf);
+ /* Make sure the remote is pointing at the right process. */
+ set_general_process ();
- /* Be clever; compute the host_crc before waiting for target
- reply. */
- host_crc = xcrc32 (data, size, 0xffffffff);
+ /* FIXME: assumes lma can fit into long. */
+ xsnprintf (rs->buf, get_remote_packet_size (), "qCRC:%lx,%lx",
+ (long) lma, (long) size);
+ putpkt (rs->buf);
- getpkt (&rs->buf, &rs->buf_size, 0);
- if (rs->buf[0] == 'E')
- return -1;
+ /* Be clever; compute the host_crc before waiting for target
+ reply. */
+ host_crc = xcrc32 (data, size, 0xffffffff);
- if (rs->buf[0] != 'C')
- error (_("remote target does not support this operation"));
+ getpkt (&rs->buf, &rs->buf_size, 0);
- for (target_crc = 0, tmp = &rs->buf[1]; *tmp; tmp++)
- target_crc = target_crc * 16 + fromhex (*tmp);
+ result = packet_ok (rs->buf,
+ &remote_protocol_packets[PACKET_qCRC]);
+ if (result == PACKET_ERROR)
+ return -1;
+ else if (result == PACKET_OK)
+ {
+ for (target_crc = 0, tmp = &rs->buf[1]; *tmp; tmp++)
+ target_crc = target_crc * 16 + fromhex (*tmp);
+
+ return (host_crc == target_crc);
+ }
+ }
- return (host_crc == target_crc);
+ return simple_verify_memory (ops, data, lma, size);
}
/* compare-sections command
int matched = 0;
int mismatched = 0;
int res;
+ int read_only = 0;
if (!exec_bfd)
error (_("command cannot be used without an exec file"));
/* Make sure the remote is pointing at the right process. */
set_general_process ();
+ if (args != NULL && strcmp (args, "-r") == 0)
+ {
+ read_only = 1;
+ args = NULL;
+ }
+
for (s = exec_bfd->sections; s; s = s->next)
{
if (!(s->flags & SEC_LOAD))
continue; /* Skip non-loadable section. */
+ if (read_only && (s->flags & SEC_READONLY) == 0)
+ continue; /* Skip writeable sections */
+
size = bfd_get_section_size (s);
if (size == 0)
continue; /* Skip zero-length section. */
do_cleanups (old_chain);
}
if (mismatched > 0)
- warning (_("One or more sections of the remote executable does not match\n\
+ warning (_("One or more sections of the target image does not match\n\
the loaded file\n"));
if (args && !matched)
printf_filtered (_("No loaded section named '%s'.\n"), args);
xfered_len,
&remote_protocol_packets[PACKET_qXfer_btrace]);
+ case TARGET_OBJECT_BTRACE_CONF:
+ return remote_read_qxfer (ops, "btrace-conf", annex, readbuf, offset,
+ len, xfered_len,
+ &remote_protocol_packets[PACKET_qXfer_btrace_conf]);
+
default:
return TARGET_XFER_E_IO;
}
- /* Note: a zero OFFSET and LEN can be used to query the minimum
- buffer size. */
- if (offset == 0 && len == 0)
- return (get_remote_packet_size ());
/* Minimum outbuf size is get_remote_packet_size (). If LEN is not
large enough let the caller deal with it. */
if (len < get_remote_packet_size ())
}
static void
-remote_rcmd (struct target_ops *self, char *command,
+remote_rcmd (struct target_ops *self, const char *command,
struct ui_file *outbuf)
{
struct remote_state *rs = get_remote_state ();
error (_("\"monitor\" command ``%s'' is too long."), command);
/* Encode the actual command. */
- bin2hex ((gdb_byte *) command, p, strlen (command));
+ bin2hex ((const gdb_byte *) command, p, strlen (command));
if (putpkt (rs->buf) < 0)
error (_("Communication problem with target."));
int
remote_filename_p (const char *filename)
{
- return strncmp (filename,
- REMOTE_SYSROOT_PREFIX,
- sizeof (REMOTE_SYSROOT_PREFIX) - 1) == 0;
+ return startswith (filename, REMOTE_SYSROOT_PREFIX);
}
bfd *
static void
remote_command (char *args, int from_tty)
{
- help_list (remote_cmdlist, "remote ", -1, gdb_stdout);
+ help_list (remote_cmdlist, "remote ", all_commands, gdb_stdout);
}
static int
{
struct thread_info *info = find_thread_ptid (ptid);
- if (info && info->private)
- return info->private->core;
+ if (info && info->priv)
+ return info->priv->core;
return -1;
}
{
/* The ptid of the traced thread. */
ptid_t ptid;
+
+ /* The obtained branch trace configuration. */
+ struct btrace_config conf;
};
+/* Reset our idea of our target's btrace configuration. */
+
+static void
+remote_btrace_reset (void)
+{
+ struct remote_state *rs = get_remote_state ();
+
+ memset (&rs->btrace_config, 0, sizeof (rs->btrace_config));
+}
+
/* Check whether the target supports branch tracing. */
static int
-remote_supports_btrace (struct target_ops *self)
+remote_supports_btrace (struct target_ops *self, enum btrace_format format)
{
if (packet_support (PACKET_Qbtrace_off) != PACKET_ENABLE)
return 0;
- if (packet_support (PACKET_Qbtrace_bts) != PACKET_ENABLE)
- return 0;
if (packet_support (PACKET_qXfer_btrace) != PACKET_ENABLE)
return 0;
- return 1;
+ switch (format)
+ {
+ case BTRACE_FORMAT_NONE:
+ return 0;
+
+ case BTRACE_FORMAT_BTS:
+ return (packet_support (PACKET_Qbtrace_bts) == PACKET_ENABLE);
+ }
+
+ internal_error (__FILE__, __LINE__, _("Unknown branch trace format"));
+}
+
+/* Synchronize the configuration with the target. */
+
+static void
+btrace_sync_conf (const struct btrace_config *conf)
+{
+ struct packet_config *packet;
+ struct remote_state *rs;
+ char *buf, *pos, *endbuf;
+
+ rs = get_remote_state ();
+ buf = rs->buf;
+ endbuf = buf + get_remote_packet_size ();
+
+ packet = &remote_protocol_packets[PACKET_Qbtrace_conf_bts_size];
+ if (packet_config_support (packet) == PACKET_ENABLE
+ && conf->bts.size != rs->btrace_config.bts.size)
+ {
+ pos = buf;
+ pos += xsnprintf (pos, endbuf - pos, "%s=0x%x", packet->name,
+ conf->bts.size);
+
+ putpkt (buf);
+ getpkt (&buf, &rs->buf_size, 0);
+
+ if (packet_ok (buf, packet) == PACKET_ERROR)
+ {
+ if (buf[0] == 'E' && buf[1] == '.')
+ error (_("Failed to configure the BTS buffer size: %s"), buf + 2);
+ else
+ error (_("Failed to configure the BTS buffer size."));
+ }
+
+ rs->btrace_config.bts.size = conf->bts.size;
+ }
+}
+
+/* Read the current thread's btrace configuration from the target and
+ store it into CONF. */
+
+static void
+btrace_read_config (struct btrace_config *conf)
+{
+ char *xml;
+
+ xml = target_read_stralloc (¤t_target,
+ TARGET_OBJECT_BTRACE_CONF, "");
+ if (xml != NULL)
+ {
+ struct cleanup *cleanup;
+
+ cleanup = make_cleanup (xfree, xml);
+ parse_xml_btrace_conf (conf, xml);
+ do_cleanups (cleanup);
+ }
}
/* Enable branch tracing. */
static struct btrace_target_info *
-remote_enable_btrace (struct target_ops *self, ptid_t ptid)
+remote_enable_btrace (struct target_ops *self, ptid_t ptid,
+ const struct btrace_config *conf)
{
struct btrace_target_info *tinfo = NULL;
struct packet_config *packet = &remote_protocol_packets[PACKET_Qbtrace_bts];
struct remote_state *rs = get_remote_state ();
char *buf = rs->buf;
char *endbuf = rs->buf + get_remote_packet_size ();
+ volatile struct gdb_exception err;
if (packet_config_support (packet) != PACKET_ENABLE)
error (_("Target does not support branch tracing."));
+ btrace_sync_conf (conf);
+
set_general_thread (ptid);
buf += xsnprintf (buf, endbuf - buf, "%s", packet->name);
tinfo = xzalloc (sizeof (*tinfo));
tinfo->ptid = ptid;
+ /* If we fail to read the configuration, we lose some information, but the
+ tracing itself is not impacted. */
+ TRY_CATCH (err, RETURN_MASK_ERROR)
+ btrace_read_config (&tinfo->conf);
+
+ if (err.message != NULL)
+ warning ("%s", err.message);
+
return tinfo;
}
static enum btrace_error
remote_read_btrace (struct target_ops *self,
- VEC (btrace_block_s) **btrace,
+ struct btrace_data *btrace,
struct btrace_target_info *tinfo,
enum btrace_read_type type)
{
return BTRACE_ERR_UNKNOWN;
cleanup = make_cleanup (xfree, xml);
- *btrace = parse_xml_btrace (xml);
+ parse_xml_btrace (btrace, xml);
do_cleanups (cleanup);
return BTRACE_ERR_NONE;
}
+static const struct btrace_config *
+remote_btrace_conf (struct target_ops *self,
+ const struct btrace_target_info *tinfo)
+{
+ return &tinfo->conf;
+}
+
static int
remote_augmented_libraries_svr4_read (struct target_ops *self)
{
/* Implementation of to_load. */
static void
-remote_load (struct target_ops *self, char *name, int from_tty)
+remote_load (struct target_ops *self, const char *name, int from_tty)
{
generic_load (name, from_tty);
}
remote_ops.to_files_info = remote_files_info;
remote_ops.to_insert_breakpoint = remote_insert_breakpoint;
remote_ops.to_remove_breakpoint = remote_remove_breakpoint;
+ remote_ops.to_stopped_by_sw_breakpoint = remote_stopped_by_sw_breakpoint;
+ remote_ops.to_supports_stopped_by_sw_breakpoint = remote_supports_stopped_by_sw_breakpoint;
+ remote_ops.to_stopped_by_hw_breakpoint = remote_stopped_by_hw_breakpoint;
+ remote_ops.to_supports_stopped_by_hw_breakpoint = remote_supports_stopped_by_hw_breakpoint;
remote_ops.to_stopped_by_watchpoint = remote_stopped_by_watchpoint;
remote_ops.to_stopped_data_address = remote_stopped_data_address;
remote_ops.to_watchpoint_addr_within_range =
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_find_new_threads = remote_threads_info;
+ 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_disable_btrace = remote_disable_btrace;
remote_ops.to_teardown_btrace = remote_teardown_btrace;
remote_ops.to_read_btrace = remote_read_btrace;
+ remote_ops.to_btrace_conf = remote_btrace_conf;
remote_ops.to_augmented_libraries_svr4_read =
remote_augmented_libraries_svr4_read;
}
extended_remote_ops.to_mourn_inferior = extended_remote_mourn;
extended_remote_ops.to_detach = extended_remote_detach;
extended_remote_ops.to_attach = extended_remote_attach;
+ extended_remote_ops.to_post_attach = extended_remote_post_attach;
extended_remote_ops.to_kill = extended_remote_kill;
extended_remote_ops.to_supports_disable_randomization
= extended_remote_supports_disable_randomization;
serial_async (rs->remote_desc, remote_async_serial_handler, rs);
rs->async_client_callback = callback;
rs->async_client_context = context;
+
+ /* If there are pending events in the stop reply queue tell the
+ event loop to process them. */
+ if (!QUEUE_is_empty (stop_reply_p, stop_reply_queue))
+ mark_async_event_handler (remote_async_inferior_event_token);
}
else
- serial_async (rs->remote_desc, NULL, NULL);
+ {
+ serial_async (rs->remote_desc, NULL, NULL);
+ clear_async_event_handler (remote_async_inferior_event_token);
+ }
}
static void
set_remote_cmd (char *args, int from_tty)
{
- help_list (remote_set_cmdlist, "set remote ", -1, gdb_stdout);
+ help_list (remote_set_cmdlist, "set remote ", all_commands, gdb_stdout);
}
static void
add_cmd ("compare-sections", class_obscure, compare_sections_command, _("\
Compare section data on target to the exec file.\n\
-Argument is a single section name (default: all loaded sections)."),
+Argument is a single section name (default: all loaded sections).\n\
+To compare only read-only loaded sections, specify the -r option."),
&cmdlist);
add_cmd ("packet", class_maintenance, packet_command, _("\
NULL, /* FIXME: i18n: */
&setlist, &showlist);
+ init_all_packet_configs ();
+
add_packet_config_cmd (&remote_protocol_packets[PACKET_X],
"X", "binary-download", 1);
add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_btrace],
"qXfer:btrace", "read-btrace", 0);
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_btrace_conf],
+ "qXfer:btrace-conf", "read-btrace-conf", 0);
+
+ 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_swbreak_feature],
+ "swbreak-feature", "swbreak-feature", 0);
+
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_hwbreak_feature],
+ "hwbreak-feature", "hwbreak-feature", 0);
+
+ /* Assert that we've registered commands for all packet configs. */
+ {
+ int i;
+
+ for (i = 0; i < PACKET_MAX; i++)
+ {
+ /* Ideally all configs would have a command associated. Some
+ still don't though. */
+ int excepted;
+
+ switch (i)
+ {
+ case PACKET_QNonStop:
+ case PACKET_multiprocess_feature:
+ case PACKET_EnableDisableTracepoints_feature:
+ case PACKET_tracenz_feature:
+ case PACKET_DisconnectedTracing_feature:
+ case PACKET_augmented_libraries_svr4_read_feature:
+ case PACKET_qCRC:
+ /* Additions to this list need to be well justified:
+ pre-existing packets are OK; new packets are not. */
+ excepted = 1;
+ break;
+ default:
+ excepted = 0;
+ break;
+ }
+
+ /* This catches both forgetting to add a config command, and
+ forgetting to remove a packet from the exception list. */
+ gdb_assert (excepted == (remote_protocol_packets[i].name == NULL));
+ }
+ }
+
/* 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