#include "cli/cli-setshow.h"
#include "target-descriptions.h"
#include "gdb_bfd.h"
+#include "filestuff.h"
#include <ctype.h>
#include <sys/time.h>
#include "ax.h"
#include "ax-gdb.h"
#include "agent.h"
+#include "btrace.h"
/* Temp hacks for tracepoint encoding migration. */
static char *target_buf;
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_open_1 (char *, int, struct target_ops *, int extended_p);
-static void remote_close (int quitting);
+static void remote_close (void);
static void remote_mourn (struct target_ops *ops);
static int readchar (int timeout);
+static void remote_serial_write (const char *str, int len);
+
static void remote_kill (struct target_ops *ops);
static int tohex (int nib);
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 int fromhex (int a);
-extern int hex2bin (const char *hex, gdb_byte *bin, int count);
-
-extern int bin2hex (const gdb_byte *bin, char *hex, int count);
-
static int putpkt_binary (char *buf, int cnt);
static void check_binary_download (CORE_ADDR addr);
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;
else
error (_("remote.c: error in outgoing packet at field #%ld."),
strtol (buf, NULL, 16));
- case '2':
- error (_("trace API error 0x%s."), ++buf);
default:
error (_("Target returns error code '%s'."), buf);
}
PACKET_qGetTIBAddr,
PACKET_qGetTLSAddr,
PACKET_qSupported,
+ PACKET_qTStatus,
PACKET_QPassSignals,
PACKET_QProgramSignals,
PACKET_qSearch_memory,
PACKET_qXfer_fdpic,
PACKET_QDisableRandomization,
PACKET_QAgent,
+ PACKET_QTBuffer_size,
+ PACKET_Qbtrace_off,
+ PACKET_Qbtrace_bts,
+ PACKET_qXfer_btrace,
PACKET_MAX
};
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
/* Clean up connection to a remote debugger. */
static void
-remote_close (int quitting)
+remote_close (void)
{
if (remote_desc == NULL)
return; /* already closed */
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. */
send_interrupt_sequence (void)
{
if (interrupt_sequence_mode == interrupt_sequence_control_c)
- serial_write (remote_desc, "\x03", 1);
+ remote_serial_write ("\x03", 1);
else if (interrupt_sequence_mode == interrupt_sequence_break)
serial_send_break (remote_desc);
else if (interrupt_sequence_mode == interrupt_sequence_break_g)
{
serial_send_break (remote_desc);
- serial_write (remote_desc, "g", 1);
+ remote_serial_write ("g", 1);
}
else
internal_error (__FILE__, __LINE__,
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,
{ "QDisableRandomization", PACKET_DISABLE, remote_supported_packet,
PACKET_QDisableRandomization },
{ "QAgent", PACKET_DISABLE, remote_supported_packet, PACKET_QAgent},
+ { "QTBuffer:size", PACKET_DISABLE,
+ remote_supported_packet, PACKET_QTBuffer_size},
{ "tracenz", PACKET_DISABLE,
remote_string_tracing_feature, -1 },
+ { "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 }
};
static char *remote_support_xml;
}
}
+/* Remove any of the remote.c targets from target stack. Upper targets depend
+ on it so remove them first. */
+
+static void
+remote_unpush_target (void)
+{
+ pop_all_targets_above (process_stratum - 1);
+}
static void
remote_open_1 (char *name, int from_tty,
wait_forever_enabled_p = 1;
/* If we're connected to a running target, target_preopen will kill it.
- But if we're connected to a target system with no running process,
- then we will still be connected when it returns. Ask this question
- first, before target_preopen has a chance to kill anything. */
+ Ask this question first, before target_preopen has a chance to kill
+ anything. */
if (remote_desc != NULL && !have_inferiors ())
{
- if (!from_tty
- || query (_("Already connected to a remote target. Disconnect? ")))
- pop_target ();
- else
+ if (from_tty
+ && !query (_("Already connected to a remote target. Disconnect? ")))
error (_("Still connected."));
}
+ /* Here the possibly existing remote target gets unpushed. */
target_preopen (from_tty);
- unpush_target (target);
-
- /* This time without a query. If we were connected to an
- extended-remote target and target_preopen killed the running
- process, we may still be connected. If we are starting "target
- remote" now, the extended-remote target will not have been
- removed by unpush_target. */
- if (remote_desc != NULL && !have_inferiors ())
- pop_target ();
-
/* Make sure we send the passed signals list the next time we resume. */
xfree (last_pass_packet);
last_pass_packet = NULL;
/* Pop the partially set up target - unless something else did
already before throwing the exception. */
if (remote_desc != NULL)
- pop_target ();
+ remote_unpush_target ();
if (target_async_permitted)
wait_forever_enabled_p = 1;
throw_exception (ex);
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
{
if (query (_("Interrupted while waiting for the program.\n\
Give up (and stop debugging it)? ")))
{
- pop_target ();
- deprecated_throw_reason (RETURN_QUIT);
+ remote_unpush_target ();
+ 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;
/* Binary mode. Send target system values byte by byte, in
increasing byte addresses. Only escape certain critical
characters. */
- payload_length = remote_escape_output (myaddr, todo, p, &nr_bytes,
- payload_size);
+ payload_length = remote_escape_output (myaddr, todo, (gdb_byte *) p,
+ &nr_bytes, payload_size);
/* If not all TODO bytes fit, then we'll need another packet. Make
a second try to keep the end of the packet aligned. Don't do
- memaddr);
if (new_nr_bytes != nr_bytes)
payload_length = remote_escape_output (myaddr, new_nr_bytes,
- p, &nr_bytes,
+ (gdb_byte *) p, &nr_bytes,
payload_size);
}
/* Stuff for dealing with the packets which are part of this protocol.
See comment at top of file for details. */
+/* Close/unpush the remote target, and throw a TARGET_CLOSE_ERROR
+ error to higher layers. Called when a serial error is detected.
+ The exception message is STRING, followed by a colon and a blank,
+ the system error message for errno at function entry and final dot
+ for output compatibility with throw_perror_with_name. */
+
+static void
+unpush_and_perror (const char *string)
+{
+ int saved_errno = errno;
+
+ remote_unpush_target ();
+ throw_error (TARGET_CLOSE_ERROR, "%s: %s.", string,
+ safe_strerror (saved_errno));
+}
+
/* Read a single character from the remote end. */
static int
switch ((enum serial_rc) ch)
{
case SERIAL_EOF:
- pop_target ();
- error (_("Remote connection closed"));
+ remote_unpush_target ();
+ throw_error (TARGET_CLOSE_ERROR, _("Remote connection closed"));
/* no return */
case SERIAL_ERROR:
- pop_target ();
- perror_with_name (_("Remote communication error. "
- "Target disconnected."));
+ unpush_and_perror (_("Remote communication error. "
+ "Target disconnected."));
/* no return */
case SERIAL_TIMEOUT:
break;
return ch;
}
+/* Wrapper for serial_write that closes the target and throws if
+ writing fails. */
+
+static void
+remote_serial_write (const char *str, int len)
+{
+ if (serial_write (remote_desc, str, len))
+ {
+ unpush_and_perror (_("Remote communication error. "
+ "Target disconnected."));
+ }
+}
+
/* Send the command in *BUF to the remote machine, and read the reply
into *BUF. Report an error if we get an error reply. Resize
*BUF using xrealloc if necessary to hold the result, and update
gdb_flush (gdb_stdlog);
do_cleanups (old_chain);
}
- if (serial_write (remote_desc, buf2, p - buf2))
- perror_with_name (_("putpkt: write failed"));
+ remote_serial_write (buf2, p - buf2);
/* If this is a no acks version of the remote protocol, send the
packet and move on. */
doesn't get retransmitted when we resend this
packet. */
skip_frame ();
- serial_write (remote_desc, "+", 1);
+ remote_serial_write ("+", 1);
continue; /* Now, go look for +. */
}
if (forever) /* Watchdog went off? Kill the target. */
{
QUIT;
- pop_target ();
- error (_("Watchdog timeout has expired. Target detached."));
+ remote_unpush_target ();
+ throw_error (TARGET_CLOSE_ERROR,
+ _("Watchdog timeout has expired. "
+ "Target detached."));
}
if (remote_debug)
fputs_filtered ("Timed out.\n", gdb_stdlog);
break;
}
- serial_write (remote_desc, "-", 1);
+ remote_serial_write ("-", 1);
}
if (tries > MAX_TRIES)
/* Skip the ack char if we're in no-ack mode. */
if (!rs->noack_mode)
- serial_write (remote_desc, "+", 1);
+ remote_serial_write ("+", 1);
return -1;
}
/* Skip the ack char if we're in no-ack mode. */
if (!rs->noack_mode)
- serial_write (remote_desc, "+", 1);
+ remote_serial_write ("+", 1);
if (is_notif != NULL)
*is_notif = 0;
return val;
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')
{
asection *s;
struct cleanup *old_chain;
- char *sectdata;
+ gdb_byte *sectdata;
const char *sectname;
bfd_size_type size;
bfd_vma lma;
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))
/* Escape as much data as fits into rs->buf. */
buf_len = remote_escape_output
- (writebuf, len, (rs->buf + i), &max_size, max_size);
+ (writebuf, len, (gdb_byte *) rs->buf + i, &max_size, max_size);
if (putpkt_binary (rs->buf, i + buf_len) < 0
|| getpkt_sane (&rs->buf, &rs->buf_size, 0) < 0
error (_("Remote qXfer reply contained no data."));
/* Got some data. */
- i = remote_unescape_input (rs->buf + 1, packet_len - 1, readbuf, n);
+ i = remote_unescape_input ((gdb_byte *) rs->buf + 1,
+ packet_len - 1, readbuf, n);
/* 'l' is an EOF marker, possibly including a final block of data,
or possibly empty. If we have the final block of a non-empty
return remote_read_qxfer (ops, "uib", annex, readbuf, offset, len,
&remote_protocol_packets[PACKET_qXfer_uib]);
+ case TARGET_OBJECT_BTRACE:
+ return remote_read_qxfer (ops, "btrace", annex, readbuf, offset, len,
+ &remote_protocol_packets[PACKET_qXfer_btrace]);
+
default:
return -1;
}
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;",
/* Escape as much data as fits into rs->buf. */
escaped_pattern_len =
- remote_escape_output (pattern, pattern_len, (rs->buf + i),
+ remote_escape_output (pattern, pattern_len, (gdb_byte *) rs->buf + i,
&used_pattern_len, max_size);
/* Bail if the pattern is too large. */
remote_buffer_add_int (&p, &left, offset);
remote_buffer_add_string (&p, &left, ",");
- p += remote_escape_output (write_buf, len, p, &out_len,
+ p += remote_escape_output (write_buf, len, (gdb_byte *) p, &out_len,
get_remote_packet_size () - (p - rs->buf));
return remote_hostio_send_command (p - rs->buf, PACKET_vFile_pwrite,
if (ret < 0)
return ret;
- read_len = remote_unescape_input (attachment, attachment_len,
+ read_len = remote_unescape_input ((gdb_byte *) attachment, attachment_len,
read_buf, len);
if (read_len != ret)
error (_("Read returned %d, but %d bytes."), ret, (int) read_len);
ret = xmalloc (len + 1);
- read_len = remote_unescape_input (attachment, attachment_len,
- ret, len);
+ read_len = remote_unescape_input ((gdb_byte *) attachment, attachment_len,
+ (gdb_byte *) ret, len);
if (read_len != len)
error (_("Readlink returned %d, but %d bytes."), len, read_len);
connection was already torn down. */
remote_hostio_close (fd, &remote_errno);
- return 1;
+ /* Zero means success. */
+ return 0;
}
static file_ptr
pos = 0;
while (nbytes > pos)
{
- bytes = remote_hostio_pread (fd, (char *)buf + pos, nbytes - pos,
+ bytes = remote_hostio_pread (fd, (gdb_byte *) buf + pos, nbytes - pos,
offset + pos, &remote_errno);
if (bytes == 0)
/* Success, but no bytes, means end-of-file. */
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];
/* FIXME we need to get register block size some other way. */
extern int trace_regblock_size;
volatile struct gdb_exception ex;
+ enum packet_result result;
+
+ if (remote_protocol_packets[PACKET_qTStatus].support == PACKET_DISABLE)
+ return -1;
trace_regblock_size = get_remote_arch_state ()->sizeof_g_packet;
}
if (ex.reason < 0)
{
- exception_fprintf (gdb_stderr, ex, "qTStatus: ");
- return -1;
+ if (ex.error != TARGET_CLOSE_ERROR)
+ {
+ exception_fprintf (gdb_stderr, ex, "qTStatus: ");
+ return -1;
+ }
+ throw_exception (ex);
}
+ result = packet_ok (p, &remote_protocol_packets[PACKET_qTStatus]);
+
/* If the remote target doesn't do tracing, flag it. */
- if (*p == '\0')
+ if (result == PACKET_UNKNOWN)
return -1;
/* We're working with a live target. */
static int
remote_trace_find (enum trace_find_type type, int num,
- ULONGEST addr1, ULONGEST addr2,
+ CORE_ADDR addr1, CORE_ADDR addr2,
int *tpp)
{
struct remote_state *rs = get_remote_state ();
}
}
+static void
+remote_set_trace_buffer_size (LONGEST val)
+{
+ if (remote_protocol_packets[PACKET_QTBuffer_size].support
+ != PACKET_DISABLE)
+ {
+ struct remote_state *rs = get_remote_state ();
+ char *buf = rs->buf;
+ char *endbuf = rs->buf + get_remote_packet_size ();
+ enum packet_result result;
+
+ gdb_assert (val >= 0 || val == -1);
+ buf += xsnprintf (buf, endbuf - buf, "QTBuffer:size:");
+ /* Send -1 as literal "-1" to avoid host size dependency. */
+ if (val < 0)
+ {
+ *buf++ = '-';
+ buf += hexnumstr (buf, (ULONGEST) -val);
+ }
+ else
+ buf += hexnumstr (buf, (ULONGEST) val);
+
+ putpkt (rs->buf);
+ remote_get_noisy_reply (&rs->buf, &rs->buf_size);
+ result = packet_ok (rs->buf,
+ &remote_protocol_packets[PACKET_QTBuffer_size]);
+
+ if (result != PACKET_OK)
+ warning (_("Bogus reply from target: %s"), rs->buf);
+ }
+}
+
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;
if (user)
{
buf += xsnprintf (buf, endbuf - buf, "user:");
- nbytes = bin2hex (user, buf, 0);
+ nbytes = bin2hex ((gdb_byte *) user, buf, 0);
buf += 2 * nbytes;
*buf++ = ';';
}
if (notes)
{
buf += xsnprintf (buf, endbuf - buf, "notes:");
- nbytes = bin2hex (notes, buf, 0);
+ nbytes = bin2hex ((gdb_byte *) notes, buf, 0);
buf += 2 * nbytes;
*buf++ = ';';
}
if (stop_notes)
{
buf += xsnprintf (buf, endbuf - buf, "tstop:");
- nbytes = bin2hex (stop_notes, buf, 0);
+ nbytes = bin2hex ((gdb_byte *) stop_notes, buf, 0);
buf += 2 * nbytes;
*buf++ = ';';
}
return (remote_protocol_packets[PACKET_QAgent].support != PACKET_DISABLE);
}
+struct btrace_target_info
+{
+ /* The ptid of the traced thread. */
+ ptid_t ptid;
+};
+
+/* Check whether the target supports branch tracing. */
+
+static int
+remote_supports_btrace (void)
+{
+ if (remote_protocol_packets[PACKET_Qbtrace_off].support != PACKET_ENABLE)
+ return 0;
+ if (remote_protocol_packets[PACKET_Qbtrace_bts].support != PACKET_ENABLE)
+ return 0;
+ if (remote_protocol_packets[PACKET_qXfer_btrace].support != PACKET_ENABLE)
+ return 0;
+
+ return 1;
+}
+
+/* Enable branch tracing. */
+
+static struct btrace_target_info *
+remote_enable_btrace (ptid_t ptid)
+{
+ 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 ();
+
+ if (packet->support != PACKET_ENABLE)
+ error (_("Target does not support branch tracing."));
+
+ set_general_thread (ptid);
+
+ buf += xsnprintf (buf, endbuf - buf, "%s", packet->name);
+ putpkt (rs->buf);
+ getpkt (&rs->buf, &rs->buf_size, 0);
+
+ if (packet_ok (rs->buf, packet) == PACKET_ERROR)
+ {
+ if (rs->buf[0] == 'E' && rs->buf[1] == '.')
+ error (_("Could not enable branch tracing for %s: %s"),
+ target_pid_to_str (ptid), rs->buf + 2);
+ else
+ error (_("Could not enable branch tracing for %s."),
+ target_pid_to_str (ptid));
+ }
+
+ tinfo = xzalloc (sizeof (*tinfo));
+ tinfo->ptid = ptid;
+
+ return tinfo;
+}
+
+/* Disable branch tracing. */
+
+static void
+remote_disable_btrace (struct btrace_target_info *tinfo)
+{
+ struct packet_config *packet = &remote_protocol_packets[PACKET_Qbtrace_off];
+ struct remote_state *rs = get_remote_state ();
+ char *buf = rs->buf;
+ char *endbuf = rs->buf + get_remote_packet_size ();
+
+ if (packet->support != PACKET_ENABLE)
+ error (_("Target does not support branch tracing."));
+
+ set_general_thread (tinfo->ptid);
+
+ buf += xsnprintf (buf, endbuf - buf, "%s", packet->name);
+ putpkt (rs->buf);
+ getpkt (&rs->buf, &rs->buf_size, 0);
+
+ if (packet_ok (rs->buf, packet) == PACKET_ERROR)
+ {
+ if (rs->buf[0] == 'E' && rs->buf[1] == '.')
+ error (_("Could not disable branch tracing for %s: %s"),
+ target_pid_to_str (tinfo->ptid), rs->buf + 2);
+ else
+ error (_("Could not disable branch tracing for %s."),
+ target_pid_to_str (tinfo->ptid));
+ }
+
+ xfree (tinfo);
+}
+
+/* Teardown branch tracing. */
+
+static void
+remote_teardown_btrace (struct btrace_target_info *tinfo)
+{
+ /* We must not talk to the target during teardown. */
+ xfree (tinfo);
+}
+
+/* Read the branch trace. */
+
+static VEC (btrace_block_s) *
+remote_read_btrace (struct btrace_target_info *tinfo,
+ enum btrace_read_type type)
+{
+ struct packet_config *packet = &remote_protocol_packets[PACKET_qXfer_btrace];
+ struct remote_state *rs = get_remote_state ();
+ VEC (btrace_block_s) *btrace = NULL;
+ const char *annex;
+ char *xml;
+
+ if (packet->support != PACKET_ENABLE)
+ error (_("Target does not support branch tracing."));
+
+#if !defined(HAVE_LIBEXPAT)
+ error (_("Cannot process branch tracing result. XML parsing not supported."));
+#endif
+
+ switch (type)
+ {
+ case btrace_read_all:
+ annex = "all";
+ break;
+ case btrace_read_new:
+ annex = "new";
+ break;
+ default:
+ internal_error (__FILE__, __LINE__,
+ _("Bad branch tracing read type: %u."),
+ (unsigned int) type);
+ }
+
+ xml = target_read_stralloc (¤t_target,
+ TARGET_OBJECT_BTRACE, annex);
+ if (xml != NULL)
+ {
+ struct cleanup *cleanup = make_cleanup (xfree, xml);
+
+ btrace = parse_xml_btrace (xml);
+ do_cleanups (cleanup);
+ }
+
+ 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_get_min_fast_tracepoint_insn_len = remote_get_min_fast_tracepoint_insn_len;
remote_ops.to_set_disconnected_tracing = remote_set_disconnected_tracing;
remote_ops.to_set_circular_trace_buffer = remote_set_circular_trace_buffer;
+ remote_ops.to_set_trace_buffer_size = remote_set_trace_buffer_size;
remote_ops.to_set_trace_notes = remote_set_trace_notes;
remote_ops.to_core_of_thread = remote_core_of_thread;
remote_ops.to_verify_memory = remote_verify_memory;
remote_ops.to_traceframe_info = remote_traceframe_info;
remote_ops.to_use_agent = remote_use_agent;
remote_ops.to_can_use_agent = remote_can_use_agent;
+ remote_ops.to_supports_btrace = remote_supports_btrace;
+ remote_ops.to_enable_btrace = remote_enable_btrace;
+ 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)
{
struct remote_state *rs;
struct cmd_list_element *cmd;
- char *cmd_name;
+ const char *cmd_name;
/* architecture specific data */
remote_gdbarch_data_handle =
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
breakpoints is %s. */
&remote_set_cmdlist, &remote_show_cmdlist);
- add_setshow_uinteger_cmd ("remoteaddresssize", class_obscure,
- &remote_address_size, _("\
+ add_setshow_zuinteger_cmd ("remoteaddresssize", class_obscure,
+ &remote_address_size, _("\
Set the maximum size of the address (in bits) in a memory packet."), _("\
Show the maximum size of the address (in bits) in a memory packet."), NULL,
- NULL,
- NULL, /* FIXME: i18n: */
- &setlist, &showlist);
+ NULL,
+ NULL, /* FIXME: i18n: */
+ &setlist, &showlist);
add_packet_config_cmd (&remote_protocol_packets[PACKET_X],
"X", "binary-download", 1);
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);
add_packet_config_cmd (&remote_protocol_packets[PACKET_qSearch_memory],
"qSearch:memory", "search-memory", 0);
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_qTStatus],
+ "qTStatus", "trace-status", 0);
+
add_packet_config_cmd (&remote_protocol_packets[PACKET_vFile_open],
"vFile:open", "hostio-open", 0);
add_packet_config_cmd (&remote_protocol_packets[PACKET_QAgent],
"QAgent", "agent", 0);
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_QTBuffer_size],
+ "QTBuffer:size", "trace-buffer-size", 0);
+
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_Qbtrace_off],
+ "Qbtrace:off", "disable-btrace", 0);
+
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_Qbtrace_bts],
+ "Qbtrace:bts", "enable-btrace", 0);
+
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_btrace],
+ "qXfer:btrace", "read-btrace", 0);
+
/* Keep the old ``set remote Z-packet ...'' working. Each individual
Z sub-packet has its own set and show commands, but users may
have sets to this variable in their .gdbinit files (or in their
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);