| 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);
|
|
|
|
|