Index: gdb/remote.c |
diff --git a/gdb/remote.c b/gdb/remote.c |
index 1c9367d2b0f569416588d3786d4a934e223d80a1..2ac8c367251f55fc15944ac4e30950772dc450a3 100644 |
--- a/gdb/remote.c |
+++ b/gdb/remote.c |
@@ -1,6 +1,6 @@ |
/* Remote target communications for serial-line targets in custom GDB protocol |
- Copyright (C) 1988-2012 Free Software Foundation, Inc. |
+ Copyright (C) 1988-2013 Free Software Foundation, Inc. |
This file is part of GDB. |
@@ -20,7 +20,7 @@ |
/* See the GDB User Guide for details of the GDB remote protocol. */ |
#include "defs.h" |
-#include "gdb_string.h" |
+#include <string.h> |
#include <ctype.h> |
#include <fcntl.h> |
#include "inferior.h" |
@@ -34,6 +34,7 @@ |
#include "gdb-stabs.h" |
#include "gdbthread.h" |
#include "remote.h" |
+#include "remote-notif.h" |
#include "regcache.h" |
#include "value.h" |
#include "gdb_assert.h" |
@@ -42,6 +43,8 @@ |
#include "cli/cli-decode.h" |
#include "cli/cli-setshow.h" |
#include "target-descriptions.h" |
+#include "gdb_bfd.h" |
+#include "filestuff.h" |
#include <ctype.h> |
#include <sys/time.h> |
@@ -57,7 +60,7 @@ |
#include "remote-fileio.h" |
#include "gdb/fileio.h" |
-#include "gdb_stat.h" |
+#include <sys/stat.h> |
#include "xml-support.h" |
#include "memory-map.h" |
@@ -66,6 +69,7 @@ |
#include "ax.h" |
#include "ax-gdb.h" |
#include "agent.h" |
+#include "btrace.h" |
/* Temp hacks for tracepoint encoding migration. */ |
static char *target_buf; |
@@ -84,16 +88,13 @@ static long target_buf_size; |
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 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); |
@@ -105,7 +106,7 @@ 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_close (int quitting); |
+static void remote_close (void); |
static void remote_mourn (struct target_ops *ops); |
@@ -119,6 +120,8 @@ static void remote_send (char **buf, long *sizeof_buf_p); |
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); |
@@ -130,11 +133,7 @@ static int remote_is_async_p (void); |
static void remote_async (void (*callback) (enum inferior_event_type event_type, |
void *context), void *context); |
-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); |
@@ -177,14 +176,8 @@ static ptid_t remote_current_thread (ptid_t oldptid); |
static void remote_find_new_threads (void); |
-static void record_currthread (ptid_t currthread); |
- |
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); |
@@ -217,22 +210,18 @@ static int remote_upload_trace_state_variables (struct uploaded_tsv **utsvp); |
static void remote_query_supported (void); |
-static void remote_check_symbols (struct objfile *objfile); |
+static void remote_check_symbols (void); |
void _initialize_remote (void); |
struct stop_reply; |
-static struct stop_reply *stop_reply_xmalloc (void); |
static void stop_reply_xfree (struct stop_reply *); |
-static void do_stop_reply_xfree (void *arg); |
-static void remote_parse_stop_reply (char *buf, struct stop_reply *); |
+static void remote_parse_stop_reply (char *, struct stop_reply *); |
static void push_stop_reply (struct stop_reply *); |
-static void remote_get_pending_stop_replies (void); |
-static void discard_pending_stop_replies (int pid); |
+static void discard_pending_stop_replies_in_queue (struct remote_state *); |
static int peek_stop_reply (ptid_t ptid); |
static void remote_async_inferior_event_handler (gdb_client_data); |
-static void remote_async_get_pending_events_handler (gdb_client_data); |
static void remote_terminal_ours (void); |
@@ -244,11 +233,6 @@ static int remote_supports_cond_breakpoints (void); |
static int remote_can_run_breakpoint_commands (void); |
-/* The non-stop remote protocol provisions for one pending stop reply. |
- This is where we keep it until it is acknowledged. */ |
- |
-static struct stop_reply *pending_stop_reply = NULL; |
- |
/* For "remote". */ |
static struct cmd_list_element *remote_cmdlist; |
@@ -258,6 +242,33 @@ static struct cmd_list_element *remote_cmdlist; |
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; |
+ |
+#define OPAQUETHREADBYTES 8 |
+ |
+/* a 64 bit opaque identifier */ |
+typedef unsigned char threadref[OPAQUETHREADBYTES]; |
+ |
+/* About this many threadisds fit in a packet. */ |
+ |
+#define MAXTHREADLISTRESULTS 32 |
+ |
/* Description of the remote protocol state for the currently |
connected target. This is per-target state, and independent of the |
selected architecture. */ |
@@ -315,8 +326,8 @@ struct remote_state |
/* 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; |
@@ -350,9 +361,71 @@ struct remote_state |
/* 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; |
+ |
+ /* Descriptor for I/O to remote machine. Initialize it to NULL so that |
+ remote_open knows that we don't have a file open when the program |
+ starts. */ |
+ struct serial *remote_desc; |
+ |
+ /* These are the threads which we last sent to the remote system. The |
+ TID member will be -1 for all or -2 for not sent yet. */ |
+ ptid_t general_thread; |
+ ptid_t continue_thread; |
+ |
+ /* This is the traceframe which we last selected on the remote system. |
+ It will be -1 if no traceframe is selected. */ |
+ int remote_traceframe_number; |
+ |
+ char *last_pass_packet; |
+ |
+ /* The last QProgramSignals packet sent to the target. We bypass |
+ sending a new program signals list down to the target if the new |
+ packet is exactly the same as the last we sent. IOW, we only let |
+ the target know about program signals list changes. */ |
+ char *last_program_signals_packet; |
+ |
+ enum gdb_signal last_sent_signal; |
+ |
+ int last_sent_step; |
+ |
+ char *finished_object; |
+ char *finished_annex; |
+ ULONGEST finished_offset; |
+ |
+ /* Should we try the 'ThreadInfo' query packet? |
+ |
+ This variable (NOT available to the user: auto-detect only!) |
+ determines whether GDB will use the new, simpler "ThreadInfo" |
+ query or the older, more complex syntax for thread queries. |
+ This is an auto-detect variable (set to true at each connect, |
+ and set to false when the target fails to recognize it). */ |
+ int use_threadinfo_query; |
+ int use_threadextra_query; |
+ |
+ void (*async_client_callback) (enum inferior_event_type event_type, |
+ void *context); |
+ void *async_client_context; |
+ |
+ /* This is set to the data address of the access causing the target |
+ 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; |
+ |
+ threadref echo_nextthread; |
+ threadref nextthread; |
+ threadref resultthreadlist[MAXTHREADLISTRESULTS]; |
+ |
+ /* The state of remote notification. */ |
+ struct remote_notif_state *notif_state; |
}; |
/* Private data that we'll store in (struct thread_info)->private. */ |
@@ -380,12 +453,30 @@ remote_multi_process_p (struct remote_state *rs) |
have access to the current target when we need it, so for now it is |
static. This will be fine for as long as only one target is in use |
at a time. */ |
-static struct remote_state remote_state; |
+static struct remote_state *remote_state; |
static struct remote_state * |
get_remote_state_raw (void) |
{ |
- return &remote_state; |
+ return remote_state; |
+} |
+ |
+/* Allocate a new struct remote_state with xmalloc, initialize it, and |
+ return it. */ |
+ |
+static struct remote_state * |
+new_remote_state (void) |
+{ |
+ struct remote_state *result = XCNEW (struct remote_state); |
+ |
+ /* The default buffer size is unimportant; it will be expanded |
+ whenever a larger buffer is needed. */ |
+ result->buf_size = 400; |
+ result->buf = xmalloc (result->buf_size); |
+ result->remote_traceframe_number = -1; |
+ result->last_sent_signal = GDB_SIGNAL_0; |
+ |
+ return result; |
} |
/* Description of the remote protocol for a given architecture. */ |
@@ -396,9 +487,9 @@ struct packet_reg |
long regnum; /* GDB's internal register number. */ |
LONGEST pnum; /* Remote protocol register number. */ |
int in_g_packet; /* Always part of G packet. */ |
- /* long size in bytes; == register_size (target_gdbarch, regnum); |
+ /* long size in bytes; == register_size (target_gdbarch (), regnum); |
at present. */ |
- /* char *name; == gdbarch_register_name (target_gdbarch, regnum); |
+ /* char *name; == gdbarch_register_name (target_gdbarch (), regnum); |
at present. */ |
}; |
@@ -424,8 +515,6 @@ struct remote_arch_state |
long remote_packet_size; |
}; |
-long sizeof_pkt = 2000; |
- |
/* Utility: generate error from an incoming stub packet. */ |
static void |
trace_error (char *buf) |
@@ -440,8 +529,6 @@ trace_error (char *buf) |
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); |
} |
@@ -483,7 +570,7 @@ remote_get_noisy_reply (char **buf_p, |
TRY_CATCH (ex, RETURN_MASK_ALL) |
{ |
- gdbarch_relocate_instruction (target_gdbarch, &to, from); |
+ gdbarch_relocate_instruction (target_gdbarch (), &to, from); |
} |
if (ex.reason >= 0) |
{ |
@@ -524,7 +611,7 @@ static struct gdbarch_data *remote_gdbarch_data_handle; |
static struct remote_arch_state * |
get_remote_arch_state (void) |
{ |
- return gdbarch_data (target_gdbarch, remote_gdbarch_data_handle); |
+ return gdbarch_data (target_gdbarch (), remote_gdbarch_data_handle); |
} |
/* Fetch the global remote target state. */ |
@@ -697,7 +784,7 @@ get_remote_packet_size (void) |
static struct packet_reg * |
packet_reg_from_regnum (struct remote_arch_state *rsa, long regnum) |
{ |
- if (regnum < 0 && regnum >= gdbarch_num_regs (target_gdbarch)) |
+ if (regnum < 0 && regnum >= gdbarch_num_regs (target_gdbarch ())) |
return NULL; |
else |
{ |
@@ -713,7 +800,7 @@ packet_reg_from_pnum (struct remote_arch_state *rsa, LONGEST pnum) |
{ |
int i; |
- for (i = 0; i < gdbarch_num_regs (target_gdbarch); i++) |
+ for (i = 0; i < gdbarch_num_regs (target_gdbarch ()); i++) |
{ |
struct packet_reg *r = &rsa->regs[i]; |
@@ -723,17 +810,6 @@ packet_reg_from_pnum (struct remote_arch_state *rsa, LONGEST pnum) |
return NULL; |
} |
-/* FIXME: graces/2002-08-08: These variables should eventually be |
- bound to an instance of the target object (as in gdbarch-tdep()), |
- when such a thing exists. */ |
- |
-/* This is set to the data address of the access causing the target |
- to stop for a watchpoint. */ |
-static CORE_ADDR remote_watch_data_address; |
- |
-/* This is non-zero if target stopped for a watchpoint. */ |
-static int remote_stopped_by_watchpoint_p; |
- |
static struct target_ops remote_ops; |
static struct target_ops extended_remote_ops; |
@@ -817,11 +893,6 @@ show_remotebreak (struct ui_file *file, int from_tty, |
{ |
} |
-/* Descriptor for I/O to remote machine. Initialize it to NULL so that |
- remote_open knows that we don't have a file open when the program |
- starts. */ |
-static struct serial *remote_desc = NULL; |
- |
/* This variable sets the number of bits in an address that are to be |
sent in a memory ("M" or "m") packet. Normally, after stripping |
leading zeros, the entire address would be sent. This variable |
@@ -833,7 +904,7 @@ static struct serial *remote_desc = NULL; |
some remote targets this variable is principly provided to |
facilitate backward compatibility. */ |
-static int remote_address_size; |
+static unsigned int remote_address_size; |
/* Temporary to track who currently owns the terminal. See |
remote_terminal_* for more details. */ |
@@ -1268,6 +1339,7 @@ enum { |
PACKET_qGetTIBAddr, |
PACKET_qGetTLSAddr, |
PACKET_qSupported, |
+ PACKET_qTStatus, |
PACKET_QPassSignals, |
PACKET_QProgramSignals, |
PACKET_qSearch_memory, |
@@ -1291,6 +1363,10 @@ enum { |
PACKET_qXfer_fdpic, |
PACKET_QDisableRandomization, |
PACKET_QAgent, |
+ PACKET_QTBuffer_size, |
+ PACKET_Qbtrace_off, |
+ PACKET_Qbtrace_bts, |
+ PACKET_qXfer_btrace, |
PACKET_MAX |
}; |
@@ -1380,20 +1456,9 @@ show_remote_protocol_Z_packet_cmd (struct ui_file *file, int from_tty, |
} |
} |
-/* Should we try the 'ThreadInfo' query packet? |
- |
- This variable (NOT available to the user: auto-detect only!) |
- determines whether GDB will use the new, simpler "ThreadInfo" |
- query or the older, more complex syntax for thread queries. |
- This is an auto-detect variable (set to true at each connect, |
- and set to false when the target fails to recognize it). */ |
- |
-static int use_threadinfo_query; |
-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; |
/* Asynchronous signal handle registered as event loop source for |
@@ -1401,28 +1466,12 @@ static struct async_signal_handler *sigint_remote_token; |
static struct async_event_handler *remote_async_inferior_event_token; |
-/* Asynchronous signal handle registered as event loop source for when |
- the remote sent us a %Stop notification. The registered callback |
- will do a vStopped sequence to pull the rest of the events out of |
- the remote side into our event queue. */ |
- |
-static struct async_event_handler *remote_async_get_pending_events_token; |
static ptid_t magic_null_ptid; |
static ptid_t not_sent_ptid; |
static ptid_t any_thread_ptid; |
-/* These are the threads which we last sent to the remote system. The |
- TID member will be -1 for all or -2 for not sent yet. */ |
- |
-static ptid_t general_thread; |
-static ptid_t continue_thread; |
- |
-/* This the traceframe which we last selected on the remote system. |
- It will be -1 if no traceframe is selected. */ |
-static int remote_traceframe_number = -1; |
- |
/* Find out if the stub attached to PID (and hence GDB should offer to |
detach instead of killing it when bailing out). */ |
@@ -1480,7 +1529,7 @@ remote_add_inferior (int fake_pid_p, int pid, int attached) |
if (attached == -1) |
attached = remote_query_attached (pid); |
- if (gdbarch_has_global_solist (target_gdbarch)) |
+ if (gdbarch_has_global_solist (target_gdbarch ())) |
{ |
/* If the target shares code across all inferiors, then every |
attach adds a new inferior. */ |
@@ -1623,13 +1672,11 @@ demand_private_info (ptid_t ptid) |
3) Successful execution of set thread */ |
static void |
-record_currthread (ptid_t currthread) |
+record_currthread (struct remote_state *rs, ptid_t currthread) |
{ |
- general_thread = currthread; |
+ rs->general_thread = currthread; |
} |
-static char *last_pass_packet; |
- |
/* If 'QPassSignals' is supported, tell the remote stub what signals |
it can simply pass through to the inferior without reporting. */ |
@@ -1640,6 +1687,7 @@ remote_pass_signals (int numsigs, unsigned char *pass_signals) |
{ |
char *pass_packet, *p; |
int count = 0, i; |
+ struct remote_state *rs = get_remote_state (); |
gdb_assert (numsigs < 256); |
for (i = 0; i < numsigs; i++) |
@@ -1665,30 +1713,22 @@ remote_pass_signals (int numsigs, unsigned char *pass_signals) |
} |
} |
*p = 0; |
- if (!last_pass_packet || strcmp (last_pass_packet, pass_packet)) |
+ if (!rs->last_pass_packet || strcmp (rs->last_pass_packet, pass_packet)) |
{ |
- struct remote_state *rs = get_remote_state (); |
char *buf = rs->buf; |
putpkt (pass_packet); |
getpkt (&rs->buf, &rs->buf_size, 0); |
packet_ok (buf, &remote_protocol_packets[PACKET_QPassSignals]); |
- if (last_pass_packet) |
- xfree (last_pass_packet); |
- last_pass_packet = pass_packet; |
+ if (rs->last_pass_packet) |
+ xfree (rs->last_pass_packet); |
+ rs->last_pass_packet = pass_packet; |
} |
else |
xfree (pass_packet); |
} |
} |
-/* The last QProgramSignals packet sent to the target. We bypass |
- sending a new program signals list down to the target if the new |
- packet is exactly the same as the last we sent. IOW, we only let |
- the target know about program signals list changes. */ |
- |
-static char *last_program_signals_packet; |
- |
/* If 'QProgramSignals' is supported, tell the remote stub what |
signals it should pass through to the inferior when detaching. */ |
@@ -1699,6 +1739,7 @@ remote_program_signals (int numsigs, unsigned char *signals) |
{ |
char *packet, *p; |
int count = 0, i; |
+ struct remote_state *rs = get_remote_state (); |
gdb_assert (numsigs < 256); |
for (i = 0; i < numsigs; i++) |
@@ -1724,17 +1765,16 @@ remote_program_signals (int numsigs, unsigned char *signals) |
} |
} |
*p = 0; |
- if (!last_program_signals_packet |
- || strcmp (last_program_signals_packet, packet) != 0) |
+ if (!rs->last_program_signals_packet |
+ || strcmp (rs->last_program_signals_packet, packet) != 0) |
{ |
- struct remote_state *rs = get_remote_state (); |
char *buf = rs->buf; |
putpkt (packet); |
getpkt (&rs->buf, &rs->buf_size, 0); |
packet_ok (buf, &remote_protocol_packets[PACKET_QProgramSignals]); |
- xfree (last_program_signals_packet); |
- last_program_signals_packet = packet; |
+ xfree (rs->last_program_signals_packet); |
+ rs->last_program_signals_packet = packet; |
} |
else |
xfree (packet); |
@@ -1749,7 +1789,7 @@ static void |
set_thread (struct ptid ptid, int gen) |
{ |
struct remote_state *rs = get_remote_state (); |
- ptid_t state = gen ? general_thread : continue_thread; |
+ ptid_t state = gen ? rs->general_thread : rs->continue_thread; |
char *buf = rs->buf; |
char *endbuf = rs->buf + get_remote_packet_size (); |
@@ -1769,9 +1809,9 @@ set_thread (struct ptid ptid, int gen) |
putpkt (rs->buf); |
getpkt (&rs->buf, &rs->buf_size, 0); |
if (gen) |
- general_thread = ptid; |
+ rs->general_thread = ptid; |
else |
- continue_thread = ptid; |
+ rs->continue_thread = ptid; |
} |
static void |
@@ -1806,7 +1846,7 @@ set_general_process (void) |
/* We only need to change the remote current thread if it's pointing |
at some other process. */ |
- if (ptid_get_pid (general_thread) != ptid_get_pid (inferior_ptid)) |
+ if (ptid_get_pid (rs->general_thread) != ptid_get_pid (inferior_ptid)) |
set_general_thread (inferior_ptid); |
} |
@@ -1847,11 +1887,6 @@ remote_thread_alive (struct target_ops *ops, ptid_t ptid) |
remote protocol in general. There is a matching unit test module |
in libstub. */ |
-#define OPAQUETHREADBYTES 8 |
- |
-/* a 64 bit opaque identifier */ |
-typedef unsigned char threadref[OPAQUETHREADBYTES]; |
- |
/* WARNING: This threadref data structure comes from the remote O.S., |
libstub protocol encoding, and remote.c. It is not particularly |
changable. */ |
@@ -2467,7 +2502,6 @@ remote_get_threadlist (int startflag, threadref *nextthread, int result_limit, |
int *done, int *result_count, threadref *threadlist) |
{ |
struct remote_state *rs = get_remote_state (); |
- static threadref echo_nextthread; |
int result = 1; |
/* Trancate result limit to be smaller than the packet size. */ |
@@ -2483,10 +2517,10 @@ remote_get_threadlist (int startflag, threadref *nextthread, int result_limit, |
return 0; |
else |
*result_count = |
- parse_threadlist_response (rs->buf + 2, result_limit, &echo_nextthread, |
- threadlist, done); |
+ parse_threadlist_response (rs->buf + 2, result_limit, |
+ &rs->echo_nextthread, threadlist, done); |
- if (!threadmatch (&echo_nextthread, nextthread)) |
+ if (!threadmatch (&rs->echo_nextthread, nextthread)) |
{ |
/* FIXME: This is a good reason to drop the packet. */ |
/* Possably, there is a duplicate response. */ |
@@ -2527,20 +2561,15 @@ remote_get_threadlist (int startflag, threadref *nextthread, int result_limit, |
quit_flag is required. */ |
-/* About this many threadisds fit in a packet. */ |
- |
-#define MAXTHREADLISTRESULTS 32 |
- |
static int |
remote_threadlist_iterator (rmt_thread_action stepfunction, void *context, |
int looplimit) |
{ |
+ struct remote_state *rs = get_remote_state (); |
int done, i, result_count; |
int startflag = 1; |
int result = 1; |
int loopcount = 0; |
- static threadref nextthread; |
- static threadref resultthreadlist[MAXTHREADLISTRESULTS]; |
done = 0; |
while (!done) |
@@ -2551,8 +2580,9 @@ remote_threadlist_iterator (rmt_thread_action stepfunction, void *context, |
warning (_("Remote fetch threadlist -infinite loop-.")); |
break; |
} |
- if (!remote_get_threadlist (startflag, &nextthread, MAXTHREADLISTRESULTS, |
- &done, &result_count, resultthreadlist)) |
+ if (!remote_get_threadlist (startflag, &rs->nextthread, |
+ MAXTHREADLISTRESULTS, |
+ &done, &result_count, rs->resultthreadlist)) |
{ |
result = 0; |
break; |
@@ -2561,10 +2591,11 @@ remote_threadlist_iterator (rmt_thread_action stepfunction, void *context, |
startflag = 0; |
/* Setup to resume next batch of thread references, set nextthread. */ |
if (result_count >= 1) |
- copy_threadref (&nextthread, &resultthreadlist[result_count - 1]); |
+ copy_threadref (&rs->nextthread, |
+ &rs->resultthreadlist[result_count - 1]); |
i = 0; |
while (result_count--) |
- if (!(result = (*stepfunction) (&resultthreadlist[i++], context))) |
+ if (!(result = (*stepfunction) (&rs->resultthreadlist[i++], context))) |
break; |
} |
return result; |
@@ -2712,7 +2743,7 @@ remote_threads_info (struct target_ops *ops) |
char *bufp; |
ptid_t new_thread; |
- if (remote_desc == 0) /* paranoia */ |
+ if (rs->remote_desc == 0) /* paranoia */ |
error (_("Command can only be used when connected to the remote target.")); |
#if defined(HAVE_LIBEXPAT) |
@@ -2765,13 +2796,22 @@ remote_threads_info (struct target_ops *ops) |
} |
#endif |
- if (use_threadinfo_query) |
+ if (rs->use_threadinfo_query) |
{ |
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 |
@@ -2789,10 +2829,12 @@ remote_threads_info (struct target_ops *ops) |
} |
} |
while (*bufp++ == ','); /* comma-separated list */ |
+ free_current_contents (&saved_reply); |
putpkt ("qsThreadInfo"); |
getpkt (&rs->buf, &rs->buf_size, 0); |
- bufp = rs->buf; |
+ bufp = saved_reply = xstrdup (rs->buf); |
} |
+ do_cleanups (old_chain); |
return; /* done */ |
} |
} |
@@ -2802,7 +2844,7 @@ remote_threads_info (struct target_ops *ops) |
return; |
/* Else fall back to old method based on jmetzler protocol. */ |
- use_threadinfo_query = 0; |
+ rs->use_threadinfo_query = 0; |
remote_find_new_threads (); |
return; |
} |
@@ -2827,7 +2869,7 @@ remote_threads_extra_info (struct thread_info *tp) |
static char display_buf[100]; /* arbitrary... */ |
int n = 0; /* position in display_buf */ |
- if (remote_desc == 0) /* paranoia */ |
+ if (rs->remote_desc == 0) /* paranoia */ |
internal_error (__FILE__, __LINE__, |
_("remote_threads_extra_info")); |
@@ -2847,7 +2889,7 @@ remote_threads_extra_info (struct thread_info *tp) |
return NULL; |
} |
- if (use_threadextra_query) |
+ if (rs->use_threadextra_query) |
{ |
char *b = rs->buf; |
char *endb = rs->buf + get_remote_packet_size (); |
@@ -2868,7 +2910,7 @@ remote_threads_extra_info (struct thread_info *tp) |
} |
/* If the above query fails, fall back to the old method. */ |
- use_threadextra_query = 0; |
+ rs->use_threadextra_query = 0; |
set = TAG_THREADID | TAG_EXISTS | TAG_THREADNAME |
| TAG_MOREDISPLAY | TAG_DISPLAY; |
int_to_threadref (&id, ptid_get_tid (tp->ptid)); |
@@ -3002,17 +3044,19 @@ extended_remote_restart (void) |
/* Clean up connection to a remote debugger. */ |
static void |
-remote_close (int quitting) |
+remote_close (void) |
{ |
- if (remote_desc == NULL) |
+ struct remote_state *rs = get_remote_state (); |
+ |
+ if (rs->remote_desc == NULL) |
return; /* already closed */ |
/* Make sure we leave stdin registered in the event loop, and we |
don't leave the async SIGINT signal handler installed. */ |
remote_terminal_ours (); |
- serial_close (remote_desc); |
- remote_desc = NULL; |
+ serial_close (rs->remote_desc); |
+ rs->remote_desc = NULL; |
/* We don't have a connection to the remote stub anymore. Get rid |
of all the inferiors and their threads we were controlling. |
@@ -3021,13 +3065,16 @@ remote_close (int quitting) |
inferior_ptid = null_ptid; |
discard_all_inferiors (); |
- /* We're no longer interested in any of these events. */ |
- discard_pending_stop_replies (-1); |
+ /* We are closing the remote target, so we should discard |
+ everything of this target. */ |
+ discard_pending_stop_replies_in_queue (rs); |
if (remote_async_inferior_event_token) |
delete_async_event_handler (&remote_async_inferior_event_token); |
- if (remote_async_get_pending_events_token) |
- delete_async_event_handler (&remote_async_get_pending_events_token); |
+ |
+ remote_notif_state_xfree (rs->notif_state); |
+ |
+ trace_reset_local_state (); |
} |
/* Query the remote side for the text, data and bss offsets. */ |
@@ -3208,14 +3255,16 @@ set_stop_requested_callback (struct thread_info *thread, void *data) |
static void |
send_interrupt_sequence (void) |
{ |
+ struct remote_state *rs = get_remote_state (); |
+ |
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); |
+ serial_send_break (rs->remote_desc); |
else if (interrupt_sequence_mode == interrupt_sequence_break_g) |
{ |
- serial_send_break (remote_desc); |
- serial_write (remote_desc, "g", 1); |
+ serial_send_break (rs->remote_desc); |
+ remote_serial_write ("g", 1); |
} |
else |
internal_error (__FILE__, __LINE__, |
@@ -3223,22 +3272,77 @@ send_interrupt_sequence (void) |
interrupt_sequence_mode); |
} |
+ |
+/* If STOP_REPLY is a T stop reply, look for the "thread" register, |
+ and extract the PTID. Returns NULL_PTID if not found. */ |
+ |
+static ptid_t |
+stop_reply_extract_thread (char *stop_reply) |
+{ |
+ if (stop_reply[0] == 'T' && strlen (stop_reply) > 3) |
+ { |
+ char *p; |
+ |
+ /* Txx r:val ; r:val (...) */ |
+ p = &stop_reply[3]; |
+ |
+ /* Look for "register" named "thread". */ |
+ while (*p != '\0') |
+ { |
+ char *p1; |
+ |
+ p1 = strchr (p, ':'); |
+ if (p1 == NULL) |
+ return null_ptid; |
+ |
+ if (strncmp (p, "thread", p1 - p) == 0) |
+ return read_ptid (++p1, &p); |
+ |
+ p1 = strchr (p, ';'); |
+ if (p1 == NULL) |
+ return null_ptid; |
+ p1++; |
+ |
+ p = p1; |
+ } |
+ } |
+ |
+ return null_ptid; |
+} |
+ |
/* Query the remote target for which is the current thread/process, |
add it to our tables, and update INFERIOR_PTID. The caller is |
responsible for setting the state such that the remote end is ready |
- to return the current thread. */ |
+ to return the current thread. |
+ |
+ This function is called after handling the '?' or 'vRun' packets, |
+ whose response is a stop reply from which we can also try |
+ extracting the thread. If the target doesn't support the explicit |
+ qC query, we infer the current thread from that stop reply, passed |
+ in in WAIT_STATUS, which may be NULL. */ |
static void |
-add_current_inferior_and_thread (void) |
+add_current_inferior_and_thread (char *wait_status) |
{ |
struct remote_state *rs = get_remote_state (); |
int fake_pid_p = 0; |
- ptid_t ptid; |
+ ptid_t ptid = null_ptid; |
inferior_ptid = null_ptid; |
- /* Now, if we have thread information, update inferior_ptid. */ |
- ptid = remote_current_thread (inferior_ptid); |
+ /* Now, if we have thread information, update inferior_ptid. First |
+ if we have a stop reply handy, maybe it's a T stop reply with a |
+ "thread" register we can extract the current thread from. If |
+ not, ask the remote which is the current thread, with qC. The |
+ former method avoids a roundtrip. Note we don't use |
+ remote_parse_stop_reply as that makes use of the target |
+ architecture, which we haven't yet fully determined at this |
+ point. */ |
+ if (wait_status != NULL) |
+ ptid = stop_reply_extract_thread (wait_status); |
+ if (ptid_equal (ptid, null_ptid)) |
+ ptid = remote_current_thread (inferior_ptid); |
+ |
if (!ptid_equal (ptid, null_ptid)) |
{ |
if (!remote_multi_process_p (rs)) |
@@ -3270,12 +3374,13 @@ remote_start_remote (int from_tty, struct target_ops *target, int extended_p) |
char *wait_status = NULL; |
immediate_quit++; /* Allow user to interrupt it. */ |
+ QUIT; |
if (interrupt_on_connect) |
send_interrupt_sequence (); |
/* Ack any packet which the remote side has already sent. */ |
- serial_write (remote_desc, "+", 1); |
+ serial_write (rs->remote_desc, "+", 1); |
/* Signal other parts that we're going through the initial setup, |
and so things may not be stable yet. */ |
@@ -3336,7 +3441,7 @@ remote_start_remote (int from_tty, struct target_ops *target, int extended_p) |
/* On OSs where the list of libraries is global to all |
processes, we fetch them early. */ |
- if (gdbarch_has_global_solist (target_gdbarch)) |
+ if (gdbarch_has_global_solist (target_gdbarch ())) |
solib_add (NULL, from_tty, target, auto_solib_add); |
if (non_stop) |
@@ -3360,7 +3465,7 @@ remote_start_remote (int from_tty, struct target_ops *target, int extended_p) |
else if (rs->non_stop_aware) |
{ |
/* Don't assume that the stub can operate in all-stop mode. |
- Request it explicitely. */ |
+ Request it explicitly. */ |
putpkt ("QNonStop:0"); |
getpkt (&rs->buf, &rs->buf_size, 0); |
@@ -3368,6 +3473,17 @@ remote_start_remote (int from_tty, struct target_ops *target, int extended_p) |
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); |
@@ -3398,7 +3514,7 @@ remote_start_remote (int from_tty, struct target_ops *target, int extended_p) |
/* Let the stub know that we want it to return the thread. */ |
set_continue_thread (minus_one_ptid); |
- add_current_inferior_and_thread (); |
+ add_current_inferior_and_thread (wait_status); |
/* init_wait_for_inferior should be called before get_offsets in order |
to manage `inserted' flag in bp loc in a correct state. |
@@ -3418,7 +3534,7 @@ remote_start_remote (int from_tty, struct target_ops *target, int extended_p) |
supported for non-stop; it could be, but it is tricky if |
there are no stopped threads when we connect. */ |
if (remote_read_description_p (target) |
- && gdbarch_target_desc (target_gdbarch) == NULL) |
+ && gdbarch_target_desc (target_gdbarch ()) == NULL) |
{ |
target_clear_description (); |
target_find_description (); |
@@ -3448,19 +3564,13 @@ remote_start_remote (int from_tty, struct target_ops *target, int extended_p) |
mechanism. */ |
if (strcmp (rs->buf, "OK") != 0) |
{ |
- struct stop_reply *stop_reply; |
- struct cleanup *old_chain; |
+ struct notif_client *notif = ¬if_client_stop; |
- stop_reply = stop_reply_xmalloc (); |
- old_chain = make_cleanup (do_stop_reply_xfree, stop_reply); |
- |
- remote_parse_stop_reply (rs->buf, stop_reply); |
- discard_cleanups (old_chain); |
- |
- /* get_pending_stop_replies acks this one, and gets the rest |
- out. */ |
- pending_stop_reply = stop_reply; |
- remote_get_pending_stop_replies (); |
+ /* remote_notif_get_pending_replies acks this one, and gets |
+ the rest out. */ |
+ rs->notif_state->pending_event[notif_client_stop.id] |
+ = remote_notif_parse (notif, rs->buf); |
+ remote_notif_get_pending_events (notif); |
/* Make sure that threads that were stopped remain |
stopped. */ |
@@ -3505,7 +3615,7 @@ remote_start_remote (int from_tty, struct target_ops *target, int extended_p) |
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 |
@@ -3513,18 +3623,10 @@ remote_start_remote (int from_tty, struct target_ops *target, int extended_p) |
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); |
@@ -3537,7 +3639,7 @@ remote_start_remote (int from_tty, struct target_ops *target, int extended_p) |
rs->starting_up = 0; |
/* If breakpoints are global, insert them now. */ |
- if (gdbarch_has_global_breakpoints (target_gdbarch) |
+ if (gdbarch_has_global_breakpoints (target_gdbarch ()) |
&& breakpoints_always_inserted_mode ()) |
insert_breakpoints (); |
} |
@@ -3574,7 +3676,7 @@ init_all_packet_configs (void) |
/* 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; |
@@ -3617,12 +3719,12 @@ remote_check_symbols (struct objfile *objfile) |
xsnprintf (msg, get_remote_packet_size (), "qSymbol::%s", &reply[8]); |
else |
{ |
- int addr_size = gdbarch_addr_bit (target_gdbarch) / 8; |
+ int addr_size = gdbarch_addr_bit (target_gdbarch ()) / 8; |
CORE_ADDR sym_addr = SYMBOL_VALUE_ADDRESS (sym); |
/* If this is a function address, return the start of code |
instead of any data function descriptor. */ |
- sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch, |
+ sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch (), |
sym_addr, |
¤t_target); |
@@ -3877,7 +3979,17 @@ remote_string_tracing_feature (const struct protocol_feature *feature, |
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 }, |
@@ -3887,6 +3999,8 @@ static struct protocol_feature remote_protocol_features[] = { |
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, |
@@ -3942,8 +4056,14 @@ static struct protocol_feature remote_protocol_features[] = { |
{ "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; |
@@ -4130,6 +4250,14 @@ remote_query_supported (void) |
} |
} |
+/* 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, |
@@ -4147,66 +4275,54 @@ 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. */ |
- if (remote_desc != NULL && !have_inferiors ()) |
- { |
- if (!from_tty |
- || query (_("Already connected to a remote target. Disconnect? "))) |
- pop_target (); |
- else |
+ Ask this question first, before target_preopen has a chance to kill |
+ anything. */ |
+ if (rs->remote_desc != NULL && !have_inferiors ()) |
+ { |
+ 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; |
+ xfree (rs->last_pass_packet); |
+ rs->last_pass_packet = NULL; |
/* Make sure we send the program signals list the next time we |
resume. */ |
- xfree (last_program_signals_packet); |
- last_program_signals_packet = NULL; |
+ xfree (rs->last_program_signals_packet); |
+ rs->last_program_signals_packet = NULL; |
remote_fileio_reset (); |
reopen_exec_file (); |
reread_symbols (); |
- remote_desc = remote_serial_open (name); |
- if (!remote_desc) |
+ rs->remote_desc = remote_serial_open (name); |
+ if (!rs->remote_desc) |
perror_with_name (name); |
if (baud_rate != -1) |
{ |
- if (serial_setbaudrate (remote_desc, baud_rate)) |
+ if (serial_setbaudrate (rs->remote_desc, baud_rate)) |
{ |
/* The requested speed could not be set. Error out to |
top level after closing remote_desc. Take care to |
set remote_desc to NULL to avoid closing remote_desc |
more than once. */ |
- serial_close (remote_desc); |
- remote_desc = NULL; |
+ serial_close (rs->remote_desc); |
+ rs->remote_desc = NULL; |
perror_with_name (name); |
} |
} |
- serial_raw (remote_desc); |
+ serial_raw (rs->remote_desc); |
/* If there is something sitting in the buffer we might take it as a |
response to a command, which would be bad. */ |
- serial_flush_input (remote_desc); |
+ serial_flush_input (rs->remote_desc); |
if (from_tty) |
{ |
@@ -4220,9 +4336,7 @@ remote_open_1 (char *name, int from_tty, |
remote_async_inferior_event_token |
= create_async_event_handler (remote_async_inferior_event_handler, |
NULL); |
- remote_async_get_pending_events_token |
- = create_async_event_handler (remote_async_get_pending_events_handler, |
- NULL); |
+ rs->notif_state = remote_notif_state_allocate (); |
/* Reset the target state; these things will be queried either by |
remote_query_supported or as they are needed. */ |
@@ -4236,13 +4350,13 @@ remote_open_1 (char *name, int from_tty, |
rs->waiting_for_stop_reply = 0; |
rs->ctrlc_pending_p = 0; |
- general_thread = not_sent_ptid; |
- continue_thread = not_sent_ptid; |
- remote_traceframe_number = -1; |
+ rs->general_thread = not_sent_ptid; |
+ rs->continue_thread = not_sent_ptid; |
+ rs->remote_traceframe_number = -1; |
/* Probe for ability to use "ThreadInfo" query, as required. */ |
- use_threadinfo_query = 1; |
- use_threadextra_query = 1; |
+ rs->use_threadinfo_query = 1; |
+ rs->use_threadextra_query = 1; |
if (target_async_permitted) |
{ |
@@ -4291,8 +4405,8 @@ remote_open_1 (char *name, int from_tty, |
{ |
/* Pop the partially set up target - unless something else did |
already before throwing the exception. */ |
- if (remote_desc != NULL) |
- pop_target (); |
+ if (rs->remote_desc != NULL) |
+ remote_unpush_target (); |
if (target_async_permitted) |
wait_forever_enabled_p = 1; |
throw_exception (ex); |
@@ -4309,7 +4423,7 @@ remote_open_1 (char *name, int from_tty, |
die when it hits one. */ |
static void |
-remote_detach_1 (char *args, int from_tty, int extended) |
+remote_detach_1 (const char *args, int from_tty, int extended) |
{ |
int pid = ptid_get_pid (inferior_ptid); |
struct remote_state *rs = get_remote_state (); |
@@ -4349,18 +4463,17 @@ remote_detach_1 (char *args, int from_tty, int extended) |
if (from_tty && !extended) |
puts_filtered (_("Ending remote debugging.\n")); |
- discard_pending_stop_replies (pid); |
target_mourn_inferior (); |
} |
static void |
-remote_detach (struct target_ops *ops, char *args, int from_tty) |
+remote_detach (struct target_ops *ops, const char *args, int from_tty) |
{ |
remote_detach_1 (args, from_tty, 0); |
} |
static void |
-extended_remote_detach (struct target_ops *ops, char *args, int from_tty) |
+extended_remote_detach (struct target_ops *ops, const char *args, int from_tty) |
{ |
remote_detach_1 (args, from_tty, 1); |
} |
@@ -4456,7 +4569,7 @@ extended_remote_attach_1 (struct target_ops *target, char *args, int from_tty) |
inferior_ptid = pid_to_ptid (pid); |
/* Invalidate our notion of the remote current thread. */ |
- record_currthread (minus_one_ptid); |
+ record_currthread (rs, minus_one_ptid); |
} |
else |
{ |
@@ -4478,14 +4591,10 @@ extended_remote_attach_1 (struct target_ops *target, char *args, int from_tty) |
if (target_can_async_p ()) |
{ |
- struct stop_reply *stop_reply; |
- struct cleanup *old_chain; |
+ struct notif_event *reply |
+ = remote_notif_parse (¬if_client_stop, wait_status); |
- stop_reply = stop_reply_xmalloc (); |
- old_chain = make_cleanup (do_stop_reply_xfree, stop_reply); |
- remote_parse_stop_reply (wait_status, stop_reply); |
- discard_cleanups (old_chain); |
- push_stop_reply (stop_reply); |
+ push_stop_reply ((struct stop_reply *) reply); |
target_async (inferior_event_handler, 0); |
} |
@@ -4592,7 +4701,8 @@ remote_vcont_probe (struct remote_state *rs) |
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++; |
@@ -4605,7 +4715,9 @@ remote_vcont_probe (struct remote_state *rs) |
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, ';'); |
} |
@@ -4637,6 +4749,42 @@ append_resumption (char *p, char *endp, |
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) |
@@ -4768,10 +4916,6 @@ remote_vcont_resume (ptid_t ptid, int step, enum gdb_signal siggnal) |
/* Tell the remote machine to resume. */ |
-static enum gdb_signal last_sent_signal = GDB_SIGNAL_0; |
- |
-static int last_sent_step; |
- |
static void |
remote_resume (struct target_ops *ops, |
ptid_t ptid, int step, enum gdb_signal siggnal) |
@@ -4779,8 +4923,17 @@ remote_resume (struct target_ops *ops, |
struct remote_state *rs = get_remote_state (); |
char *buf; |
- last_sent_signal = siggnal; |
- last_sent_step = step; |
+ /* In all-stop, we can't mark REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN |
+ (explained in remote-notif.c:handle_notification) so |
+ remote_notif_process is not called. We need find a place where |
+ it is safe to start a 'vNotif' sequence. It is good to do it |
+ before resuming inferior, because inferior was stopped and no RSP |
+ traffic at that moment. */ |
+ if (!non_stop) |
+ remote_notif_process (rs->notif_state, ¬if_client_stop); |
+ |
+ rs->last_sent_signal = siggnal; |
+ rs->last_sent_step = step; |
/* The vCont packet doesn't need to specify threads via Hc. */ |
/* No reverse support (yet) for vCont. */ |
@@ -4850,27 +5003,27 @@ remote_resume (struct target_ops *ops, |
/* 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_wrapper (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_wrapper (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 |
@@ -4886,7 +5039,7 @@ async_remote_interrupt (gdb_client_data arg) |
/* 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) |
@@ -4898,7 +5051,7 @@ async_remote_interrupt_twice (gdb_client_data arg) |
/* 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); |
} |
@@ -4913,22 +5066,22 @@ static void (*ofunc) (int); |
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 |
@@ -4945,7 +5098,7 @@ remote_stop_ns (ptid_t ptid) |
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) |
@@ -5029,15 +5182,15 @@ interrupt_query (void) |
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 (); |
} |
} |
@@ -5066,7 +5219,7 @@ remote_terminal_inferior (void) |
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. */ |
@@ -5082,7 +5235,7 @@ remote_terminal_ours (void) |
/* 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; |
} |
@@ -5112,12 +5265,18 @@ typedef struct cached_reg |
DEF_VEC_O(cached_reg_t); |
-struct stop_reply |
+typedef struct stop_reply |
{ |
- struct stop_reply *next; |
+ struct notif_event base; |
+ /* The identifier of the thread about this event */ |
ptid_t ptid; |
+ /* The remote state this event is associated with. When the remote |
+ connection, represented by a remote_state object, is closed, |
+ all the associated stop_reply events should be released. */ |
+ struct remote_state *rs; |
+ |
struct target_waitstatus ws; |
/* Expedited registers. This makes remote debugging a bit more |
@@ -5129,79 +5288,231 @@ struct stop_reply |
int stopped_by_watchpoint_p; |
CORE_ADDR watch_data_address; |
- int solibs_changed; |
- int replay_event; |
- |
int core; |
-}; |
+} *stop_reply_p; |
-/* The list of already fetched and acknowledged stop events. */ |
-static struct stop_reply *stop_reply_queue; |
+DECLARE_QUEUE_P (stop_reply_p); |
+DEFINE_QUEUE_P (stop_reply_p); |
+/* The list of already fetched and acknowledged stop events. This |
+ queue is used for notification Stop, and other notifications |
+ don't need queue for their events, because the notification events |
+ of Stop can't be consumed immediately, so that events should be |
+ queued first, and be consumed by remote_wait_{ns,as} one per |
+ time. Other notifications can consume their events immediately, |
+ so queue is not needed for them. */ |
+static QUEUE (stop_reply_p) *stop_reply_queue; |
-static struct stop_reply * |
-stop_reply_xmalloc (void) |
+static void |
+stop_reply_xfree (struct stop_reply *r) |
{ |
- struct stop_reply *r = XMALLOC (struct stop_reply); |
+ notif_event_xfree ((struct notif_event *) r); |
+} |
- r->next = NULL; |
- return r; |
+static void |
+remote_notif_stop_parse (struct notif_client *self, char *buf, |
+ struct notif_event *event) |
+{ |
+ remote_parse_stop_reply (buf, (struct stop_reply *) event); |
} |
static void |
-stop_reply_xfree (struct stop_reply *r) |
+remote_notif_stop_ack (struct notif_client *self, char *buf, |
+ struct notif_event *event) |
+{ |
+ struct stop_reply *stop_reply = (struct stop_reply *) event; |
+ |
+ /* acknowledge */ |
+ putpkt ((char *) self->ack_command); |
+ |
+ if (stop_reply->ws.kind == TARGET_WAITKIND_IGNORE) |
+ /* We got an unknown stop reply. */ |
+ error (_("Unknown stop reply")); |
+ |
+ push_stop_reply (stop_reply); |
+} |
+ |
+static int |
+remote_notif_stop_can_get_pending_events (struct notif_client *self) |
+{ |
+ /* We can't get pending events in remote_notif_process for |
+ notification stop, and we have to do this in remote_wait_ns |
+ instead. If we fetch all queued events from stub, remote stub |
+ may exit and we have no chance to process them back in |
+ remote_wait_ns. */ |
+ mark_async_event_handler (remote_async_inferior_event_token); |
+ return 0; |
+} |
+ |
+static void |
+stop_reply_dtr (struct notif_event *event) |
+{ |
+ struct stop_reply *r = (struct stop_reply *) event; |
+ |
+ VEC_free (cached_reg_t, r->regcache); |
+} |
+ |
+static struct notif_event * |
+remote_notif_stop_alloc_reply (void) |
+{ |
+ struct notif_event *r |
+ = (struct notif_event *) XMALLOC (struct stop_reply); |
+ |
+ r->dtr = stop_reply_dtr; |
+ |
+ return r; |
+} |
+ |
+/* A client of notification Stop. */ |
+ |
+struct notif_client notif_client_stop = |
+{ |
+ "Stop", |
+ "vStopped", |
+ remote_notif_stop_parse, |
+ remote_notif_stop_ack, |
+ remote_notif_stop_can_get_pending_events, |
+ remote_notif_stop_alloc_reply, |
+ REMOTE_NOTIF_STOP, |
+}; |
+ |
+/* A parameter to pass data in and out. */ |
+ |
+struct queue_iter_param |
{ |
- if (r != NULL) |
+ void *input; |
+ struct stop_reply *output; |
+}; |
+ |
+/* Remove stop replies in the queue if its pid is equal to the given |
+ inferior's pid. */ |
+ |
+static int |
+remove_stop_reply_for_inferior (QUEUE (stop_reply_p) *q, |
+ QUEUE_ITER (stop_reply_p) *iter, |
+ stop_reply_p event, |
+ void *data) |
+{ |
+ struct queue_iter_param *param = data; |
+ struct inferior *inf = param->input; |
+ |
+ if (ptid_get_pid (event->ptid) == inf->pid) |
{ |
- VEC_free (cached_reg_t, r->regcache); |
- xfree (r); |
+ stop_reply_xfree (event); |
+ QUEUE_remove_elem (stop_reply_p, q, iter); |
} |
+ |
+ return 1; |
} |
-/* Discard all pending stop replies of inferior PID. If PID is -1, |
- discard everything. */ |
+/* Discard all pending stop replies of inferior INF. */ |
static void |
-discard_pending_stop_replies (int pid) |
+discard_pending_stop_replies (struct inferior *inf) |
{ |
- struct stop_reply *prev = NULL, *reply, *next; |
+ int i; |
+ struct queue_iter_param param; |
+ struct stop_reply *reply; |
+ struct remote_state *rs = get_remote_state (); |
+ struct remote_notif_state *rns = rs->notif_state; |
+ |
+ /* This function can be notified when an inferior exists. When the |
+ target is not remote, the notification state is NULL. */ |
+ if (rs->remote_desc == NULL) |
+ return; |
+ |
+ reply = (struct stop_reply *) rns->pending_event[notif_client_stop.id]; |
/* Discard the in-flight notification. */ |
- if (pending_stop_reply != NULL |
- && (pid == -1 |
- || ptid_get_pid (pending_stop_reply->ptid) == pid)) |
+ if (reply != NULL && ptid_get_pid (reply->ptid) == inf->pid) |
{ |
- stop_reply_xfree (pending_stop_reply); |
- pending_stop_reply = NULL; |
+ stop_reply_xfree (reply); |
+ rns->pending_event[notif_client_stop.id] = NULL; |
} |
+ param.input = inf; |
+ param.output = NULL; |
/* Discard the stop replies we have already pulled with |
vStopped. */ |
- for (reply = stop_reply_queue; reply; reply = next) |
- { |
- next = reply->next; |
- if (pid == -1 |
- || ptid_get_pid (reply->ptid) == pid) |
- { |
- if (reply == stop_reply_queue) |
- stop_reply_queue = reply->next; |
- else |
- prev->next = reply->next; |
+ QUEUE_iterate (stop_reply_p, stop_reply_queue, |
+ remove_stop_reply_for_inferior, ¶m); |
+} |
- stop_reply_xfree (reply); |
- } |
- else |
- prev = reply; |
+/* If its remote state is equal to the given remote state, |
+ remove EVENT from the stop reply queue. */ |
+ |
+static int |
+remove_stop_reply_of_remote_state (QUEUE (stop_reply_p) *q, |
+ QUEUE_ITER (stop_reply_p) *iter, |
+ stop_reply_p event, |
+ void *data) |
+{ |
+ struct queue_iter_param *param = data; |
+ struct remote_state *rs = param->input; |
+ |
+ if (event->rs == rs) |
+ { |
+ stop_reply_xfree (event); |
+ QUEUE_remove_elem (stop_reply_p, q, iter); |
} |
+ |
+ return 1; |
} |
-/* Cleanup wrapper. */ |
+/* Discard the stop replies for RS in stop_reply_queue. */ |
static void |
-do_stop_reply_xfree (void *arg) |
+discard_pending_stop_replies_in_queue (struct remote_state *rs) |
+{ |
+ struct queue_iter_param param; |
+ |
+ param.input = rs; |
+ param.output = NULL; |
+ /* Discard the stop replies we have already pulled with |
+ vStopped. */ |
+ QUEUE_iterate (stop_reply_p, stop_reply_queue, |
+ remove_stop_reply_of_remote_state, ¶m); |
+} |
+ |
+/* A parameter to pass data in and out. */ |
+ |
+static int |
+remote_notif_remove_once_on_match (QUEUE (stop_reply_p) *q, |
+ QUEUE_ITER (stop_reply_p) *iter, |
+ stop_reply_p event, |
+ void *data) |
+{ |
+ struct queue_iter_param *param = data; |
+ ptid_t *ptid = param->input; |
+ |
+ if (ptid_match (event->ptid, *ptid)) |
+ { |
+ param->output = event; |
+ QUEUE_remove_elem (stop_reply_p, q, iter); |
+ return 0; |
+ } |
+ |
+ return 1; |
+} |
+ |
+/* Remove the first reply in 'stop_reply_queue' which matches |
+ PTID. */ |
+ |
+static struct stop_reply * |
+remote_notif_remove_queued_reply (ptid_t ptid) |
{ |
- struct stop_reply *r = arg; |
+ struct queue_iter_param param; |
+ |
+ param.input = &ptid; |
+ param.output = NULL; |
- stop_reply_xfree (r); |
+ QUEUE_iterate (stop_reply_p, stop_reply_queue, |
+ remote_notif_remove_once_on_match, ¶m); |
+ if (notif_debug) |
+ fprintf_unfiltered (gdb_stdlog, |
+ "notif: discard queued event: 'Stop' in %s\n", |
+ target_pid_to_str (ptid)); |
+ |
+ return param.output; |
} |
/* Look for a queued stop reply belonging to PTID. If one is found, |
@@ -5212,29 +5523,13 @@ do_stop_reply_xfree (void *arg) |
static struct stop_reply * |
queued_stop_reply (ptid_t ptid) |
{ |
- struct stop_reply *it; |
- struct stop_reply **it_link; |
- |
- it = stop_reply_queue; |
- it_link = &stop_reply_queue; |
- while (it) |
- { |
- if (ptid_match (it->ptid, ptid)) |
- { |
- *it_link = it->next; |
- it->next = NULL; |
- break; |
- } |
+ struct stop_reply *r = remote_notif_remove_queued_reply (ptid); |
- it_link = &it->next; |
- it = *it_link; |
- } |
- |
- if (stop_reply_queue) |
+ if (!QUEUE_is_empty (stop_reply_p, stop_reply_queue)) |
/* There's still at least an event left. */ |
mark_async_event_handler (remote_async_inferior_event_token); |
- return it; |
+ return r; |
} |
/* Push a fully parsed stop reply in the stop reply queue. Since we |
@@ -5244,38 +5539,37 @@ queued_stop_reply (ptid_t ptid) |
static void |
push_stop_reply (struct stop_reply *new_event) |
{ |
- struct stop_reply *event; |
+ QUEUE_enque (stop_reply_p, stop_reply_queue, new_event); |
- if (stop_reply_queue) |
- { |
- for (event = stop_reply_queue; |
- event && event->next; |
- event = event->next) |
- ; |
- |
- event->next = new_event; |
- } |
- else |
- stop_reply_queue = new_event; |
+ if (notif_debug) |
+ fprintf_unfiltered (gdb_stdlog, |
+ "notif: push 'Stop' %s to queue %d\n", |
+ target_pid_to_str (new_event->ptid), |
+ QUEUE_length (stop_reply_p, |
+ stop_reply_queue)); |
mark_async_event_handler (remote_async_inferior_event_token); |
} |
+static int |
+stop_reply_match_ptid_and_ws (QUEUE (stop_reply_p) *q, |
+ QUEUE_ITER (stop_reply_p) *iter, |
+ struct stop_reply *event, |
+ void *data) |
+{ |
+ ptid_t *ptid = data; |
+ |
+ return !(ptid_equal (*ptid, event->ptid) |
+ && event->ws.kind == TARGET_WAITKIND_STOPPED); |
+} |
+ |
/* Returns true if we have a stop reply for PTID. */ |
static int |
peek_stop_reply (ptid_t ptid) |
{ |
- struct stop_reply *it; |
- |
- for (it = stop_reply_queue; it; it = it->next) |
- if (ptid_equal (ptid, it->ptid)) |
- { |
- if (it->ws.kind == TARGET_WAITKIND_STOPPED) |
- return 1; |
- } |
- |
- return 0; |
+ return !QUEUE_iterate (stop_reply_p, stop_reply_queue, |
+ stop_reply_match_ptid_and_ws, &ptid); |
} |
/* Parse the stop reply in BUF. Either the function succeeds, and the |
@@ -5289,10 +5583,9 @@ remote_parse_stop_reply (char *buf, struct stop_reply *event) |
char *p; |
event->ptid = null_ptid; |
+ event->rs = get_remote_state (); |
event->ws.kind = TARGET_WAITKIND_IGNORE; |
event->ws.value.integer = 0; |
- event->solibs_changed = 0; |
- event->replay_event = 0; |
event->stopped_by_watchpoint_p = 0; |
event->regcache = NULL; |
event->core = -1; |
@@ -5356,15 +5649,14 @@ Packet: '%s'\n"), |
while (*p_temp && *p_temp != ';') |
p_temp++; |
- event->solibs_changed = 1; |
+ event->ws.kind = TARGET_WAITKIND_LOADED; |
p = p_temp; |
} |
else if (strncmp (p, "replaylog", p1 - p) == 0) |
{ |
- /* NO_HISTORY event. |
- p1 will indicate "begin" or "end", but |
- it makes no difference for now, so ignore it. */ |
- event->replay_event = 1; |
+ 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; |
@@ -5405,10 +5697,10 @@ Packet: '%s'\n"), |
cached_reg.num = reg->regnum; |
fieldsize = hex2bin (p, cached_reg.data, |
- register_size (target_gdbarch, |
+ register_size (target_gdbarch (), |
reg->regnum)); |
p += 2 * fieldsize; |
- if (fieldsize < register_size (target_gdbarch, |
+ if (fieldsize < register_size (target_gdbarch (), |
reg->regnum)) |
warning (_("Remote reply is too short: %s"), buf); |
@@ -5420,18 +5712,22 @@ Packet: '%s'\n"), |
buf, p); |
++p; |
} |
+ |
+ if (event->ws.kind != TARGET_WAITKIND_IGNORE) |
+ break; |
+ |
/* fall through */ |
case 'S': /* Old style status, just signal only. */ |
- if (event->solibs_changed) |
- event->ws.kind = TARGET_WAITKIND_LOADED; |
- else if (event->replay_event) |
- event->ws.kind = TARGET_WAITKIND_NO_HISTORY; |
- else |
- { |
- event->ws.kind = TARGET_WAITKIND_STOPPED; |
- event->ws.value.sig = (enum gdb_signal) |
- (((fromhex (buf[1])) << 4) + (fromhex (buf[2]))); |
- } |
+ { |
+ int sig; |
+ |
+ event->ws.kind = TARGET_WAITKIND_STOPPED; |
+ sig = (fromhex (buf[1]) << 4) + fromhex (buf[2]); |
+ if (GDB_SIGNAL_FIRST <= sig && sig < GDB_SIGNAL_LAST) |
+ event->ws.value.sig = (enum gdb_signal) sig; |
+ else |
+ event->ws.value.sig = GDB_SIGNAL_UNKNOWN; |
+ } |
break; |
case 'W': /* Target exited. */ |
case 'X': |
@@ -5455,7 +5751,10 @@ Packet: '%s'\n"), |
{ |
/* The remote process exited with a signal. */ |
event->ws.kind = TARGET_WAITKIND_SIGNALLED; |
- event->ws.value.sig = (enum gdb_signal) value; |
+ if (GDB_SIGNAL_FIRST <= value && value < GDB_SIGNAL_LAST) |
+ event->ws.value.sig = (enum gdb_signal) value; |
+ else |
+ event->ws.value.sig = GDB_SIGNAL_UNKNOWN; |
} |
/* If no process is specified, assume inferior_ptid. */ |
@@ -5491,13 +5790,14 @@ Packet: '%s'\n"), |
error (_("No process or thread specified in stop reply: %s"), buf); |
} |
-/* When the stub wants to tell GDB about a new stop reply, it sends a |
- stop notification (%Stop). Those can come it at any time, hence, |
- we have to make sure that any pending putpkt/getpkt sequence we're |
- making is finished, before querying the stub for more events with |
- vStopped. E.g., if we started a vStopped sequence immediatelly |
- upon receiving the %Stop notification, something like this could |
- happen: |
+/* When the stub wants to tell GDB about a new notification reply, it |
+ sends a notification (%Stop, for example). Those can come it at |
+ any time, hence, we have to make sure that any pending |
+ putpkt/getpkt sequence we're making is finished, before querying |
+ the stub for more events with the corresponding ack command |
+ (vStopped, for example). E.g., if we started a vStopped sequence |
+ immediately upon receiving the notification, something like this |
+ could happen: |
1.1) --> Hg 1 |
1.2) <-- OK |
@@ -5509,7 +5809,7 @@ Packet: '%s'\n"), |
Obviously, the reply in step #1.6 would be unexpected to a vStopped |
query. |
- To solve this, whenever we parse a %Stop notification sucessfully, |
+ To solve this, whenever we parse a %Stop notification successfully, |
we mark the REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN, and carry on |
doing whatever we were doing: |
@@ -5532,19 +5832,21 @@ Packet: '%s'\n"), |
2.9) --> OK |
*/ |
-static void |
-remote_get_pending_stop_replies (void) |
+void |
+remote_notif_get_pending_events (struct notif_client *nc) |
{ |
struct remote_state *rs = get_remote_state (); |
- if (pending_stop_reply) |
+ if (rs->notif_state->pending_event[nc->id] != NULL) |
{ |
- /* acknowledge */ |
- putpkt ("vStopped"); |
+ if (notif_debug) |
+ fprintf_unfiltered (gdb_stdlog, |
+ "notif: process: '%s' ack pending event\n", |
+ nc->name); |
- /* Now we can rely on it. */ |
- push_stop_reply (pending_stop_reply); |
- pending_stop_reply = NULL; |
+ /* acknowledge */ |
+ nc->ack (nc, rs->buf, rs->notif_state->pending_event[nc->id]); |
+ rs->notif_state->pending_event[nc->id] = NULL; |
while (1) |
{ |
@@ -5552,31 +5854,18 @@ remote_get_pending_stop_replies (void) |
if (strcmp (rs->buf, "OK") == 0) |
break; |
else |
- { |
- struct cleanup *old_chain; |
- struct stop_reply *stop_reply = stop_reply_xmalloc (); |
- |
- old_chain = make_cleanup (do_stop_reply_xfree, stop_reply); |
- remote_parse_stop_reply (rs->buf, stop_reply); |
- |
- /* acknowledge */ |
- putpkt ("vStopped"); |
- |
- if (stop_reply->ws.kind != TARGET_WAITKIND_IGNORE) |
- { |
- /* Now we can rely on it. */ |
- discard_cleanups (old_chain); |
- push_stop_reply (stop_reply); |
- } |
- else |
- /* We got an unknown stop reply. */ |
- do_cleanups (old_chain); |
- } |
+ remote_notif_ack (nc, rs->buf); |
} |
} |
+ else |
+ { |
+ if (notif_debug) |
+ fprintf_unfiltered (gdb_stdlog, |
+ "notif: process: '%s' no pending reply\n", |
+ nc->name); |
+ } |
} |
- |
/* Called when it is decided that STOP_REPLY holds the info of the |
event that is to be returned to the core. This function always |
destroys STOP_REPLY. */ |
@@ -5598,11 +5887,13 @@ process_stop_reply (struct stop_reply *stop_reply, |
if (status->kind != TARGET_WAITKIND_EXITED |
&& status->kind != TARGET_WAITKIND_SIGNALLED) |
{ |
+ struct remote_state *rs = get_remote_state (); |
+ |
/* Expedited registers. */ |
if (stop_reply->regcache) |
{ |
struct regcache *regcache |
- = get_thread_arch_regcache (ptid, target_gdbarch); |
+ = get_thread_arch_regcache (ptid, target_gdbarch ()); |
cached_reg_t *reg; |
int ix; |
@@ -5613,8 +5904,8 @@ process_stop_reply (struct stop_reply *stop_reply, |
VEC_free (cached_reg_t, stop_reply->regcache); |
} |
- remote_stopped_by_watchpoint_p = stop_reply->stopped_by_watchpoint_p; |
- remote_watch_data_address = stop_reply->watch_data_address; |
+ rs->remote_stopped_by_watchpoint_p = stop_reply->stopped_by_watchpoint_p; |
+ rs->remote_watch_data_address = stop_reply->watch_data_address; |
remote_notice_new_inferior (ptid, 0); |
demand_private_info (ptid)->core = stop_reply->core; |
@@ -5632,15 +5923,16 @@ remote_wait_ns (ptid_t ptid, struct target_waitstatus *status, int options) |
struct remote_state *rs = get_remote_state (); |
struct stop_reply *stop_reply; |
int ret; |
+ int is_notif = 0; |
/* If in non-stop mode, get out of getpkt even if a |
notification is received. */ |
ret = getpkt_or_notif_sane (&rs->buf, &rs->buf_size, |
- 0 /* forever */); |
+ 0 /* forever */, &is_notif); |
while (1) |
{ |
- if (ret != -1) |
+ if (ret != -1 && !is_notif) |
switch (rs->buf[0]) |
{ |
case 'E': /* Error of some sort. */ |
@@ -5659,8 +5951,8 @@ remote_wait_ns (ptid_t ptid, struct target_waitstatus *status, int options) |
/* Acknowledge a pending stop reply that may have arrived in the |
mean time. */ |
- if (pending_stop_reply != NULL) |
- remote_get_pending_stop_replies (); |
+ if (rs->notif_state->pending_event[notif_client_stop.id] != NULL) |
+ remote_notif_get_pending_events (¬if_client_stop); |
/* If indeed we noticed a stop reply, we're done. */ |
stop_reply = queued_stop_reply (ptid); |
@@ -5677,7 +5969,7 @@ remote_wait_ns (ptid_t ptid, struct target_waitstatus *status, int options) |
/* Otherwise do a blocking wait. */ |
ret = getpkt_or_notif_sane (&rs->buf, &rs->buf_size, |
- 1 /* forever */); |
+ 1 /* forever */, &is_notif); |
} |
} |
@@ -5707,16 +5999,17 @@ remote_wait_as (ptid_t ptid, struct target_waitstatus *status, int options) |
else |
{ |
int ret; |
+ int is_notif; |
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 (quit_flag) |
+ if (check_quit_flag ()) |
{ |
- quit_flag = 0; |
- remote_interrupt (SIGINT); |
+ clear_quit_flag (); |
+ sync_remote_interrupt (SIGINT); |
} |
} |
@@ -5724,14 +6017,21 @@ remote_wait_as (ptid_t ptid, struct target_waitstatus *status, int options) |
_never_ wait for ever -> test on target_is_async_p(). |
However, before we do that we need to ensure that the caller |
knows how to take the target into/out of async mode. */ |
- ret = getpkt_sane (&rs->buf, &rs->buf_size, wait_forever_enabled_p); |
+ 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; |
} |
buf = rs->buf; |
- remote_stopped_by_watchpoint_p = 0; |
+ rs->remote_stopped_by_watchpoint_p = 0; |
/* We got something. */ |
rs->waiting_for_stop_reply = 0; |
@@ -5756,13 +6056,10 @@ remote_wait_as (ptid_t ptid, struct target_waitstatus *status, int options) |
break; |
case 'T': case 'S': case 'X': case 'W': |
{ |
- struct stop_reply *stop_reply; |
- struct cleanup *old_chain; |
+ struct stop_reply *stop_reply |
+ = (struct stop_reply *) remote_notif_parse (¬if_client_stop, |
+ rs->buf); |
- stop_reply = stop_reply_xmalloc (); |
- old_chain = make_cleanup (do_stop_reply_xfree, stop_reply); |
- remote_parse_stop_reply (buf, stop_reply); |
- discard_cleanups (old_chain); |
event_ptid = process_stop_reply (stop_reply, status); |
break; |
} |
@@ -5774,18 +6071,18 @@ remote_wait_as (ptid_t ptid, struct target_waitstatus *status, int options) |
break; |
case '\0': |
- if (last_sent_signal != GDB_SIGNAL_0) |
+ if (rs->last_sent_signal != GDB_SIGNAL_0) |
{ |
/* Zero length reply means that we tried 'S' or 'C' and the |
remote system doesn't support it. */ |
target_terminal_ours_for_output (); |
printf_filtered |
("Can't send signals to this remote system. %s not sent.\n", |
- gdb_signal_to_name (last_sent_signal)); |
- last_sent_signal = GDB_SIGNAL_0; |
+ gdb_signal_to_name (rs->last_sent_signal)); |
+ rs->last_sent_signal = GDB_SIGNAL_0; |
target_terminal_inferior (); |
- strcpy ((char *) buf, last_sent_step ? "s" : "c"); |
+ strcpy ((char *) buf, rs->last_sent_step ? "s" : "c"); |
putpkt ((char *) buf); |
/* We just told the target to resume, so a stop reply is in |
@@ -5814,13 +6111,13 @@ remote_wait_as (ptid_t ptid, struct target_waitstatus *status, int options) |
&& status->kind != TARGET_WAITKIND_SIGNALLED) |
{ |
if (!ptid_equal (event_ptid, null_ptid)) |
- record_currthread (event_ptid); |
+ record_currthread (rs, event_ptid); |
else |
event_ptid = inferior_ptid; |
} |
else |
/* A process exit. Invalidate our notion of current thread. */ |
- record_currthread (minus_one_ptid); |
+ record_currthread (rs, minus_one_ptid); |
return event_ptid; |
} |
@@ -5843,7 +6140,7 @@ remote_wait (struct target_ops *ops, |
{ |
/* If there are are events left in the queue tell the event loop |
to return here. */ |
- if (stop_reply_queue) |
+ if (!QUEUE_is_empty (stop_reply_p, stop_reply_queue)) |
mark_async_event_handler (remote_async_inferior_event_token); |
} |
@@ -6048,12 +6345,13 @@ static void |
set_remote_traceframe (void) |
{ |
int newnum; |
+ struct remote_state *rs = get_remote_state (); |
- if (remote_traceframe_number == get_traceframe_number ()) |
+ if (rs->remote_traceframe_number == get_traceframe_number ()) |
return; |
/* Avoid recursion, remote_trace_find calls us again. */ |
- remote_traceframe_number = get_traceframe_number (); |
+ rs->remote_traceframe_number = get_traceframe_number (); |
newnum = target_trace_find (tfind_number, |
get_traceframe_number (), 0, 0, NULL); |
@@ -6312,11 +6610,11 @@ hexnumnstr (char *buf, ULONGEST num, int width) |
static CORE_ADDR |
remote_address_masked (CORE_ADDR addr) |
{ |
- int address_size = remote_address_size; |
+ unsigned int address_size = remote_address_size; |
/* If "remoteaddresssize" was not set, default to target address size. */ |
if (!address_size) |
- address_size = gdbarch_addr_bit (target_gdbarch); |
+ address_size = gdbarch_addr_bit (target_gdbarch ()); |
if (address_size > 0 |
&& address_size < (sizeof (ULONGEST) * 8)) |
@@ -6490,10 +6788,11 @@ check_binary_download (CORE_ADDR addr) |
If USE_LENGTH is 0, then the <LENGTH> field and the preceding comma |
are omitted. |
- Returns the number of bytes transferred, or 0 (setting errno) for |
- error. Only transfer a single packet. */ |
+ Returns the number of bytes transferred, or a negative value (an |
+ 'enum target_xfer_error' value) for error. Only transfer a single |
+ packet. */ |
-static int |
+static LONGEST |
remote_write_bytes_aux (const char *header, CORE_ADDR memaddr, |
const gdb_byte *myaddr, ssize_t len, |
char packet_format, int use_length) |
@@ -6590,8 +6889,8 @@ remote_write_bytes_aux (const char *header, CORE_ADDR memaddr, |
/* 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 |
@@ -6604,7 +6903,7 @@ remote_write_bytes_aux (const char *header, CORE_ADDR memaddr, |
- 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); |
} |
@@ -6632,14 +6931,7 @@ remote_write_bytes_aux (const char *header, CORE_ADDR memaddr, |
getpkt (&rs->buf, &rs->buf_size, 0); |
if (rs->buf[0] == 'E') |
- { |
- /* There is no correspondance between what the remote protocol |
- uses for errors and errno codes. We would like a cleaner way |
- of representing errors (big enough to include errno codes, |
- bfd_error codes, and others). But for now just return EIO. */ |
- errno = EIO; |
- return 0; |
- } |
+ return TARGET_XFER_E_IO; |
/* Return NR_BYTES, not TODO, in case escape chars caused us to send |
fewer bytes than we'd planned. */ |
@@ -6652,10 +6944,11 @@ remote_write_bytes_aux (const char *header, CORE_ADDR memaddr, |
MYADDR is the address of the buffer in our space. |
LEN is the number of bytes. |
- Returns number of bytes transferred, or 0 (setting errno) for |
- error. Only transfer a single packet. */ |
+ Returns number of bytes transferred, or a negative value (an 'enum |
+ target_xfer_error' value) for error. Only transfer a single |
+ packet. */ |
-static int |
+static LONGEST |
remote_write_bytes (CORE_ADDR memaddr, const gdb_byte *myaddr, ssize_t len) |
{ |
char *packet_format = 0; |
@@ -6688,9 +6981,10 @@ remote_write_bytes (CORE_ADDR memaddr, const gdb_byte *myaddr, ssize_t len) |
MYADDR is the address of the buffer in our space. |
LEN is the number of bytes. |
- Returns number of bytes transferred, or 0 for error. */ |
+ Returns number of bytes transferred, or a negative value (an 'enum |
+ target_xfer_error' value) for error. */ |
-static int |
+static LONGEST |
remote_read_bytes (CORE_ADDR memaddr, gdb_byte *myaddr, int len) |
{ |
struct remote_state *rs = get_remote_state (); |
@@ -6722,15 +7016,7 @@ remote_read_bytes (CORE_ADDR memaddr, gdb_byte *myaddr, int len) |
if (rs->buf[0] == 'E' |
&& isxdigit (rs->buf[1]) && isxdigit (rs->buf[2]) |
&& rs->buf[3] == '\0') |
- { |
- /* There is no correspondance between what the remote protocol |
- uses for errors and errno codes. We would like a cleaner way |
- of representing errors (big enough to include errno codes, |
- bfd_error codes, and others). But for now just return |
- EIO. */ |
- errno = EIO; |
- return 0; |
- } |
+ return TARGET_XFER_E_IO; |
/* Reply describes memory byte by byte, each byte encoded as two hex |
characters. */ |
p = rs->buf; |
@@ -6738,75 +7024,8 @@ remote_read_bytes (CORE_ADDR memaddr, gdb_byte *myaddr, int len) |
/* Return what we have. Let higher layers handle partial reads. */ |
return i; |
} |
- |
- |
-/* Remote notification handler. */ |
- |
-static void |
-handle_notification (char *buf, size_t length) |
-{ |
- if (strncmp (buf, "Stop:", 5) == 0) |
- { |
- if (pending_stop_reply) |
- { |
- /* We've already parsed the in-flight stop-reply, but the |
- stub for some reason thought we didn't, possibly due to |
- timeout on its side. Just ignore it. */ |
- if (remote_debug) |
- fprintf_unfiltered (gdb_stdlog, "ignoring resent notification\n"); |
- } |
- else |
- { |
- struct cleanup *old_chain; |
- struct stop_reply *reply = stop_reply_xmalloc (); |
- |
- old_chain = make_cleanup (do_stop_reply_xfree, reply); |
- |
- remote_parse_stop_reply (buf + 5, reply); |
- |
- discard_cleanups (old_chain); |
- |
- /* Be careful to only set it after parsing, since an error |
- may be thrown then. */ |
- pending_stop_reply = reply; |
- |
- /* Notify the event loop there's a stop reply to acknowledge |
- and that there may be more events to fetch. */ |
- mark_async_event_handler (remote_async_get_pending_events_token); |
- |
- if (remote_debug) |
- fprintf_unfiltered (gdb_stdlog, "stop notification captured\n"); |
- } |
- } |
- else |
- /* We ignore notifications we don't recognize, for compatibility |
- with newer stubs. */ |
- ; |
-} |
-/* Read or write LEN bytes from inferior memory at MEMADDR, |
- transferring to or from debugger address BUFFER. Write to inferior |
- if SHOULD_WRITE is nonzero. Returns length of data written or |
- read; 0 for error. TARGET is unused. */ |
- |
-static int |
-remote_xfer_memory (CORE_ADDR mem_addr, gdb_byte *buffer, int mem_len, |
- int should_write, struct mem_attrib *attrib, |
- struct target_ops *target) |
-{ |
- int res; |
- |
- set_remote_traceframe (); |
- set_general_thread (inferior_ptid); |
- |
- if (should_write) |
- res = remote_write_bytes (mem_addr, buffer, mem_len); |
- else |
- res = remote_read_bytes (mem_addr, buffer, mem_len); |
- |
- return res; |
-} |
/* Sends a packet with content determined by the printf format string |
FORMAT and the remaining arguments, then gets the reply. Returns |
@@ -6851,7 +7070,7 @@ static void |
remote_flash_erase (struct target_ops *ops, |
ULONGEST address, LONGEST length) |
{ |
- int addr_size = gdbarch_addr_bit (target_gdbarch) / 8; |
+ int addr_size = gdbarch_addr_bit (target_gdbarch ()) / 8; |
int saved_remote_timeout = remote_timeout; |
enum packet_result ret; |
struct cleanup *back_to = make_cleanup (restore_remote_timeout, |
@@ -6881,7 +7100,7 @@ remote_flash_write (struct target_ops *ops, |
const gdb_byte *data) |
{ |
int saved_remote_timeout = remote_timeout; |
- int ret; |
+ LONGEST ret; |
struct cleanup *back_to = make_cleanup (restore_remote_timeout, |
&saved_remote_timeout); |
@@ -6924,14 +7143,31 @@ remote_files_info (struct target_ops *ignore) |
/* 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 |
readchar (int timeout) |
{ |
int ch; |
+ struct remote_state *rs = get_remote_state (); |
- ch = serial_readchar (remote_desc, timeout); |
+ ch = serial_readchar (rs->remote_desc, timeout); |
if (ch >= 0) |
return ch; |
@@ -6939,13 +7175,12 @@ readchar (int timeout) |
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; |
@@ -6953,6 +7188,21 @@ readchar (int timeout) |
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) |
+{ |
+ struct remote_state *rs = get_remote_state (); |
+ |
+ if (serial_write (rs->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 |
@@ -7024,6 +7274,7 @@ putpkt_binary (char *buf, int cnt) |
int ch; |
int tcount = 0; |
char *p; |
+ char *message; |
/* Catch cases like trying to read memory or listing threads while |
we're waiting for a stop reply. The remote server wouldn't be |
@@ -7072,8 +7323,7 @@ putpkt_binary (char *buf, int cnt) |
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. */ |
@@ -7128,7 +7378,7 @@ putpkt_binary (char *buf, int cnt) |
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 +. */ |
} |
@@ -7155,7 +7405,7 @@ putpkt_binary (char *buf, int cnt) |
str); |
do_cleanups (old_chain); |
} |
- handle_notification (rs->buf, val); |
+ handle_notification (rs->notif_state, rs->buf); |
/* We're in sync now, rewait for the ack. */ |
tcount = 0; |
} |
@@ -7406,11 +7656,13 @@ getpkt (char **buf, |
0, this function is allowed to time out gracefully and return an |
indication of this to the caller. Otherwise return the number of |
bytes read. If EXPECTING_NOTIF, consider receiving a notification |
- enough reason to return to the caller. */ |
+ enough reason to return to the caller. *IS_NOTIF is an output |
+ boolean that indicates whether *BUF holds a notification or not |
+ (a regular packet). */ |
static int |
getpkt_or_notif_sane_1 (char **buf, long *sizeof_buf, int forever, |
- int expecting_notif) |
+ int expecting_notif, int *is_notif) |
{ |
struct remote_state *rs = get_remote_state (); |
int c; |
@@ -7438,7 +7690,7 @@ getpkt_or_notif_sane_1 (char **buf, long *sizeof_buf, int forever, |
we get a packet. */ |
for (;;) |
{ |
- /* If we get a timeout or bad checksm, retry up to MAX_TRIES |
+ /* If we get a timeout or bad checksum, retry up to MAX_TRIES |
times. */ |
for (tries = 1; tries <= MAX_TRIES; tries++) |
{ |
@@ -7464,8 +7716,10 @@ getpkt_or_notif_sane_1 (char **buf, long *sizeof_buf, int forever, |
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); |
@@ -7479,7 +7733,7 @@ getpkt_or_notif_sane_1 (char **buf, long *sizeof_buf, int forever, |
break; |
} |
- serial_write (remote_desc, "-", 1); |
+ remote_serial_write ("-", 1); |
} |
if (tries > MAX_TRIES) |
@@ -7490,7 +7744,7 @@ getpkt_or_notif_sane_1 (char **buf, long *sizeof_buf, int forever, |
/* 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; |
} |
@@ -7510,7 +7764,9 @@ getpkt_or_notif_sane_1 (char **buf, long *sizeof_buf, int forever, |
/* 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; |
} |
@@ -7532,13 +7788,15 @@ getpkt_or_notif_sane_1 (char **buf, long *sizeof_buf, int forever, |
str); |
do_cleanups (old_chain); |
} |
+ if (is_notif != NULL) |
+ *is_notif = 1; |
- handle_notification (*buf, val); |
+ handle_notification (rs->notif_state, *buf); |
/* Notifications require no acknowledgement. */ |
if (expecting_notif) |
- return -1; |
+ return val; |
} |
} |
} |
@@ -7546,33 +7804,51 @@ getpkt_or_notif_sane_1 (char **buf, long *sizeof_buf, int forever, |
static int |
getpkt_sane (char **buf, long *sizeof_buf, int forever) |
{ |
- return getpkt_or_notif_sane_1 (buf, sizeof_buf, forever, 0); |
+ return getpkt_or_notif_sane_1 (buf, sizeof_buf, forever, 0, NULL); |
} |
static int |
-getpkt_or_notif_sane (char **buf, long *sizeof_buf, int forever) |
+getpkt_or_notif_sane (char **buf, long *sizeof_buf, int forever, |
+ int *is_notif) |
{ |
- return getpkt_or_notif_sane_1 (buf, sizeof_buf, forever, 1); |
+ return getpkt_or_notif_sane_1 (buf, sizeof_buf, forever, 1, |
+ is_notif); |
} |
-/* A helper function that just calls putpkt; for type correctness. */ |
- |
-static int |
-putpkt_for_catch_errors (void *arg) |
-{ |
- return putpkt (arg); |
-} |
- |
static void |
remote_kill (struct target_ops *ops) |
{ |
- /* Use catch_errors so the user can quit from gdb even when we |
+ struct gdb_exception ex; |
+ |
+ /* Catch errors so the user can quit from gdb even when we |
aren't on speaking terms with the remote system. */ |
- catch_errors (putpkt_for_catch_errors, "k", "", RETURN_MASK_ERROR); |
+ TRY_CATCH (ex, RETURN_MASK_ERROR) |
+ { |
+ putpkt ("k"); |
+ } |
+ if (ex.reason < 0) |
+ { |
+ if (ex.error == TARGET_CLOSE_ERROR) |
+ { |
+ /* If we got an (EOF) error that caused the target |
+ to go away, then we're done, that's what we wanted. |
+ "k" is susceptible to cause a premature EOF, given |
+ that the remote server isn't actually required to |
+ reply to "k", and it can happen that it doesn't |
+ even get to reply ACK to the "k". */ |
+ return; |
+ } |
- /* Don't wait for it to die. I'm not really sure it matters whether |
- we do or not. For the existing stubs, kill is a noop. */ |
+ /* Otherwise, something went wrong. We didn't actually kill |
+ the target. Just propagate the exception, and let the |
+ user or higher layers decide what to do. */ |
+ throw_exception (ex); |
+ } |
+ |
+ /* We've killed the remote end, we get to mourn it. Since this is |
+ target remote, single-process, mourning the inferior also |
+ unpushes remote_ops. */ |
target_mourn_inferior (); |
} |
@@ -7652,9 +7928,6 @@ extended_remote_mourn_1 (struct target_ops *target) |
connected. */ |
rs->waiting_for_stop_reply = 0; |
- /* We're no longer interested in these events. */ |
- discard_pending_stop_replies (ptid_get_pid (inferior_ptid)); |
- |
/* If the current general thread belonged to the process we just |
detached from or has exited, the remote side current general |
thread becomes undefined. Considering a case like this: |
@@ -7678,7 +7951,7 @@ extended_remote_mourn_1 (struct target_ops *target) |
To keep things simple, we always invalidate our notion of the |
current thread. */ |
- record_currthread (minus_one_ptid); |
+ record_currthread (rs, minus_one_ptid); |
/* Unlike "target remote", we do not want to unpush the target; then |
the next time the user says "run", we won't be connected. */ |
@@ -7780,7 +8053,7 @@ extended_remote_run (char *args) |
if (packet_ok (rs->buf, &remote_protocol_packets[PACKET_vRun]) == PACKET_OK) |
{ |
- /* We have a wait response; we don't need it, though. All is well. */ |
+ /* We have a wait response. All is well. */ |
return 0; |
} |
else if (remote_protocol_packets[PACKET_vRun].support == PACKET_DISABLE) |
@@ -7807,6 +8080,10 @@ static void |
extended_remote_create_inferior_1 (char *exec_file, char *args, |
char **env, int from_tty) |
{ |
+ int run_worked; |
+ char *stop_reply; |
+ struct remote_state *rs = get_remote_state (); |
+ |
/* If running asynchronously, register the target file descriptor |
with the event loop. */ |
if (target_can_async_p ()) |
@@ -7817,7 +8094,8 @@ extended_remote_create_inferior_1 (char *exec_file, char *args, |
extended_remote_disable_randomization (disable_randomization); |
/* Now restart the remote server. */ |
- if (extended_remote_run (args) == -1) |
+ run_worked = extended_remote_run (args) != -1; |
+ if (!run_worked) |
{ |
/* vRun was not supported. Fail if we need it to do what the |
user requested. */ |
@@ -7839,7 +8117,9 @@ extended_remote_create_inferior_1 (char *exec_file, char *args, |
init_wait_for_inferior (); |
} |
- add_current_inferior_and_thread (); |
+ /* vRun's success return is a stop reply. */ |
+ stop_reply = run_worked ? rs->buf : NULL; |
+ add_current_inferior_and_thread (stop_reply); |
/* Get updated offsets, if the stub uses qOffsets. */ |
get_offsets (); |
@@ -7887,8 +8167,6 @@ remote_add_target_side_condition (struct gdbarch *gdbarch, |
buf = pack_hex_byte (buf, aexpr->buf[i]); |
*buf = '\0'; |
} |
- |
- VEC_free (agent_expr_p, bp_tgt->conditions); |
return 0; |
} |
@@ -7919,8 +8197,6 @@ remote_add_target_side_commands (struct gdbarch *gdbarch, |
buf = pack_hex_byte (buf, aexpr->buf[i]); |
*buf = '\0'; |
} |
- |
- VEC_free (agent_expr_p, bp_tgt->tcommands); |
} |
/* Insert a breakpoint. On targets that have software breakpoint |
@@ -7944,6 +8220,11 @@ remote_insert_breakpoint (struct gdbarch *gdbarch, |
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 (); |
@@ -7994,6 +8275,11 @@ remote_remove_breakpoint (struct gdbarch *gdbarch, |
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++) = ','; |
@@ -8043,6 +8329,11 @@ remote_insert_watchpoint (CORE_ADDR addr, int len, int type, |
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); |
@@ -8087,6 +8378,11 @@ remote_remove_watchpoint (CORE_ADDR addr, int len, int type, |
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); |
@@ -8154,17 +8450,20 @@ remote_check_watch_resources (int type, int cnt, int ot) |
static int |
remote_stopped_by_watchpoint (void) |
{ |
- return remote_stopped_by_watchpoint_p; |
+ struct remote_state *rs = get_remote_state (); |
+ |
+ return rs->remote_stopped_by_watchpoint_p; |
} |
static int |
remote_stopped_data_address (struct target_ops *target, CORE_ADDR *addr_p) |
{ |
+ struct remote_state *rs = get_remote_state (); |
int rc = 0; |
if (remote_stopped_by_watchpoint ()) |
{ |
- *addr_p = remote_watch_data_address; |
+ *addr_p = rs->remote_watch_data_address; |
rc = 1; |
} |
@@ -8179,6 +8478,7 @@ remote_insert_hw_breakpoint (struct gdbarch *gdbarch, |
CORE_ADDR addr; |
struct remote_state *rs; |
char *p, *endbuf; |
+ char *message; |
/* The length field should be set to the size of a breakpoint |
instruction, even though we aren't inserting one ourselves. */ |
@@ -8189,6 +8489,11 @@ remote_insert_hw_breakpoint (struct gdbarch *gdbarch, |
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 (); |
@@ -8213,6 +8518,13 @@ remote_insert_hw_breakpoint (struct gdbarch *gdbarch, |
switch (packet_ok (rs->buf, &remote_protocol_packets[PACKET_Z1])) |
{ |
case PACKET_ERROR: |
+ if (rs->buf[1] == '.') |
+ { |
+ message = strchr (rs->buf + 2, '.'); |
+ if (message) |
+ error (_("Remote failure reply: %s"), message + 1); |
+ } |
+ return -1; |
case PACKET_UNKNOWN: |
return -1; |
case PACKET_OK: |
@@ -8235,6 +8547,11 @@ remote_remove_hw_breakpoint (struct gdbarch *gdbarch, |
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++) = ','; |
@@ -8258,36 +8575,6 @@ remote_remove_hw_breakpoint (struct gdbarch *gdbarch, |
_("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 |
@@ -8298,6 +8585,9 @@ remote_verify_memory (struct target_ops *ops, |
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); |
@@ -8305,7 +8595,7 @@ remote_verify_memory (struct target_ops *ops, |
/* 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') |
@@ -8331,7 +8621,7 @@ compare_sections_command (char *args, int from_tty) |
{ |
asection *s; |
struct cleanup *old_chain; |
- char *sectdata; |
+ gdb_byte *sectdata; |
const char *sectname; |
bfd_size_type size; |
bfd_vma lma; |
@@ -8342,6 +8632,9 @@ compare_sections_command (char *args, int from_tty) |
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)) |
@@ -8366,12 +8659,12 @@ compare_sections_command (char *args, int from_tty) |
if (res == -1) |
error (_("target memory fault, section %s, range %s -- %s"), sectname, |
- paddress (target_gdbarch, lma), |
- paddress (target_gdbarch, lma + size)); |
+ paddress (target_gdbarch (), lma), |
+ paddress (target_gdbarch (), lma + size)); |
printf_filtered ("Section %s, range %s -- %s: ", sectname, |
- paddress (target_gdbarch, lma), |
- paddress (target_gdbarch, lma + size)); |
+ paddress (target_gdbarch (), lma), |
+ paddress (target_gdbarch (), lma + size)); |
if (res) |
printf_filtered ("matched.\n"); |
else |
@@ -8416,7 +8709,7 @@ remote_write_qxfer (struct target_ops *ops, const char *object_name, |
/* 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 |
@@ -8440,10 +8733,6 @@ remote_read_qxfer (struct target_ops *ops, const char *object_name, |
gdb_byte *readbuf, ULONGEST offset, LONGEST len, |
struct packet_config *packet) |
{ |
- static char *finished_object; |
- static char *finished_annex; |
- static ULONGEST finished_offset; |
- |
struct remote_state *rs = get_remote_state (); |
LONGEST i, n, packet_len; |
@@ -8452,19 +8741,19 @@ remote_read_qxfer (struct target_ops *ops, const char *object_name, |
/* Check whether we've cached an end-of-object packet that matches |
this request. */ |
- if (finished_object) |
+ if (rs->finished_object) |
{ |
- if (strcmp (object_name, finished_object) == 0 |
- && strcmp (annex ? annex : "", finished_annex) == 0 |
- && offset == finished_offset) |
+ if (strcmp (object_name, rs->finished_object) == 0 |
+ && strcmp (annex ? annex : "", rs->finished_annex) == 0 |
+ && offset == rs->finished_offset) |
return 0; |
/* Otherwise, we're now reading something different. Discard |
the cache. */ |
- xfree (finished_object); |
- xfree (finished_annex); |
- finished_object = NULL; |
- finished_annex = NULL; |
+ xfree (rs->finished_object); |
+ xfree (rs->finished_annex); |
+ rs->finished_object = NULL; |
+ rs->finished_annex = NULL; |
} |
/* Request only enough to fit in a single packet. The actual data |
@@ -8495,16 +8784,17 @@ remote_read_qxfer (struct target_ops *ops, const char *object_name, |
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 |
object, record this fact to bypass a subsequent partial read. */ |
if (rs->buf[0] == 'l' && offset + i > 0) |
{ |
- finished_object = xstrdup (object_name); |
- finished_annex = xstrdup (annex ? annex : ""); |
- finished_offset = offset + i; |
+ rs->finished_object = xstrdup (object_name); |
+ rs->finished_annex = xstrdup (annex ? annex : ""); |
+ rs->finished_offset = offset + i; |
} |
return i; |
@@ -8528,9 +8818,7 @@ remote_xfer_partial (struct target_ops *ops, enum target_object object, |
/* Handle memory using the standard memory routines. */ |
if (object == TARGET_OBJECT_MEMORY) |
{ |
- int xfered; |
- |
- errno = 0; |
+ LONGEST xfered; |
/* If the remote target is connected but not running, we should |
pass this request down to a lower stratum (e.g. the executable |
@@ -8543,12 +8831,7 @@ remote_xfer_partial (struct target_ops *ops, enum target_object object, |
else |
xfered = remote_read_bytes (offset, readbuf, len); |
- if (xfered > 0) |
- return xfered; |
- else if (xfered == 0 && errno == 0) |
- return 0; |
- else |
- return -1; |
+ return xfered; |
} |
/* Handle SPU memory using qxfer packets. */ |
@@ -8597,14 +8880,7 @@ remote_xfer_partial (struct target_ops *ops, enum target_object object, |
switch (object) |
{ |
case TARGET_OBJECT_FLASH: |
- xfered = remote_flash_write (ops, offset, len, writebuf); |
- |
- if (xfered > 0) |
- return xfered; |
- else if (xfered == 0 && errno == 0) |
- return 0; |
- else |
- return -1; |
+ return remote_flash_write (ops, offset, len, writebuf); |
default: |
return -1; |
@@ -8646,7 +8922,7 @@ remote_xfer_partial (struct target_ops *ops, enum target_object object, |
case TARGET_OBJECT_OSDATA: |
/* Should only get here if we're connected. */ |
- gdb_assert (remote_desc); |
+ gdb_assert (rs->remote_desc); |
return remote_read_qxfer |
(ops, "osdata", annex, readbuf, offset, len, |
&remote_protocol_packets[PACKET_qXfer_osdata]); |
@@ -8670,6 +8946,10 @@ remote_xfer_partial (struct target_ops *ops, enum target_object object, |
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; |
} |
@@ -8685,7 +8965,7 @@ remote_xfer_partial (struct target_ops *ops, enum target_object object, |
len = get_remote_packet_size (); |
/* Except for querying the minimum buffer size, target must be open. */ |
- if (!remote_desc) |
+ if (!rs->remote_desc) |
error (_("remote query is only available after target open")); |
gdb_assert (annex != NULL); |
@@ -8727,7 +9007,7 @@ remote_search_memory (struct target_ops* ops, |
const gdb_byte *pattern, ULONGEST pattern_len, |
CORE_ADDR *found_addrp) |
{ |
- int addr_size = gdbarch_addr_bit (target_gdbarch) / 8; |
+ int addr_size = gdbarch_addr_bit (target_gdbarch ()) / 8; |
struct remote_state *rs = get_remote_state (); |
int max_size = get_memory_write_packet_size (); |
struct packet_config *packet = |
@@ -8763,6 +9043,9 @@ remote_search_memory (struct target_ops* ops, |
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;", |
@@ -8772,7 +9055,7 @@ remote_search_memory (struct target_ops* ops, |
/* 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. */ |
@@ -8816,7 +9099,7 @@ remote_rcmd (char *command, |
struct remote_state *rs = get_remote_state (); |
char *p = rs->buf; |
- if (!remote_desc) |
+ if (!rs->remote_desc) |
error (_("remote rcmd is only available after target open")); |
/* Send a NULL command across as an empty command. */ |
@@ -8902,7 +9185,7 @@ packet_command (char *args, int from_tty) |
{ |
struct remote_state *rs = get_remote_state (); |
- if (!remote_desc) |
+ if (!rs->remote_desc) |
error (_("command can only be used with remote target")); |
if (!args) |
@@ -9261,7 +9544,7 @@ static int |
remote_read_description_p (struct target_ops *target) |
{ |
struct remote_g_packet_data *data |
- = gdbarch_data (target_gdbarch, remote_g_packet_data_handle); |
+ = gdbarch_data (target_gdbarch (), remote_g_packet_data_handle); |
if (!VEC_empty (remote_g_packet_guess_s, data->guesses)) |
return 1; |
@@ -9273,7 +9556,7 @@ static const struct target_desc * |
remote_read_description (struct target_ops *target) |
{ |
struct remote_g_packet_data *data |
- = gdbarch_data (target_gdbarch, remote_g_packet_data_handle); |
+ = gdbarch_data (target_gdbarch (), remote_g_packet_data_handle); |
/* Do not try this during initial connection, when we do not know |
whether there is a running but stopped thread. */ |
@@ -9442,7 +9725,7 @@ remote_hostio_send_command (int command_bytes, int which_packet, |
int ret, bytes_read; |
char *attachment_tmp; |
- if (!remote_desc |
+ if (!rs->remote_desc |
|| remote_protocol_packets[which_packet].support == PACKET_DISABLE) |
{ |
*remote_errno = FILEIO_ENOSYS; |
@@ -9546,7 +9829,7 @@ remote_hostio_pwrite (int fd, const gdb_byte *write_buf, int len, |
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, |
@@ -9585,7 +9868,7 @@ remote_hostio_pread (int fd, gdb_byte *read_buf, int len, |
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); |
@@ -9659,8 +9942,8 @@ remote_hostio_readlink (const char *filename, int *remote_errno) |
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); |
@@ -9774,7 +10057,8 @@ remote_bfd_iovec_close (struct bfd *abfd, void *stream) |
connection was already torn down. */ |
remote_hostio_close (fd, &remote_errno); |
- return 1; |
+ /* Zero means success. */ |
+ return 0; |
} |
static file_ptr |
@@ -9788,7 +10072,7 @@ remote_bfd_iovec_pread (struct bfd *abfd, void *stream, void *buf, |
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. */ |
@@ -9817,17 +10101,21 @@ remote_bfd_iovec_stat (struct bfd *abfd, void *stream, struct stat *sb) |
int |
remote_filename_p (const char *filename) |
{ |
- return strncmp (filename, "remote:", 7) == 0; |
+ return strncmp (filename, |
+ REMOTE_SYSROOT_PREFIX, |
+ sizeof (REMOTE_SYSROOT_PREFIX) - 1) == 0; |
} |
bfd * |
remote_bfd_open (const char *remote_file, const char *target) |
{ |
- return bfd_openr_iovec (remote_file, target, |
- remote_bfd_iovec_open, NULL, |
- remote_bfd_iovec_pread, |
- remote_bfd_iovec_close, |
- remote_bfd_iovec_stat); |
+ bfd *abfd = gdb_bfd_openr_iovec (remote_file, target, |
+ remote_bfd_iovec_open, NULL, |
+ remote_bfd_iovec_pread, |
+ remote_bfd_iovec_close, |
+ remote_bfd_iovec_stat); |
+ |
+ return abfd; |
} |
void |
@@ -9840,11 +10128,12 @@ remote_file_put (const char *local_file, const char *remote_file, int from_tty) |
int bytes_in_buffer; |
int saw_eof; |
ULONGEST offset; |
+ struct remote_state *rs = get_remote_state (); |
- if (!remote_desc) |
+ if (!rs->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); |
@@ -9928,15 +10217,16 @@ remote_file_get (const char *remote_file, const char *local_file, int from_tty) |
FILE *file; |
gdb_byte *buffer; |
ULONGEST offset; |
+ struct remote_state *rs = get_remote_state (); |
- if (!remote_desc) |
+ if (!rs->remote_desc) |
error (_("command can only be used with remote target")); |
fd = remote_hostio_open (remote_file, FILEIO_O_RDONLY, 0, &remote_errno); |
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); |
@@ -9979,8 +10269,9 @@ void |
remote_file_delete (const char *remote_file, int from_tty) |
{ |
int retcode, remote_errno; |
+ struct remote_state *rs = get_remote_state (); |
- if (!remote_desc) |
+ if (!rs->remote_desc) |
error (_("command can only be used with remote target")); |
retcode = remote_hostio_unlink (remote_file, &remote_errno); |
@@ -10242,7 +10533,7 @@ remote_download_tracepoint (struct bp_location *loc) |
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, |
@@ -10265,7 +10556,7 @@ remote_download_tracepoint (struct bp_location *loc) |
{ |
int isize; |
- if (gdbarch_fast_tracepoint_valid_at (target_gdbarch, |
+ if (gdbarch_fast_tracepoint_valid_at (target_gdbarch (), |
tpaddr, &isize, NULL)) |
xsnprintf (buf + strlen (buf), BUF_SIZE - strlen (buf), ":F%x", |
isize); |
@@ -10499,6 +10790,7 @@ remote_trace_set_readonly_regions (void) |
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]; |
@@ -10553,6 +10845,10 @@ remote_get_trace_status (struct trace_status *ts) |
/* 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; |
@@ -10564,26 +10860,28 @@ remote_get_trace_status (struct trace_status *ts) |
} |
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. */ |
- ts->from_file = 0; |
- |
- /* Set some defaults. */ |
- ts->running_known = 0; |
- ts->stop_reason = trace_stop_reason_unknown; |
- ts->traceframe_count = -1; |
- ts->buffer_free = 0; |
+ ts->filename = NULL; |
if (*p++ != 'T') |
error (_("Bogus trace status reply from target: %s"), target_buf); |
+ /* Function 'parse_trace_status' sets default value of each field of |
+ 'ts' at first, so we don't have to do it here. */ |
parse_trace_status (p, ts); |
return ts->running; |
@@ -10649,7 +10947,7 @@ remote_trace_stop (void) |
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 (); |
@@ -10690,7 +10988,7 @@ remote_trace_find (enum trace_find_type type, int num, |
} |
putpkt (rs->buf); |
- reply = remote_get_noisy_reply (&(rs->buf), &sizeof_pkt); |
+ reply = remote_get_noisy_reply (&(rs->buf), &rs->buf_size); |
if (*reply == '\0') |
error (_("Target does not support this command.")); |
@@ -10725,7 +11023,7 @@ remote_trace_find (enum trace_find_type type, int num, |
if (tpp) |
*tpp = target_tracept; |
- remote_traceframe_number = target_frameno; |
+ rs->remote_traceframe_number = target_frameno; |
return target_frameno; |
} |
@@ -10869,6 +11167,11 @@ remote_traceframe_info (void) |
{ |
char *text; |
+ /* If current traceframe is not selected, don't bother the remote |
+ stub. */ |
+ if (get_traceframe_number () < 0) |
+ return NULL; |
+ |
text = target_read_stralloc (¤t_target, |
TARGET_OBJECT_TRACEFRAME_INFO, NULL); |
if (text != NULL) |
@@ -10918,8 +11221,41 @@ remote_get_min_fast_tracepoint_insn_len (void) |
} |
} |
+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; |
@@ -10931,21 +11267,21 @@ remote_set_trace_notes (char *user, char *notes, char *stop_notes) |
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++ = ';'; |
} |
@@ -10991,6 +11327,158 @@ remote_can_use_agent (void) |
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) |
{ |
@@ -11009,7 +11497,6 @@ Specify the serial device it is connected to\n\ |
remote_ops.to_fetch_registers = remote_fetch_registers; |
remote_ops.to_store_registers = remote_store_registers; |
remote_ops.to_prepare_to_store = remote_prepare_to_store; |
- remote_ops.deprecated_xfer_memory = remote_xfer_memory; |
remote_ops.to_files_info = remote_files_info; |
remote_ops.to_insert_breakpoint = remote_insert_breakpoint; |
remote_ops.to_remove_breakpoint = remote_remove_breakpoint; |
@@ -11095,6 +11582,7 @@ Specify the serial device it is connected to\n\ |
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; |
@@ -11107,6 +11595,13 @@ Specify the serial device it is connected to\n\ |
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 |
@@ -11136,40 +11631,43 @@ Specify the serial device it is connected to (e.g. /dev/ttya)."; |
static int |
remote_can_async_p (void) |
{ |
+ struct remote_state *rs = get_remote_state (); |
+ |
if (!target_async_permitted) |
/* We only enable async when the user specifically asks for it. */ |
return 0; |
/* We're async whenever the serial device is. */ |
- return serial_can_async_p (remote_desc); |
+ return serial_can_async_p (rs->remote_desc); |
} |
static int |
remote_is_async_p (void) |
{ |
+ struct remote_state *rs = get_remote_state (); |
+ |
if (!target_async_permitted) |
/* We only enable async when the user specifically asks for it. */ |
return 0; |
/* We're async whenever the serial device is. */ |
- return serial_is_async_p (remote_desc); |
+ return serial_is_async_p (rs->remote_desc); |
} |
/* Pass the SERIAL event on and up to the client. One day this code |
will be able to delay notifying the client of an event until the |
point where an entire packet has been received. */ |
-static void (*async_client_callback) (enum inferior_event_type event_type, |
- void *context); |
-static void *async_client_context; |
static serial_event_ftype remote_async_serial_handler; |
static void |
remote_async_serial_handler (struct serial *scb, void *context) |
{ |
+ struct remote_state *rs = context; |
+ |
/* Don't propogate error information up to the client. Instead let |
the client find out about the error by querying the target. */ |
- async_client_callback (INF_REG_EVENT, async_client_context); |
+ rs->async_client_callback (INF_REG_EVENT, rs->async_client_context); |
} |
static void |
@@ -11179,23 +11677,19 @@ remote_async_inferior_event_handler (gdb_client_data data) |
} |
static void |
-remote_async_get_pending_events_handler (gdb_client_data data) |
-{ |
- remote_get_pending_stop_replies (); |
-} |
- |
-static void |
remote_async (void (*callback) (enum inferior_event_type event_type, |
void *context), void *context) |
{ |
+ struct remote_state *rs = get_remote_state (); |
+ |
if (callback != NULL) |
{ |
- serial_async (remote_desc, remote_async_serial_handler, NULL); |
- async_client_callback = callback; |
- async_client_context = context; |
+ serial_async (rs->remote_desc, remote_async_serial_handler, rs); |
+ rs->async_client_callback = callback; |
+ rs->async_client_context = context; |
} |
else |
- serial_async (remote_desc, NULL, NULL); |
+ serial_async (rs->remote_desc, NULL, NULL); |
} |
static void |
@@ -11229,7 +11723,7 @@ show_remote_cmd (char *args, int from_tty) |
ui_out_field_string (uiout, "name", list->name); |
ui_out_text (uiout, ": "); |
if (list->type == show_cmd) |
- do_setshow_command ((char *) NULL, from_tty, list); |
+ do_show_command ((char *) NULL, from_tty, list); |
else |
cmd_func (list, NULL, from_tty); |
/* Close the tuple. */ |
@@ -11245,8 +11739,10 @@ show_remote_cmd (char *args, int from_tty) |
static void |
remote_new_objfile (struct objfile *objfile) |
{ |
- if (remote_desc != 0) /* Have a remote connection. */ |
- remote_check_symbols (objfile); |
+ struct remote_state *rs = get_remote_state (); |
+ |
+ if (rs->remote_desc != 0) /* Have a remote connection. */ |
+ remote_check_symbols (); |
} |
/* Pull all the tracepoints defined on the target and create local |
@@ -11296,12 +11792,50 @@ remote_upload_trace_state_variables (struct uploaded_tsv **utsvp) |
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) |
+{ |
+ struct remote_state *rs = get_remote_state (); |
+ |
+ /* Whene enabling, check whether range stepping is actually |
+ supported by the target, and warn if not. */ |
+ if (use_range_stepping) |
+ { |
+ if (rs->remote_desc != NULL) |
+ { |
+ 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 = |
@@ -11311,11 +11845,8 @@ _initialize_remote (void) |
/* Initialize the per-target state. At the moment there is only one |
of these, not one per target. Only one target is active at a |
- time. The default buffer size is unimportant; it will be expanded |
- whenever a larger buffer is needed. */ |
- rs = get_remote_state_raw (); |
- rs->buf_size = 400; |
- rs->buf = xmalloc (rs->buf_size); |
+ time. */ |
+ remote_state = new_remote_state (); |
init_remote_ops (); |
add_target (&remote_ops); |
@@ -11325,17 +11856,21 @@ _initialize_remote (void) |
/* Hook into new objfile notification. */ |
observer_attach_new_objfile (remote_new_objfile); |
+ /* We're no longer interested in notification events of an inferior |
+ when it exits. */ |
+ 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 |
init_remote_threadtests (); |
#endif |
+ stop_reply_queue = QUEUE_alloc (stop_reply_p, stop_reply_xfree); |
/* set/show remote ... */ |
add_prefix_cmd ("remote", class_maintenance, set_remote_cmd, _("\ |
@@ -11457,13 +11992,13 @@ Specify a negative limit for unlimited."), |
breakpoints is %s. */ |
&remote_set_cmdlist, &remote_show_cmdlist); |
- add_setshow_integer_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); |
@@ -11536,7 +12071,7 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL, |
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); |
@@ -11561,6 +12096,9 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL, |
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); |
@@ -11633,6 +12171,18 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL, |
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 |
@@ -11674,6 +12224,20 @@ Set the remote pathname for \"run\""), _("\ |
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); |