#include "cli/cli-setshow.h"
#include "target-descriptions.h"
#include "gdb_bfd.h"
+#include "filestuff.h"
#include <ctype.h>
#include <sys/time.h>
enum { REMOTE_ALIGN_WRITES = 16 };
/* Prototypes for local functions. */
-static void cleanup_sigint_signal_handler (void *dummy);
-static void initialize_sigint_signal_handler (void);
+static void async_cleanup_sigint_signal_handler (void *dummy);
static int getpkt_sane (char **buf, long *sizeof_buf, int forever);
static int getpkt_or_notif_sane (char **buf, long *sizeof_buf,
int forever, int *is_notif);
-static void handle_remote_sigint (int);
-static void handle_remote_sigint_twice (int);
-static void async_remote_interrupt (gdb_client_data);
-void async_remote_interrupt_twice (gdb_client_data);
+static void async_handle_remote_sigint (int);
+static void async_handle_remote_sigint_twice (int);
static void remote_files_info (struct target_ops *ignore);
static void remote_detach (struct target_ops *ops, char *args, int from_tty);
-static void remote_interrupt (int signo);
-
-static void remote_interrupt_twice (int signo);
+static void sync_remote_interrupt_twice (int signo);
static void interrupt_query (void);
static void remote_query_supported (void);
-static void remote_check_symbols (struct objfile *objfile);
+static void remote_check_symbols (void);
void _initialize_remote (void);
static struct cmd_list_element *remote_set_cmdlist;
static struct cmd_list_element *remote_show_cmdlist;
+/* Stub vCont actions support.
+
+ Each field is a boolean flag indicating whether the stub reports
+ support for the corresponding action. */
+
+struct vCont_action_support
+{
+ /* vCont;t */
+ int t;
+
+ /* vCont;r */
+ int r;
+};
+
+/* Controls whether GDB is willing to use range stepping. */
+
+static int use_range_stepping = 1;
+
/* Description of the remote protocol state for the currently
connected target. This is per-target state, and independent of the
selected architecture. */
/* True if the stub reports support for non-stop mode. */
int non_stop_aware;
- /* True if the stub reports support for vCont;t. */
- int support_vCont_t;
+ /* The status of the stub support for the various vCont actions. */
+ struct vCont_action_support supports_vCont;
/* True if the stub reports support for conditional tracepoints. */
int cond_tracepoints;
/* True if the stub can collect strings using tracenz bytecode. */
int string_tracing;
+ /* True if the stub supports qXfer:libraries-svr4:read with a
+ non-empty annex. */
+ int augmented_libraries_svr4_read;
+
/* Nonzero if the user has pressed Ctrl-C, but the target hasn't
responded to that. */
int ctrlc_pending_p;
static int use_threadextra_query;
/* Tokens for use by the asynchronous signal handlers for SIGINT. */
-static struct async_signal_handler *sigint_remote_twice_token;
-static struct async_signal_handler *sigint_remote_token;
+static struct async_signal_handler *async_sigint_remote_twice_token;
+static struct async_signal_handler *async_sigint_remote_token;
\f
/* Asynchronous signal handle registered as event loop source for
delete_async_event_handler (&remote_async_inferior_event_token);
remote_notif_unregister_async_event_handler ();
+
+ trace_reset_local_state ();
}
/* Query the remote side for the text, data and bss offsets. */
error (_("Remote refused setting all-stop mode with: %s"), rs->buf);
}
+ /* Upload TSVs regardless of whether the target is running or not. The
+ remote stub, such as GDBserver, may have some predefined or builtin
+ TSVs, even if the target is not running. */
+ if (remote_get_trace_status (current_trace_status ()) != -1)
+ {
+ struct uploaded_tsv *uploaded_tsvs = NULL;
+
+ remote_upload_trace_state_variables (&uploaded_tsvs);
+ merge_uploaded_trace_state_variables (&uploaded_tsvs);
+ }
+
/* Check whether the target is running now. */
putpkt ("?");
getpkt (&rs->buf, &rs->buf_size, 0);
if (target_has_execution)
{
if (exec_bfd) /* No use without an exec file. */
- remote_check_symbols (symfile_objfile);
+ remote_check_symbols ();
}
/* Possibly the target has been engaged in a trace run started
if (remote_get_trace_status (current_trace_status ()) != -1)
{
struct uploaded_tp *uploaded_tps = NULL;
- struct uploaded_tsv *uploaded_tsvs = NULL;
if (current_trace_status ()->running)
printf_filtered (_("Trace is already running on the target.\n"));
- /* Get trace state variables first, they may be checked when
- parsing uploaded commands. */
-
- remote_upload_trace_state_variables (&uploaded_tsvs);
-
- merge_uploaded_trace_state_variables (&uploaded_tsvs);
-
remote_upload_tracepoints (&uploaded_tps);
merge_uploaded_tracepoints (&uploaded_tps);
/* Symbol look-up. */
static void
-remote_check_symbols (struct objfile *objfile)
+remote_check_symbols (void)
{
struct remote_state *rs = get_remote_state ();
char *msg, *reply, *tmp;
rs->string_tracing = (support == PACKET_ENABLE);
}
-static struct protocol_feature remote_protocol_features[] = {
+static void
+remote_augmented_libraries_svr4_read_feature
+ (const struct protocol_feature *feature,
+ enum packet_support support, const char *value)
+{
+ struct remote_state *rs = get_remote_state ();
+
+ rs->augmented_libraries_svr4_read = (support == PACKET_ENABLE);
+}
+
+static const struct protocol_feature remote_protocol_features[] = {
{ "PacketSize", PACKET_DISABLE, remote_packet_size, -1 },
{ "qXfer:auxv:read", PACKET_DISABLE, remote_supported_packet,
PACKET_qXfer_auxv },
PACKET_qXfer_libraries },
{ "qXfer:libraries-svr4:read", PACKET_DISABLE, remote_supported_packet,
PACKET_qXfer_libraries_svr4 },
+ { "augmented-libraries-svr4-read", PACKET_DISABLE,
+ remote_augmented_libraries_svr4_read_feature, -1 },
{ "qXfer:memory-map:read", PACKET_DISABLE, remote_supported_packet,
PACKET_qXfer_memory_map },
{ "qXfer:spu:read", PACKET_DISABLE, remote_supported_packet,
support_S = 0;
support_c = 0;
support_C = 0;
- rs->support_vCont_t = 0;
+ rs->supports_vCont.t = 0;
+ rs->supports_vCont.r = 0;
while (p && *p == ';')
{
p++;
else if (*p == 'C' && (*(p + 1) == ';' || *(p + 1) == 0))
support_C = 1;
else if (*p == 't' && (*(p + 1) == ';' || *(p + 1) == 0))
- rs->support_vCont_t = 1;
+ rs->supports_vCont.t = 1;
+ else if (*p == 'r' && (*(p + 1) == ';' || *(p + 1) == 0))
+ rs->supports_vCont.r = 1;
p = strchr (p, ';');
}
if (step && siggnal != GDB_SIGNAL_0)
p += xsnprintf (p, endp - p, ";S%02x", siggnal);
+ else if (step
+ /* GDB is willing to range step. */
+ && use_range_stepping
+ /* Target supports range stepping. */
+ && rs->supports_vCont.r
+ /* We don't currently support range stepping multiple
+ threads with a wildcard (though the protocol allows it,
+ so stubs shouldn't make an active effort to forbid
+ it). */
+ && !(remote_multi_process_p (rs) && ptid_is_pid (ptid)))
+ {
+ struct thread_info *tp;
+
+ if (ptid_equal (ptid, minus_one_ptid))
+ {
+ /* If we don't know about the target thread's tid, then
+ we're resuming magic_null_ptid (see caller). */
+ tp = find_thread_ptid (magic_null_ptid);
+ }
+ else
+ tp = find_thread_ptid (ptid);
+ gdb_assert (tp != NULL);
+
+ if (tp->control.may_range_step)
+ {
+ int addr_size = gdbarch_addr_bit (target_gdbarch ()) / 8;
+
+ p += xsnprintf (p, endp - p, ";r%s,%s",
+ phex_nz (tp->control.step_range_start,
+ addr_size),
+ phex_nz (tp->control.step_range_end,
+ addr_size));
+ }
+ else
+ p += xsnprintf (p, endp - p, ";s");
+ }
else if (step)
p += xsnprintf (p, endp - p, ";s");
else if (siggnal != GDB_SIGNAL_0)
/* Set up the signal handler for SIGINT, while the target is
executing, ovewriting the 'regular' SIGINT signal handler. */
static void
-initialize_sigint_signal_handler (void)
+async_initialize_sigint_signal_handler (void)
{
- signal (SIGINT, handle_remote_sigint);
+ signal (SIGINT, async_handle_remote_sigint);
}
/* Signal handler for SIGINT, while the target is executing. */
static void
-handle_remote_sigint (int sig)
+async_handle_remote_sigint (int sig)
{
- signal (sig, handle_remote_sigint_twice);
- mark_async_signal_handler (sigint_remote_token);
+ signal (sig, async_handle_remote_sigint_twice);
+ mark_async_signal_handler (async_sigint_remote_token);
}
/* Signal handler for SIGINT, installed after SIGINT has already been
sent once. It will take effect the second time that the user sends
a ^C. */
static void
-handle_remote_sigint_twice (int sig)
+async_handle_remote_sigint_twice (int sig)
{
- signal (sig, handle_remote_sigint);
- mark_async_signal_handler (sigint_remote_twice_token);
+ signal (sig, async_handle_remote_sigint);
+ mark_async_signal_handler (async_sigint_remote_twice_token);
}
/* Perform the real interruption of the target execution, in response
/* Perform interrupt, if the first attempt did not succeed. Just give
up on the target alltogether. */
-void
+static void
async_remote_interrupt_twice (gdb_client_data arg)
{
if (remote_debug)
/* Reinstall the usual SIGINT handlers, after the target has
stopped. */
static void
-cleanup_sigint_signal_handler (void *dummy)
+async_cleanup_sigint_signal_handler (void *dummy)
{
signal (SIGINT, handle_sigint);
}
response from the target (it didn't stop when the user requested it),
we ask the user if he'd like to detach from the target. */
static void
-remote_interrupt (int signo)
+sync_remote_interrupt (int signo)
{
/* If this doesn't work, try more severe steps. */
- signal (signo, remote_interrupt_twice);
+ signal (signo, sync_remote_interrupt_twice);
- gdb_call_async_signal_handler (sigint_remote_token, 1);
+ gdb_call_async_signal_handler (async_sigint_remote_token, 1);
}
/* The user typed ^C twice. */
static void
-remote_interrupt_twice (int signo)
+sync_remote_interrupt_twice (int signo)
{
signal (signo, ofunc);
- gdb_call_async_signal_handler (sigint_remote_twice_token, 1);
- signal (signo, remote_interrupt);
+ gdb_call_async_signal_handler (async_sigint_remote_twice_token, 1);
+ signal (signo, sync_remote_interrupt);
}
/* Non-stop version of target_stop. Uses `vCont;t' to stop a remote
if (remote_protocol_packets[PACKET_vCont].support == PACKET_SUPPORT_UNKNOWN)
remote_vcont_probe (rs);
- if (!rs->support_vCont_t)
+ if (!rs->supports_vCont.t)
error (_("Remote server does not support stopping threads"));
if (ptid_equal (ptid, minus_one_ptid)
if (target_can_async_p ())
{
signal (SIGINT, handle_sigint);
- deprecated_throw_reason (RETURN_QUIT);
+ quit ();
}
else
{
Give up (and stop debugging it)? ")))
{
remote_unpush_target ();
- deprecated_throw_reason (RETURN_QUIT);
+ quit ();
}
}
return;
delete_file_handler (input_fd);
remote_async_terminal_ours_p = 0;
- initialize_sigint_signal_handler ();
+ async_initialize_sigint_signal_handler ();
/* NOTE: At this point we could also register our selves as the
recipient of all input. Any characters typed could then be
passed on down to the target. */
/* See FIXME in remote_terminal_inferior. */
if (remote_async_terminal_ours_p)
return;
- cleanup_sigint_signal_handler (NULL);
+ async_cleanup_sigint_signal_handler (NULL);
add_file_handler (input_fd, stdin_event_handler, 0);
remote_async_terminal_ours_p = 1;
}
if (!target_is_async_p ())
{
- ofunc = signal (SIGINT, remote_interrupt);
+ ofunc = signal (SIGINT, sync_remote_interrupt);
/* If the user hit C-c before this packet, or between packets,
pretend that it was hit right here. */
if (check_quit_flag ())
{
clear_quit_flag ();
- remote_interrupt (SIGINT);
+ sync_remote_interrupt (SIGINT);
}
}
ret = getpkt_or_notif_sane (&rs->buf, &rs->buf_size,
wait_forever_enabled_p, &is_notif);
+ if (!target_is_async_p ())
+ signal (SIGINT, ofunc);
+
/* GDB gets a notification. Return to core as this event is
not interesting. */
if (ret != -1 && is_notif)
return minus_one_ptid;
-
- if (!target_is_async_p ())
- signal (SIGINT, ofunc);
}
buf = rs->buf;
int bpsize;
struct condition_list *cond = NULL;
+ /* Make sure the remote is pointing at the right process, if
+ necessary. */
+ if (!gdbarch_has_global_breakpoints (target_gdbarch ()))
+ set_general_process ();
+
gdbarch_remote_breakpoint_from_pc (gdbarch, &addr, &bpsize);
rs = get_remote_state ();
char *p = rs->buf;
char *endbuf = rs->buf + get_remote_packet_size ();
+ /* Make sure the remote is pointing at the right process, if
+ necessary. */
+ if (!gdbarch_has_global_breakpoints (target_gdbarch ()))
+ set_general_process ();
+
*(p++) = 'z';
*(p++) = '0';
*(p++) = ',';
if (remote_protocol_packets[PACKET_Z0 + packet].support == PACKET_DISABLE)
return 1;
+ /* Make sure the remote is pointing at the right process, if
+ necessary. */
+ if (!gdbarch_has_global_breakpoints (target_gdbarch ()))
+ set_general_process ();
+
xsnprintf (rs->buf, endbuf - rs->buf, "Z%x,", packet);
p = strchr (rs->buf, '\0');
addr = remote_address_masked (addr);
if (remote_protocol_packets[PACKET_Z0 + packet].support == PACKET_DISABLE)
return -1;
+ /* Make sure the remote is pointing at the right process, if
+ necessary. */
+ if (!gdbarch_has_global_breakpoints (target_gdbarch ()))
+ set_general_process ();
+
xsnprintf (rs->buf, endbuf - rs->buf, "z%x,", packet);
p = strchr (rs->buf, '\0');
addr = remote_address_masked (addr);
if (remote_protocol_packets[PACKET_Z1].support == PACKET_DISABLE)
return -1;
+ /* Make sure the remote is pointing at the right process, if
+ necessary. */
+ if (!gdbarch_has_global_breakpoints (target_gdbarch ()))
+ set_general_process ();
+
rs = get_remote_state ();
p = rs->buf;
endbuf = rs->buf + get_remote_packet_size ();
if (remote_protocol_packets[PACKET_Z1].support == PACKET_DISABLE)
return -1;
+ /* Make sure the remote is pointing at the right process, if
+ necessary. */
+ if (!gdbarch_has_global_breakpoints (target_gdbarch ()))
+ set_general_process ();
+
*(p++) = 'z';
*(p++) = '1';
*(p++) = ',';
_("remote_remove_hw_breakpoint: reached end of function"));
}
-/* Table used by the crc32 function to calcuate the checksum. */
-
-static unsigned long crc32_table[256] =
-{0, 0};
-
-static unsigned long
-crc32 (const unsigned char *buf, int len, unsigned int crc)
-{
- if (!crc32_table[1])
- {
- /* Initialize the CRC table and the decoding table. */
- int i, j;
- unsigned int c;
-
- for (i = 0; i < 256; i++)
- {
- for (c = i << 24, j = 8; j > 0; --j)
- c = c & 0x80000000 ? (c << 1) ^ 0x04c11db7 : (c << 1);
- crc32_table[i] = c;
- }
- }
-
- while (len--)
- {
- crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ *buf) & 255];
- buf++;
- }
- return crc;
-}
-
/* Verify memory using the "qCRC:" request. */
static int
unsigned long host_crc, target_crc;
char *tmp;
+ /* Make sure the remote is pointing at the right process. */
+ set_general_process ();
+
/* FIXME: assumes lma can fit into long. */
xsnprintf (rs->buf, get_remote_packet_size (), "qCRC:%lx,%lx",
(long) lma, (long) size);
/* Be clever; compute the host_crc before waiting for target
reply. */
- host_crc = crc32 (data, size, 0xffffffff);
+ host_crc = xcrc32 (data, size, 0xffffffff);
getpkt (&rs->buf, &rs->buf_size, 0);
if (rs->buf[0] == 'E')
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 ();
+
for (s = exec_bfd->sections; s; s = s->next)
{
if (!(s->flags & SEC_LOAD))
pattern, pattern_len, found_addrp);
}
+ /* Make sure the remote is pointing at the right process. */
+ set_general_process ();
+
/* Insert header. */
i = snprintf (rs->buf, max_size,
"qSearch:memory:%s;%s;",
if (!remote_desc)
error (_("command can only be used with remote target"));
- file = fopen (local_file, "rb");
+ file = gdb_fopen_cloexec (local_file, "rb");
if (file == NULL)
perror_with_name (local_file);
back_to = make_cleanup_fclose (file);
if (fd == -1)
remote_hostio_error (remote_errno);
- file = fopen (local_file, "wb");
+ file = gdb_fopen_cloexec (local_file, "wb");
if (file == NULL)
perror_with_name (local_file);
back_to = make_cleanup_fclose (file);
struct breakpoint *b = loc->owner;
struct tracepoint *t = (struct tracepoint *) b;
- encode_actions (loc->owner, loc, &tdp_actions, &stepping_actions);
+ encode_actions_rsp (loc, &tdp_actions, &stepping_actions);
old_chain = make_cleanup (free_actions_list_cleanup_wrapper,
tdp_actions);
(void) make_cleanup (free_actions_list_cleanup_wrapper,
return; /* No information to give. */
strcpy (target_buf, "QTro");
+ offset = strlen (target_buf);
for (s = exec_bfd->sections; s; s = s->next)
{
char tmp1[40], tmp2[40];
}
static int
-remote_set_trace_notes (char *user, char *notes, char *stop_notes)
+remote_set_trace_notes (const char *user, const char *notes,
+ const char *stop_notes)
{
struct remote_state *rs = get_remote_state ();
char *reply;
return btrace;
}
+static int
+remote_augmented_libraries_svr4_read (void)
+{
+ struct remote_state *rs = get_remote_state ();
+
+ return rs->augmented_libraries_svr4_read;
+}
+
static void
init_remote_ops (void)
{
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_augmented_libraries_svr4_read =
+ remote_augmented_libraries_svr4_read;
}
/* Set up the extended remote vector by making a copy of the standard
remote_new_objfile (struct objfile *objfile)
{
if (remote_desc != 0) /* Have a remote connection. */
- remote_check_symbols (objfile);
+ remote_check_symbols ();
}
/* Pull all the tracepoints defined on the target and create local
return 0;
}
+/* The "set/show range-stepping" show hook. */
+
+static void
+show_range_stepping (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c,
+ const char *value)
+{
+ fprintf_filtered (file,
+ _("Debugger's willingness to use range stepping "
+ "is %s.\n"), value);
+}
+
+/* The "set/show range-stepping" set hook. */
+
+static void
+set_range_stepping (char *ignore_args, int from_tty,
+ struct cmd_list_element *c)
+{
+ /* Whene enabling, check whether range stepping is actually
+ supported by the target, and warn if not. */
+ if (use_range_stepping)
+ {
+ if (remote_desc != NULL)
+ {
+ struct remote_state *rs = get_remote_state ();
+
+ if (remote_protocol_packets[PACKET_vCont].support == PACKET_SUPPORT_UNKNOWN)
+ remote_vcont_probe (rs);
+
+ if (remote_protocol_packets[PACKET_vCont].support == PACKET_ENABLE
+ && rs->supports_vCont.r)
+ return;
+ }
+
+ warning (_("Range stepping is not supported by the current target"));
+ }
+}
+
void
_initialize_remote (void)
{
observer_attach_inferior_exit (discard_pending_stop_replies);
/* Set up signal handlers. */
- sigint_remote_token =
+ async_sigint_remote_token =
create_async_signal_handler (async_remote_interrupt, NULL);
- sigint_remote_twice_token =
+ async_sigint_remote_twice_token =
create_async_signal_handler (async_remote_interrupt_twice, NULL);
#if 0
add_packet_config_cmd
(&remote_protocol_packets[PACKET_qXfer_traceframe_info],
- "qXfer:trace-frame-info:read", "traceframe-info", 0);
+ "qXfer:traceframe-info:read", "traceframe-info", 0);
add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_uib],
"qXfer:uib:read", "unwind-info-block", 0);
Show the remote pathname for \"run\""), NULL, NULL, NULL,
&remote_set_cmdlist, &remote_show_cmdlist);
+ add_setshow_boolean_cmd ("range-stepping", class_run,
+ &use_range_stepping, _("\
+Enable or disable range stepping."), _("\
+Show whether target-assisted range stepping is enabled."), _("\
+If on, and the target supports it, when stepping a source line, GDB\n\
+tells the target to step the corresponding range of addresses itself instead\n\
+of issuing multiple single-steps. This speeds up source level\n\
+stepping. If off, GDB always issues single-steps, even if range\n\
+stepping is supported by the target. The default is on."),
+ set_range_stepping,
+ show_range_stepping,
+ &setlist,
+ &showlist);
+
/* Eventually initialize fileio. See fileio.c */
initialize_remote_fileio (remote_set_cmdlist, remote_show_cmdlist);