Specify the serial device it is connected to\n\
(e.g. /dev/ttyS0, /dev/ttya, COM1, etc.).");
+#define OPAQUETHREADBYTES 8
+
+/* a 64 bit opaque identifier */
+typedef unsigned char threadref[OPAQUETHREADBYTES];
+
+struct gdb_ext_thread_info;
+struct threads_listing_context;
+typedef int (*rmt_thread_action) (threadref *ref, void *context);
+struct protocol_feature;
+struct packet_reg;
+
+struct stop_reply;
+static void stop_reply_xfree (struct stop_reply *);
+
+struct stop_reply_deleter
+{
+ void operator() (stop_reply *r) const
+ {
+ stop_reply_xfree (r);
+ }
+};
+
+typedef std::unique_ptr<stop_reply, stop_reply_deleter> stop_reply_up;
+
+/* Generic configuration support for packets the stub optionally
+ supports. Allows the user to specify the use of the packet as well
+ as allowing GDB to auto-detect support in the remote stub. */
+
+enum packet_support
+ {
+ PACKET_SUPPORT_UNKNOWN = 0,
+ PACKET_ENABLE,
+ PACKET_DISABLE
+ };
+
+/* Analyze a packet's return value and update the packet config
+ accordingly. */
+
+enum packet_result
+{
+ PACKET_ERROR,
+ PACKET_OK,
+ PACKET_UNKNOWN
+};
+
+struct threads_listing_context;
+
+/* 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 */
+ bool t = false;
+
+ /* vCont;r */
+ bool r = false;
+
+ /* vCont;s */
+ bool s = false;
+
+ /* vCont;S */
+ bool S = false;
+};
+
+/* About this many threadisds fit in a packet. */
+
+#define MAXTHREADLISTRESULTS 32
+
+/* Data for the vFile:pread readahead cache. */
+
+struct readahead_cache
+{
+ /* Invalidate the readahead cache. */
+ void invalidate ();
+
+ /* Invalidate the readahead cache if it is holding data for FD. */
+ void invalidate_fd (int fd);
+
+ /* Serve pread from the readahead cache. Returns number of bytes
+ read, or 0 if the request can't be served from the cache. */
+ int pread (int fd, gdb_byte *read_buf, size_t len, ULONGEST offset);
+
+ /* The file descriptor for the file that is being cached. -1 if the
+ cache is invalid. */
+ int fd = -1;
+
+ /* The offset into the file that the cache buffer corresponds
+ to. */
+ ULONGEST offset = 0;
+
+ /* The buffer holding the cache contents. */
+ gdb_byte *buf = nullptr;
+ /* The buffer's size. We try to read as much as fits into a packet
+ at a time. */
+ size_t bufsize = 0;
+
+ /* Cache hit and miss counters. */
+ ULONGEST hit_count = 0;
+ ULONGEST miss_count = 0;
+};
+
+/* Description of the remote protocol for a given architecture. */
+
+struct packet_reg
+{
+ long offset; /* Offset into G packet. */
+ 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);
+ at present. */
+ /* char *name; == gdbarch_register_name (target_gdbarch (), regnum);
+ at present. */
+};
+
+struct remote_arch_state
+{
+ explicit remote_arch_state (struct gdbarch *gdbarch);
+
+ /* Description of the remote protocol registers. */
+ long sizeof_g_packet;
+
+ /* Description of the remote protocol registers indexed by REGNUM
+ (making an array gdbarch_num_regs in size). */
+ std::unique_ptr<packet_reg[]> regs;
+
+ /* This is the size (in chars) of the first response to the ``g''
+ packet. It is used as a heuristic when determining the maximum
+ size of memory-read and memory-write packets. A target will
+ typically only reserve a buffer large enough to hold the ``g''
+ packet. The size does not include packet overhead (headers and
+ trailers). */
+ long actual_register_packet_size;
+
+ /* This is the maximum size (in chars) of a non read/write packet.
+ It is also used as a cap on the size of read/write packets. */
+ long remote_packet_size;
+};
+
+/* Description of the remote protocol state for the currently
+ connected target. This is per-target state, and independent of the
+ selected architecture. */
+
+class remote_state
+{
+public:
+
+ remote_state ();
+ ~remote_state ();
+
+ /* Get the remote arch state for GDBARCH. */
+ struct remote_arch_state *get_remote_arch_state (struct gdbarch *gdbarch);
+
+public: /* data */
+
+ /* A buffer to use for incoming packets, and its current size. The
+ buffer is grown dynamically for larger incoming packets.
+ Outgoing packets may also be constructed in this buffer.
+ BUF_SIZE is always at least REMOTE_PACKET_SIZE;
+ REMOTE_PACKET_SIZE should be used to limit the length of outgoing
+ packets. */
+ char *buf;
+ long buf_size;
+
+ /* True if we're going through initial connection setup (finding out
+ about the remote side's threads, relocating symbols, etc.). */
+ bool starting_up = false;
+
+ /* If we negotiated packet size explicitly (and thus can bypass
+ heuristics for the largest packet size that will not overflow
+ a buffer in the stub), this will be set to that packet size.
+ Otherwise zero, meaning to use the guessed size. */
+ long explicit_packet_size = 0;
+
+ /* remote_wait is normally called when the target is running and
+ waits for a stop reply packet. But sometimes we need to call it
+ when the target is already stopped. We can send a "?" packet
+ and have remote_wait read the response. Or, if we already have
+ the response, we can stash it in BUF and tell remote_wait to
+ skip calling getpkt. This flag is set when BUF contains a
+ stop reply packet and the target is not waiting. */
+ int cached_wait_status = 0;
+
+ /* True, if in no ack mode. That is, neither GDB nor the stub will
+ expect acks from each other. The connection is assumed to be
+ reliable. */
+ bool noack_mode = false;
+
+ /* True if we're connected in extended remote mode. */
+ bool extended = false;
+
+ /* True if we resumed the target and we're waiting for the target to
+ stop. In the mean time, we can't start another command/query.
+ The remote server wouldn't be ready to process it, so we'd
+ timeout waiting for a reply that would never come and eventually
+ we'd close the connection. This can happen in asynchronous mode
+ because we allow GDB commands while the target is running. */
+ bool waiting_for_stop_reply = false;
+
+ /* The status of the stub support for the various vCont actions. */
+ vCont_action_support supports_vCont;
+
+ /* True if the user has pressed Ctrl-C, but the target hasn't
+ responded to that. */
+ bool ctrlc_pending_p = false;
+
+ /* True if we saw a Ctrl-C while reading or writing from/to the
+ remote descriptor. At that point it is not safe to send a remote
+ interrupt packet, so we instead remember we saw the Ctrl-C and
+ process it once we're done with sending/receiving the current
+ packet, which should be shortly. If however that takes too long,
+ and the user presses Ctrl-C again, we offer to disconnect. */
+ bool got_ctrlc_during_io = false;
+
+ /* 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 = nullptr;
+
+ /* 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 = null_ptid;
+ ptid_t continue_thread = null_ptid;
+
+ /* 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 = -1;
+
+ char *last_pass_packet = nullptr;
+
+ /* 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 = nullptr;
+
+ gdb_signal last_sent_signal = GDB_SIGNAL_0;
+
+ bool last_sent_step = false;
+
+ /* The execution direction of the last resume we got. */
+ exec_direction_kind last_resume_exec_dir = EXEC_FORWARD;
+
+ char *finished_object = nullptr;
+ char *finished_annex = nullptr;
+ ULONGEST finished_offset = 0;
+
+ /* 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). */
+ bool use_threadinfo_query = false;
+ bool use_threadextra_query = false;
+
+ threadref echo_nextthread {};
+ threadref nextthread {};
+ threadref resultthreadlist[MAXTHREADLISTRESULTS] {};
+
+ /* The state of remote notification. */
+ struct remote_notif_state *notif_state = nullptr;
+
+ /* The branch trace configuration. */
+ struct btrace_config btrace_config {};
+
+ /* The argument to the last "vFile:setfs:" packet we sent, used
+ to avoid sending repeated unnecessary "vFile:setfs:" packets.
+ Initialized to -1 to indicate that no "vFile:setfs:" packet
+ has yet been sent. */
+ int fs_pid = -1;
+
+ /* A readahead cache for vFile:pread. Often, reading a binary
+ involves a sequence of small reads. E.g., when parsing an ELF
+ file. A readahead cache helps mostly the case of remote
+ debugging on a connection with higher latency, due to the
+ request/reply nature of the RSP. We only cache data for a single
+ file descriptor at a time. */
+ struct readahead_cache readahead_cache;
+
+ /* 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. */
+ std::vector<stop_reply_up> stop_reply_queue;
+
+ /* Asynchronous signal handle registered as event loop source for
+ when we have pending events ready to be passed to the core. */
+ struct async_event_handler *remote_async_inferior_event_token = nullptr;
+
+ /* FIXME: cagney/1999-09-23: Even though getpkt was called with
+ ``forever'' still use the normal timeout mechanism. This is
+ currently used by the ASYNC code to guarentee that target reads
+ during the initial connect always time-out. Once getpkt has been
+ modified to return a timeout indication and, in turn
+ remote_wait()/wait_for_inferior() have gained a timeout parameter
+ this can go away. */
+ int wait_forever_enabled_p = 1;
+
+private:
+ /* Mapping of remote protocol data for each gdbarch. Usually there
+ is only one entry here, though we may see more with stubs that
+ support multi-process. */
+ std::unordered_map<struct gdbarch *, remote_arch_state>
+ m_arch_states;
+};
+
static const target_info remote_target_info = {
"remote",
N_("Remote serial target in gdb-specific protocol"),
{
to_stratum = process_stratum;
}
+ ~remote_target () override;
const target_info &info () const override
{ return remote_target_info; }
int remove_exec_catchpoint (int) override;
enum exec_direction_kind execution_direction () override;
-protected:
- static void open_1 (const char *name, int from_tty, int extended_p);
- void start_remote (int from_tty, int extended_p);
-};
+public: /* Remote specific methods. */
-static const target_info extended_remote_target_info = {
- "extended-remote",
- N_("Extended remote serial target in gdb-specific protocol"),
- remote_doc
-};
+ void remote_download_command_source (int num, ULONGEST addr,
+ struct command_line *cmds);
-/* Set up the extended remote target by extending the standard remote
- target and adding to it. */
+ void remote_file_put (const char *local_file, const char *remote_file,
+ int from_tty);
+ void remote_file_get (const char *remote_file, const char *local_file,
+ int from_tty);
+ void remote_file_delete (const char *remote_file, int from_tty);
-class extended_remote_target final : public remote_target
-{
-public:
- const target_info &info () const override
- { return extended_remote_target_info; }
+ int remote_hostio_pread (int fd, gdb_byte *read_buf, int len,
+ ULONGEST offset, int *remote_errno);
+ int remote_hostio_pwrite (int fd, const gdb_byte *write_buf, int len,
+ ULONGEST offset, int *remote_errno);
+ int remote_hostio_pread_vFile (int fd, gdb_byte *read_buf, int len,
+ ULONGEST offset, int *remote_errno);
- /* Open an extended-remote connection. */
- static void open (const char *, int);
+ int remote_hostio_send_command (int command_bytes, int which_packet,
+ int *remote_errno, char **attachment,
+ int *attachment_len);
+ int remote_hostio_set_filesystem (struct inferior *inf,
+ int *remote_errno);
+ /* We should get rid of this and use fileio_open directly. */
+ int remote_hostio_open (struct inferior *inf, const char *filename,
+ int flags, int mode, int warn_if_slow,
+ int *remote_errno);
+ int remote_hostio_close (int fd, int *remote_errno);
- bool can_create_inferior () override { return true; }
- void create_inferior (const char *, const std::string &,
- char **, int) override;
+ int remote_hostio_unlink (inferior *inf, const char *filename,
+ int *remote_errno);
- void detach (inferior *, int) override;
+ struct remote_state *get_remote_state ();
- bool can_attach () override { return true; }
- void attach (const char *, int) override;
+ long get_remote_packet_size (void);
+ long get_memory_packet_size (struct memory_packet_config *config);
- void post_attach (int) override;
- bool supports_disable_randomization () override;
-};
+ long get_memory_write_packet_size ();
+ long get_memory_read_packet_size ();
-/* Per-program-space data key. */
-static const struct program_space_data *remote_pspace_data;
+ char *append_pending_thread_resumptions (char *p, char *endp,
+ ptid_t ptid);
+ static void open_1 (const char *name, int from_tty, int extended_p);
+ void start_remote (int from_tty, int extended_p);
+ void remote_detach_1 (struct inferior *inf, int from_tty);
-/* The variable registered as the control variable used by the
- remote exec-file commands. While the remote exec-file setting is
- per-program-space, the set/show machinery uses this as the
- location of the remote exec-file value. */
-static char *remote_exec_file_var;
+ char *append_resumption (char *p, char *endp,
+ ptid_t ptid, int step, gdb_signal siggnal);
+ int remote_resume_with_vcont (ptid_t ptid, int step,
+ gdb_signal siggnal);
-/* The size to align memory write packets, when practical. The protocol
- does not guarantee any alignment, and gdb will generate short
- writes and unaligned writes, but even as a best-effort attempt this
- can improve bulk transfers. For instance, if a write is misaligned
- relative to the target's data bus, the stub may need to make an extra
- round trip fetching data from the target. This doesn't make a
- huge difference, but it's easy to do, so we try to be helpful.
+ void add_current_inferior_and_thread (char *wait_status);
- The alignment chosen is arbitrary; usually data bus width is
- important here, not the possibly larger cache line size. */
-enum { REMOTE_ALIGN_WRITES = 16 };
+ ptid_t wait_ns (ptid_t ptid, struct target_waitstatus *status,
+ int options);
+ ptid_t wait_as (ptid_t ptid, target_waitstatus *status,
+ int options);
-/* Prototypes for local functions. */
-static int getpkt_sane (char **buf, long *sizeof_buf, int forever);
-static int getpkt_or_notif_sane (char **buf, long *sizeof_buf,
- int forever, int *is_notif);
+ ptid_t process_stop_reply (struct stop_reply *stop_reply,
+ target_waitstatus *status);
-struct remote_state;
+ void remote_notice_new_inferior (ptid_t currthread, int executing);
-static int remote_vkill (int pid, struct remote_state *rs);
+ void process_initial_stop_replies (int from_tty);
-static void remote_kill_k (void);
+ thread_info *remote_add_thread (ptid_t ptid, bool running, bool executing);
-static int readchar (int timeout);
+ void btrace_sync_conf (const btrace_config *conf);
-static void remote_serial_write (const char *str, int len);
+ void remote_btrace_maybe_reopen ();
-static void interrupt_query (void);
+ void remove_new_fork_children (threads_listing_context *context);
+ void kill_new_fork_children (int pid);
+ void discard_pending_stop_replies (struct inferior *inf);
+ int stop_reply_queue_length ();
-static void set_general_thread (ptid_t ptid);
-static void set_continue_thread (ptid_t ptid);
+ void check_pending_events_prevent_wildcard_vcont
+ (int *may_global_wildcard_vcont);
-static void get_offsets (void);
+ void discard_pending_stop_replies_in_queue ();
+ struct stop_reply *remote_notif_remove_queued_reply (ptid_t ptid);
+ struct stop_reply *queued_stop_reply (ptid_t ptid);
+ int peek_stop_reply (ptid_t ptid);
+ void remote_parse_stop_reply (char *buf, stop_reply *event);
-static void skip_frame (void);
+ void remote_stop_ns (ptid_t ptid);
+ void remote_interrupt_as ();
+ void remote_interrupt_ns ();
-static long read_frame (char **buf_p, long *sizeof_buf);
+ char *remote_get_noisy_reply ();
+ int remote_query_attached (int pid);
+ inferior *remote_add_inferior (int fake_pid_p, int pid, int attached,
+ int try_open_exec);
-static int hexnumlen (ULONGEST num);
+ ptid_t remote_current_thread (ptid_t oldpid);
+ ptid_t get_current_thread (char *wait_status);
-static int stubhex (int ch);
+ void set_thread (ptid_t ptid, int gen);
+ void set_general_thread (ptid_t ptid);
+ void set_continue_thread (ptid_t ptid);
+ void set_general_process ();
-static int hexnumstr (char *, ULONGEST);
+ char *write_ptid (char *buf, const char *endbuf, ptid_t ptid);
-static int hexnumnstr (char *, ULONGEST, int);
+ int remote_unpack_thread_info_response (char *pkt, threadref *expectedref,
+ gdb_ext_thread_info *info);
+ int remote_get_threadinfo (threadref *threadid, int fieldset,
+ gdb_ext_thread_info *info);
-static CORE_ADDR remote_address_masked (CORE_ADDR);
+ int parse_threadlist_response (char *pkt, int result_limit,
+ threadref *original_echo,
+ threadref *resultlist,
+ int *doneflag);
+ int remote_get_threadlist (int startflag, threadref *nextthread,
+ int result_limit, int *done, int *result_count,
+ threadref *threadlist);
-static void print_packet (const char *);
+ int remote_threadlist_iterator (rmt_thread_action stepfunction,
+ void *context, int looplimit);
-static int stub_unpack_int (char *buff, int fieldlength);
+ int remote_get_threads_with_ql (threads_listing_context *context);
+ int remote_get_threads_with_qxfer (threads_listing_context *context);
+ int remote_get_threads_with_qthreadinfo (threads_listing_context *context);
-static ptid_t remote_current_thread (ptid_t oldptid);
+ void extended_remote_restart ();
-static int putpkt_binary (const char *buf, int cnt);
+ void get_offsets ();
-static void check_binary_download (CORE_ADDR addr);
+ void remote_check_symbols ();
-struct packet_config;
+ void remote_supported_packet (const struct protocol_feature *feature,
+ enum packet_support support,
+ const char *argument);
-static void show_packet_config_cmd (struct packet_config *config);
+ void remote_query_supported ();
-static void show_remote_protocol_packet_cmd (struct ui_file *file,
- int from_tty,
- struct cmd_list_element *c,
- const char *value);
+ void remote_packet_size (const protocol_feature *feature,
+ packet_support support, const char *value);
-static char *write_ptid (char *buf, const char *endbuf, ptid_t ptid);
-static ptid_t read_ptid (const char *buf, const char **obuf);
+ void remote_serial_quit_handler ();
-static void remote_query_supported (void);
+ void remote_detach_pid (int pid);
-static void remote_check_symbols (void);
+ void remote_vcont_probe ();
-struct stop_reply;
-static void stop_reply_xfree (struct stop_reply *);
-static void remote_parse_stop_reply (char *, struct stop_reply *);
-static void push_stop_reply (struct stop_reply *);
-static void discard_pending_stop_replies_in_queue (struct remote_state *);
-static int peek_stop_reply (ptid_t ptid);
+ void remote_resume_with_hc (ptid_t ptid, int step,
+ gdb_signal siggnal);
-struct threads_listing_context;
-static void remove_new_fork_children (struct threads_listing_context *);
+ void send_interrupt_sequence ();
+ void interrupt_query ();
-static void remote_async_inferior_event_handler (gdb_client_data);
+ void remote_notif_get_pending_events (notif_client *nc);
-static int remote_read_description_p (struct target_ops *target);
+ int fetch_register_using_p (struct regcache *regcache,
+ packet_reg *reg);
+ int send_g_packet ();
+ void process_g_packet (struct regcache *regcache);
+ void fetch_registers_using_g (struct regcache *regcache);
+ int store_register_using_P (const struct regcache *regcache,
+ packet_reg *reg);
+ void store_registers_using_G (const struct regcache *regcache);
-static void remote_console_output (char *msg);
+ void set_remote_traceframe ();
-static void remote_btrace_reset (void);
+ void check_binary_download (CORE_ADDR addr);
-static void remote_btrace_maybe_reopen (void);
+ target_xfer_status remote_write_bytes_aux (const char *header,
+ CORE_ADDR memaddr,
+ const gdb_byte *myaddr,
+ ULONGEST len_units,
+ int unit_size,
+ ULONGEST *xfered_len_units,
+ char packet_format,
+ int use_length);
-static int stop_reply_queue_length (void);
+ target_xfer_status remote_write_bytes (CORE_ADDR memaddr,
+ const gdb_byte *myaddr, ULONGEST len,
+ int unit_size, ULONGEST *xfered_len);
-static void remote_unpush_and_throw (void);
+ target_xfer_status remote_read_bytes_1 (CORE_ADDR memaddr, gdb_byte *myaddr,
+ ULONGEST len_units,
+ int unit_size, ULONGEST *xfered_len_units);
-static struct remote_state *get_remote_state (void);
+ target_xfer_status remote_xfer_live_readonly_partial (gdb_byte *readbuf,
+ ULONGEST memaddr,
+ ULONGEST len,
+ int unit_size,
+ ULONGEST *xfered_len);
-/* For "remote". */
+ target_xfer_status remote_read_bytes (CORE_ADDR memaddr,
+ gdb_byte *myaddr, ULONGEST len,
+ int unit_size,
+ ULONGEST *xfered_len);
-static struct cmd_list_element *remote_cmdlist;
+ packet_result remote_send_printf (const char *format, ...)
+ ATTRIBUTE_PRINTF (2, 3);
-/* For "set remote" and "show remote". */
+ target_xfer_status remote_flash_write (ULONGEST address,
+ ULONGEST length, ULONGEST *xfered_len,
+ const gdb_byte *data);
-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 */
- bool t = false;
-
- /* vCont;r */
- bool r = false;
-
- /* vCont;s */
- bool s = false;
-
- /* vCont;S */
- bool S = false;
-};
-
-/* Controls whether GDB is willing to use range stepping. */
-
-static int use_range_stepping = 1;
+ int readchar (int timeout);
-#define OPAQUETHREADBYTES 8
+ void remote_serial_write (const char *str, int len);
-/* a 64 bit opaque identifier */
-typedef unsigned char threadref[OPAQUETHREADBYTES];
+ int putpkt (const char *buf);
+ int putpkt_binary (const char *buf, int cnt);
-/* About this many threadisds fit in a packet. */
+ void skip_frame ();
+ long read_frame (char **buf_p, long *sizeof_buf);
+ void getpkt (char **buf, long *sizeof_buf, int forever);
+ int getpkt_or_notif_sane_1 (char **buf, long *sizeof_buf, int forever,
+ int expecting_notif, int *is_notif);
+ int getpkt_sane (char **buf, long *sizeof_buf, int forever);
+ int getpkt_or_notif_sane (char **buf, long *sizeof_buf, int forever,
+ int *is_notif);
+ int remote_vkill (int pid);
+ void remote_kill_k ();
-#define MAXTHREADLISTRESULTS 32
+ void extended_remote_disable_randomization (int val);
+ int extended_remote_run (const std::string &args);
-/* The max number of chars in debug output. The rest of chars are
- omitted. */
+ void send_environment_packet (const char *action,
+ const char *packet,
+ const char *value);
-#define REMOTE_DEBUG_MAX_CHAR 512
+ void extended_remote_environment_support ();
+ void extended_remote_set_inferior_cwd ();
-/* Data for the vFile:pread readahead cache. */
+ target_xfer_status remote_write_qxfer (const char *object_name,
+ const char *annex,
+ const gdb_byte *writebuf,
+ ULONGEST offset, LONGEST len,
+ ULONGEST *xfered_len,
+ struct packet_config *packet);
-struct readahead_cache
-{
- /* Invalidate the readahead cache. */
- void invalidate ();
+ target_xfer_status remote_read_qxfer (const char *object_name,
+ const char *annex,
+ gdb_byte *readbuf, ULONGEST offset,
+ LONGEST len,
+ ULONGEST *xfered_len,
+ struct packet_config *packet);
- /* Invalidate the readahead cache if it is holding data for FD. */
- void invalidate_fd (int fd);
+ void push_stop_reply (struct stop_reply *new_event);
- /* Serve pread from the readahead cache. Returns number of bytes
- read, or 0 if the request can't be served from the cache. */
- int pread (int fd, gdb_byte *read_buf, size_t len, ULONGEST offset);
+ bool vcont_r_supported ();
- /* The file descriptor for the file that is being cached. -1 if the
- cache is invalid. */
- int fd = -1;
+ void packet_command (const char *args, int from_tty);
- /* The offset into the file that the cache buffer corresponds
- to. */
- ULONGEST offset = 0;
+private: /* data fields */
- /* The buffer holding the cache contents. */
- gdb_byte *buf = nullptr;
- /* The buffer's size. We try to read as much as fits into a packet
- at a time. */
- size_t bufsize = 0;
+ /* The remote state. Don't reference this directly. Use the
+ get_remote_state method instead. */
+ remote_state m_remote_state;
+};
- /* Cache hit and miss counters. */
- ULONGEST hit_count = 0;
- ULONGEST miss_count = 0;
+static const target_info extended_remote_target_info = {
+ "extended-remote",
+ N_("Extended remote serial target in gdb-specific protocol"),
+ remote_doc
};
-/* Description of the remote protocol state for the currently
- connected target. This is per-target state, and independent of the
- selected architecture. */
+/* Set up the extended remote target by extending the standard remote
+ target and adding to it. */
-class remote_state
+class extended_remote_target final : public remote_target
{
public:
+ const target_info &info () const override
+ { return extended_remote_target_info; }
- remote_state ();
- ~remote_state ();
+ /* Open an extended-remote connection. */
+ static void open (const char *, int);
- /* Get the remote arch state for GDBARCH. */
- struct remote_arch_state *get_remote_arch_state (struct gdbarch *gdbarch);
+ bool can_create_inferior () override { return true; }
+ void create_inferior (const char *, const std::string &,
+ char **, int) override;
-public: /* data */
+ void detach (inferior *, int) override;
- /* A buffer to use for incoming packets, and its current size. The
- buffer is grown dynamically for larger incoming packets.
- Outgoing packets may also be constructed in this buffer.
- BUF_SIZE is always at least REMOTE_PACKET_SIZE;
- REMOTE_PACKET_SIZE should be used to limit the length of outgoing
- packets. */
- char *buf;
- long buf_size;
+ bool can_attach () override { return true; }
+ void attach (const char *, int) override;
- /* True if we're going through initial connection setup (finding out
- about the remote side's threads, relocating symbols, etc.). */
- bool starting_up = false;
+ void post_attach (int) override;
+ bool supports_disable_randomization () override;
+};
- /* If we negotiated packet size explicitly (and thus can bypass
- heuristics for the largest packet size that will not overflow
- a buffer in the stub), this will be set to that packet size.
- Otherwise zero, meaning to use the guessed size. */
- long explicit_packet_size = 0;
+/* Per-program-space data key. */
+static const struct program_space_data *remote_pspace_data;
- /* remote_wait is normally called when the target is running and
- waits for a stop reply packet. But sometimes we need to call it
- when the target is already stopped. We can send a "?" packet
- and have remote_wait read the response. Or, if we already have
- the response, we can stash it in BUF and tell remote_wait to
- skip calling getpkt. This flag is set when BUF contains a
- stop reply packet and the target is not waiting. */
- int cached_wait_status = 0;
+/* The variable registered as the control variable used by the
+ remote exec-file commands. While the remote exec-file setting is
+ per-program-space, the set/show machinery uses this as the
+ location of the remote exec-file value. */
+static char *remote_exec_file_var;
- /* True, if in no ack mode. That is, neither GDB nor the stub will
- expect acks from each other. The connection is assumed to be
- reliable. */
- bool noack_mode = false;
+/* The size to align memory write packets, when practical. The protocol
+ does not guarantee any alignment, and gdb will generate short
+ writes and unaligned writes, but even as a best-effort attempt this
+ can improve bulk transfers. For instance, if a write is misaligned
+ relative to the target's data bus, the stub may need to make an extra
+ round trip fetching data from the target. This doesn't make a
+ huge difference, but it's easy to do, so we try to be helpful.
- /* True if we're connected in extended remote mode. */
- bool extended = false;
+ The alignment chosen is arbitrary; usually data bus width is
+ important here, not the possibly larger cache line size. */
+enum { REMOTE_ALIGN_WRITES = 16 };
- /* True if we resumed the target and we're waiting for the target to
- stop. In the mean time, we can't start another command/query.
- The remote server wouldn't be ready to process it, so we'd
- timeout waiting for a reply that would never come and eventually
- we'd close the connection. This can happen in asynchronous mode
- because we allow GDB commands while the target is running. */
- bool waiting_for_stop_reply = false;
+/* Prototypes for local functions. */
- /* The status of the stub support for the various vCont actions. */
- vCont_action_support supports_vCont;
+static int hexnumlen (ULONGEST num);
- /* True if the user has pressed Ctrl-C, but the target hasn't
- responded to that. */
- bool ctrlc_pending_p = false;
+static int stubhex (int ch);
- /* True if we saw a Ctrl-C while reading or writing from/to the
- remote descriptor. At that point it is not safe to send a remote
- interrupt packet, so we instead remember we saw the Ctrl-C and
- process it once we're done with sending/receiving the current
- packet, which should be shortly. If however that takes too long,
- and the user presses Ctrl-C again, we offer to disconnect. */
- bool got_ctrlc_during_io = false;
+static int hexnumstr (char *, ULONGEST);
- /* 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 = nullptr;
+static int hexnumnstr (char *, ULONGEST, int);
- /* 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 = null_ptid;
- ptid_t continue_thread = null_ptid;
+static CORE_ADDR remote_address_masked (CORE_ADDR);
- /* 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 = -1;
+static void print_packet (const char *);
- char *last_pass_packet = nullptr;
+static int stub_unpack_int (char *buff, int fieldlength);
- /* 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 = nullptr;
+struct packet_config;
- gdb_signal last_sent_signal = GDB_SIGNAL_0;
+static void show_packet_config_cmd (struct packet_config *config);
- bool last_sent_step = false;
+static void show_remote_protocol_packet_cmd (struct ui_file *file,
+ int from_tty,
+ struct cmd_list_element *c,
+ const char *value);
- /* The execution direction of the last resume we got. */
- exec_direction_kind last_resume_exec_dir = EXEC_FORWARD;
+static ptid_t read_ptid (const char *buf, const char **obuf);
- char *finished_object = nullptr;
- char *finished_annex = nullptr;
- ULONGEST finished_offset = 0;
+static void remote_async_inferior_event_handler (gdb_client_data);
- /* Should we try the 'ThreadInfo' query packet?
+static int remote_read_description_p (struct target_ops *target);
- 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). */
- bool use_threadinfo_query = false;
- bool use_threadextra_query = false;
+static void remote_console_output (char *msg);
- threadref echo_nextthread {};
- threadref nextthread {};
- threadref resultthreadlist[MAXTHREADLISTRESULTS] {};
+static void remote_btrace_reset (remote_state *rs);
- /* The state of remote notification. */
- struct remote_notif_state *notif_state = nullptr;
+static void remote_unpush_and_throw (void);
- /* The branch trace configuration. */
- struct btrace_config btrace_config {};
+/* For "remote". */
- /* The argument to the last "vFile:setfs:" packet we sent, used
- to avoid sending repeated unnecessary "vFile:setfs:" packets.
- Initialized to -1 to indicate that no "vFile:setfs:" packet
- has yet been sent. */
- int fs_pid = -1;
+static struct cmd_list_element *remote_cmdlist;
- /* A readahead cache for vFile:pread. Often, reading a binary
- involves a sequence of small reads. E.g., when parsing an ELF
- file. A readahead cache helps mostly the case of remote
- debugging on a connection with higher latency, due to the
- request/reply nature of the RSP. We only cache data for a single
- file descriptor at a time. */
- struct readahead_cache readahead_cache;
+/* For "set remote" and "show remote". */
-private:
- /* Mapping of remote protocol data for each gdbarch. Usually there
- is only one entry here, though we may see more with stubs that
- support multi-process. */
- std::unordered_map<struct gdbarch *,
- std::unique_ptr<struct remote_arch_state>>
- m_arch_states;
-};
+static struct cmd_list_element *remote_set_cmdlist;
+static struct cmd_list_element *remote_show_cmdlist;
+
+/* Controls whether GDB is willing to use range stepping. */
+
+static int use_range_stepping = 1;
+
+/* The max number of chars in debug output. The rest of chars are
+ omitted. */
+
+#define REMOTE_DEBUG_MAX_CHAR 512
/* Private data that we'll store in (struct thread_info)->priv. */
struct remote_thread_info : public private_thread_info
request, false if a continue request. */
int last_resume_step = 0;
- /* The signal specified in the last target_resume call for this
- thread. */
- gdb_signal last_resume_sig = GDB_SIGNAL_0;
-
- /* Whether this thread was already vCont-resumed on the remote
- side. */
- int vcont_resumed = 0;
-};
-
-remote_state::remote_state ()
-{
- /* The default buffer size is unimportant; it will be expanded
- whenever a larger buffer is needed. */
- this->buf_size = 400;
- this->buf = (char *) xmalloc (this->buf_size);
-}
-
-remote_state::~remote_state ()
-{
- xfree (this->last_pass_packet);
- xfree (this->last_program_signals_packet);
- xfree (this->buf);
- xfree (this->finished_object);
- xfree (this->finished_annex);
-}
-
-/* This data could be associated with a target, but we do not always
- 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 *
-get_remote_state_raw (void)
-{
- return remote_state;
-}
-
-/* Description of the remote protocol for a given architecture. */
-
-struct packet_reg
-{
- long offset; /* Offset into G packet. */
- 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);
- at present. */
- /* char *name; == gdbarch_register_name (target_gdbarch (), regnum);
- at present. */
-};
-
-struct remote_arch_state
-{
- explicit remote_arch_state (struct gdbarch *gdbarch);
-
- /* Description of the remote protocol registers. */
- long sizeof_g_packet;
-
- /* Description of the remote protocol registers indexed by REGNUM
- (making an array gdbarch_num_regs in size). */
- std::unique_ptr<packet_reg[]> regs;
-
- /* This is the size (in chars) of the first response to the ``g''
- packet. It is used as a heuristic when determining the maximum
- size of memory-read and memory-write packets. A target will
- typically only reserve a buffer large enough to hold the ``g''
- packet. The size does not include packet overhead (headers and
- trailers). */
- long actual_register_packet_size;
+ /* The signal specified in the last target_resume call for this
+ thread. */
+ gdb_signal last_resume_sig = GDB_SIGNAL_0;
- /* This is the maximum size (in chars) of a non read/write packet.
- It is also used as a cap on the size of read/write packets. */
- long remote_packet_size;
+ /* Whether this thread was already vCont-resumed on the remote
+ side. */
+ int vcont_resumed = 0;
};
+remote_state::remote_state ()
+{
+ /* The default buffer size is unimportant; it will be expanded
+ whenever a larger buffer is needed. */
+ this->buf_size = 400;
+ this->buf = (char *) xmalloc (this->buf_size);
+}
+
+remote_state::~remote_state ()
+{
+ xfree (this->last_pass_packet);
+ xfree (this->last_program_signals_packet);
+ xfree (this->buf);
+ xfree (this->finished_object);
+ xfree (this->finished_annex);
+}
+
/* Utility: generate error from an incoming stub packet. */
static void
trace_error (char *buf)
/* Utility: wait for reply from stub, while accepting "O" packets. */
-static char *
-remote_get_noisy_reply ()
+char *
+remote_target::remote_get_noisy_reply ()
{
struct remote_state *rs = get_remote_state ();
struct remote_arch_state *
remote_state::get_remote_arch_state (struct gdbarch *gdbarch)
{
- auto &rsa = this->m_arch_states[gdbarch];
- if (rsa == nullptr)
+ remote_arch_state *rsa;
+
+ auto it = this->m_arch_states.find (gdbarch);
+ if (it == this->m_arch_states.end ())
{
- rsa.reset (new remote_arch_state (gdbarch));
+ auto p = this->m_arch_states.emplace (std::piecewise_construct,
+ std::forward_as_tuple (gdbarch),
+ std::forward_as_tuple (gdbarch));
+ rsa = &p.first->second;
/* Make sure that the packet buffer is plenty big enough for
this architecture. */
this->buf = (char *) xrealloc (this->buf, this->buf_size);
}
}
- return rsa.get ();
+ else
+ rsa = &it->second;
+
+ return rsa;
}
/* Fetch the global remote target state. */
-static struct remote_state *
-get_remote_state (void)
+remote_state *
+remote_target::get_remote_state ()
{
- struct remote_state *rs = get_remote_state_raw ();
-
/* Make sure that the remote architecture state has been
initialized, because doing so might reallocate rs->buf. Any
function which calls getpkt also needs to be mindful of changes
to rs->buf, but this call limits the number of places which run
into trouble. */
- rs->get_remote_arch_state (target_gdbarch ());
+ m_remote_state.get_remote_arch_state (target_gdbarch ());
- return rs;
+ return &m_remote_state;
}
/* Cleanup routine for the remote module's pspace data. */
this->remote_packet_size = (this->sizeof_g_packet * 2 + 32);
}
+/* Get a pointer to the current remote target. If not connected to a
+ remote target, return NULL. */
+
+static remote_target *
+get_current_remote_target ()
+{
+ target_ops *proc_target = find_target_at (process_stratum);
+ return dynamic_cast<remote_target *> (proc_target);
+}
+
/* Return the current allowed size of a remote packet. This is
inferred from the current architecture, and should be used to
limit the length of outgoing packets. */
-static long
-get_remote_packet_size (void)
+long
+remote_target::get_remote_packet_size ()
{
struct remote_state *rs = get_remote_state ();
remote_arch_state *rsa = rs->get_remote_arch_state (target_gdbarch ());
return NULL;
}
-static remote_target remote_ops;
-
-static extended_remote_target extended_remote_ops;
-
-/* FIXME: cagney/1999-09-23: Even though getpkt was called with
- ``forever'' still use the normal timeout mechanism. This is
- currently used by the ASYNC code to guarentee that target reads
- during the initial connect always time-out. Once getpkt has been
- modified to return a timeout indication and, in turn
- remote_wait()/wait_for_inferior() have gained a timeout parameter
- this can go away. */
-static int wait_forever_enabled_p = 1;
-
/* Allow the user to specify what sequence to send to the remote
when he requests a program interruption: Although ^C is usually
what remote systems expect (this is the default, here), it is
int fixed_p;
};
-/* The default max memory-write-packet-size. The 16k is historical.
- (It came from older GDB's using alloca for buffers and the
- knowledge (folklore?) that some hosts don't cope very well with
- large alloca calls.) */
-#define DEFAULT_MAX_MEMORY_PACKET_SIZE 16384
+/* The default max memory-write-packet-size, when the setting is
+ "fixed". The 16k is historical. (It came from older GDB's using
+ alloca for buffers and the knowledge (folklore?) that some hosts
+ don't cope very well with large alloca calls.) */
+#define DEFAULT_MAX_MEMORY_PACKET_SIZE_FIXED 16384
/* The minimum remote packet size for memory transfers. Ensures we
can write at least one byte. */
#define MIN_MEMORY_PACKET_SIZE 20
+/* Get the memory packet size, assuming it is fixed. */
+
+static long
+get_fixed_memory_packet_size (struct memory_packet_config *config)
+{
+ gdb_assert (config->fixed_p);
+
+ if (config->size <= 0)
+ return DEFAULT_MAX_MEMORY_PACKET_SIZE_FIXED;
+ else
+ return config->size;
+}
+
/* Compute the current size of a read/write packet. Since this makes
use of ``actual_register_packet_size'' the computation is dynamic. */
-static long
-get_memory_packet_size (struct memory_packet_config *config)
+long
+remote_target::get_memory_packet_size (struct memory_packet_config *config)
{
struct remote_state *rs = get_remote_state ();
remote_arch_state *rsa = rs->get_remote_arch_state (target_gdbarch ());
long what_they_get;
if (config->fixed_p)
- {
- if (config->size <= 0)
- what_they_get = DEFAULT_MAX_MEMORY_PACKET_SIZE;
- else
- what_they_get = config->size;
- }
+ what_they_get = get_fixed_memory_packet_size (config);
else
{
what_they_get = get_remote_packet_size ();
something arbitrarily large. */
}
- /* So that the query shows the correct value. */
- if (size <= 0)
- size = DEFAULT_MAX_MEMORY_PACKET_SIZE;
-
/* Extra checks? */
if (fixed_p && !config->fixed_p)
{
+ /* So that the query shows the correct value. */
+ long query_size = (size <= 0
+ ? DEFAULT_MAX_MEMORY_PACKET_SIZE_FIXED
+ : size);
+
if (! query (_("The target may not be able to correctly handle a %s\n"
"of %ld bytes. Change the packet size? "),
- config->name, size))
+ config->name, query_size))
error (_("Packet size not changed."));
}
/* Update the config. */
static void
show_memory_packet_size (struct memory_packet_config *config)
{
- printf_filtered (_("The %s is %ld. "), config->name, config->size);
+ if (config->size == 0)
+ printf_filtered (_("The %s is 0 (default). "), config->name);
+ else
+ printf_filtered (_("The %s is %ld. "), config->name, config->size);
if (config->fixed_p)
printf_filtered (_("Packets are fixed at %ld bytes.\n"),
- get_memory_packet_size (config));
+ get_fixed_memory_packet_size (config));
else
- printf_filtered (_("Packets are limited to %ld bytes.\n"),
- get_memory_packet_size (config));
+ {
+ remote_target *remote = get_current_remote_target ();
+
+ if (remote != NULL)
+ printf_filtered (_("Packets are limited to %ld bytes.\n"),
+ remote->get_memory_packet_size (config));
+ else
+ puts_filtered ("The actual limit will be further reduced "
+ "dependent on the target.\n");
+ }
}
static struct memory_packet_config memory_write_packet_config =
show_memory_packet_size (&memory_write_packet_config);
}
-static long
-get_memory_write_packet_size (void)
+long
+remote_target::get_memory_write_packet_size ()
{
return get_memory_packet_size (&memory_write_packet_config);
}
show_memory_packet_size (&memory_read_packet_config);
}
-static long
-get_memory_read_packet_size (void)
+long
+remote_target::get_memory_read_packet_size ()
{
long size = get_memory_packet_size (&memory_read_packet_config);
}
\f
-/* Generic configuration support for packets the stub optionally
- supports. Allows the user to specify the use of the packet as well
- as allowing GDB to auto-detect support in the remote stub. */
-
-enum packet_support
- {
- PACKET_SUPPORT_UNKNOWN = 0,
- PACKET_ENABLE,
- PACKET_DISABLE
- };
struct packet_config
{
enum packet_support support;
};
-/* Analyze a packet's return value and update the packet config
- accordingly. */
-
-enum packet_result
-{
- PACKET_ERROR,
- PACKET_OK,
- PACKET_UNKNOWN
-};
-
static enum packet_support packet_config_support (struct packet_config *config);
static enum packet_support packet_support (int packet);
return 0;
}
-\f
-/* Asynchronous signal handle registered as event loop source for
- when we have pending events ready to be passed to the core. */
-
-static struct async_event_handler *remote_async_inferior_event_token;
-
\f
static ptid_t magic_null_ptid;
/* Find out if the stub attached to PID (and hence GDB should offer to
detach instead of killing it when bailing out). */
-static int
-remote_query_attached (int pid)
+int
+remote_target::remote_query_attached (int pid)
{
struct remote_state *rs = get_remote_state ();
size_t size = get_remote_packet_size ();
attempt to open this inferior's executable as the main executable
if no main executable is open already. */
-static struct inferior *
-remote_add_inferior (int fake_pid_p, int pid, int attached,
- int try_open_exec)
+inferior *
+remote_target::remote_add_inferior (int fake_pid_p, int pid, int attached,
+ int try_open_exec)
{
struct inferior *inf;
}
static remote_thread_info *get_remote_thread_info (thread_info *thread);
+static remote_thread_info *get_remote_thread_info (ptid_t ptid);
/* Add thread PTID to GDB's thread list. Tag it as executing/running
according to RUNNING. */
-static void
-remote_add_thread (ptid_t ptid, int running, int executing)
+thread_info *
+remote_target::remote_add_thread (ptid_t ptid, bool running, bool executing)
{
struct remote_state *rs = get_remote_state ();
struct thread_info *thread;
get_remote_thread_info (thread)->vcont_resumed = executing;
set_executing (ptid, executing);
set_running (ptid, running);
+
+ return thread;
}
/* Come here when we learn about a thread id from the remote target.
GDB's inferior list as well. EXECUTING indicates whether the
thread is (internally) executing or stopped. */
-static void
-remote_notice_new_inferior (ptid_t currthread, int executing)
+void
+remote_target::remote_notice_new_inferior (ptid_t currthread, int executing)
{
/* In non-stop mode, we assume new found threads are (externally)
running until proven otherwise with a stop reply. In all-stop,
/* If this is a new thread, add it to GDB's thread list.
If we leave it up to WFI to do this, bad things will happen. */
- if (in_thread_list (currthread) && is_exited (currthread))
+ thread_info *tp = find_thread_ptid (currthread);
+ if (tp != NULL && tp->state == THREAD_EXITED)
{
/* We're seeing an event on a thread id we knew had exited.
This has to be a new thread reusing the old id. Add it. */
stub doesn't support qC. This is the first stop reported
after an attach, so this is the main thread. Update the
ptid in the thread list. */
- if (in_thread_list (pid_to_ptid (pid)))
+ if (in_thread_list (ptid_t (pid)))
thread_change_ptid (inferior_ptid, currthread);
else
{
extended-remote which already was debugging an inferior, we
may not know about it yet. Add it before adding its child
thread, so notifications are emitted in a sensible order. */
- if (!in_inferior_list (ptid_get_pid (currthread)))
+ if (find_inferior_pid (ptid_get_pid (currthread)) == NULL)
{
struct remote_state *rs = get_remote_state ();
int fake_pid_p = !remote_multi_process_p (rs);
}
/* This is really a new thread. Add it. */
- remote_add_thread (currthread, running, executing);
+ thread_info *new_thr
+ = remote_add_thread (currthread, running, executing);
/* If we found a new inferior, let the common code do whatever
it needs to with it (e.g., read shared libraries, insert
struct remote_state *rs = get_remote_state ();
if (!rs->starting_up)
- notice_new_inferior (currthread, executing, 0);
+ notice_new_inferior (new_thr, executing, 0);
}
}
}
return static_cast<remote_thread_info *> (thread->priv.get ());
}
-/* Return PTID's private thread data, creating it if necessary. */
-
static remote_thread_info *
get_remote_thread_info (ptid_t ptid)
{
- struct thread_info *info = find_thread_ptid (ptid);
-
- return get_remote_thread_info (info);
+ thread_info *thr = find_thread_ptid (ptid);
+ return get_remote_thread_info (thr);
}
/* Call this function as a result of
MINUS_ONE_PTID, set the thread to -1, so the stub returns the
thread. If GEN is set, set the general thread, if not, then set
the step/continue thread. */
-static void
-set_thread (ptid_t ptid, int gen)
+void
+remote_target::set_thread (ptid_t ptid, int gen)
{
struct remote_state *rs = get_remote_state ();
ptid_t state = gen ? rs->general_thread : rs->continue_thread;
rs->continue_thread = ptid;
}
-static void
-set_general_thread (ptid_t ptid)
+void
+remote_target::set_general_thread (ptid_t ptid)
{
set_thread (ptid, 1);
}
-static void
-set_continue_thread (ptid_t ptid)
+void
+remote_target::set_continue_thread (ptid_t ptid)
{
set_thread (ptid, 0);
}
general operations is the process the selected general thread
belongs to. */
-static void
-set_general_process (void)
+void
+remote_target::set_general_process ()
{
struct remote_state *rs = get_remote_state ();
static char *pack_threadinfo_request (char *pkt, int mode,
threadref *id);
-static int remote_unpack_thread_info_response (char *pkt,
- threadref *expectedref,
- struct gdb_ext_thread_info
- *info);
-
-
-static int remote_get_threadinfo (threadref *threadid,
- int fieldset, /*TAG mask */
- struct gdb_ext_thread_info *info);
-
static char *pack_threadlist_request (char *pkt, int startflag,
int threadcount,
threadref *nextthread);
-static int parse_threadlist_response (char *pkt,
- int result_limit,
- threadref *original_echo,
- threadref *resultlist,
- int *doneflag);
-
-static int remote_get_threadlist (int startflag,
- threadref *nextthread,
- int result_limit,
- int *done,
- int *result_count,
- threadref *threadlist);
-
-typedef int (*rmt_thread_action) (threadref *ref, void *context);
-
-static int remote_threadlist_iterator (rmt_thread_action stepfunction,
- void *context, int looplimit);
-
static int remote_newthread_step (threadref *ref, void *context);
buffer we're allowed to write to. Returns
BUF+CHARACTERS_WRITTEN. */
-static char *
-write_ptid (char *buf, const char *endbuf, ptid_t ptid)
+char *
+remote_target::write_ptid (char *buf, const char *endbuf, ptid_t ptid)
{
int pid, tid;
struct remote_state *rs = get_remote_state ();
pp = unpack_varlen_hex (p + 1, &tid);
if (obuf)
*obuf = pp;
- return ptid_build (pid, tid, 0);
+ return ptid_t (pid, tid, 0);
}
/* No multi-process. Just a tid. */
if (obuf)
*obuf = pp;
- return ptid_build (pid, tid, 0);
+ return ptid_t (pid, tid, 0);
}
static int
#define TAG_MOREDISPLAY 16 /* Whatever the kernel wants to say about
the process. */
-static int
-remote_unpack_thread_info_response (char *pkt, threadref *expectedref,
- struct gdb_ext_thread_info *info)
+int
+remote_target::remote_unpack_thread_info_response (char *pkt,
+ threadref *expectedref,
+ gdb_ext_thread_info *info)
{
struct remote_state *rs = get_remote_state ();
int mask, length;
return retval;
}
-static int
-remote_get_threadinfo (threadref *threadid, int fieldset, /* TAG mask */
- struct gdb_ext_thread_info *info)
+int
+remote_target::remote_get_threadinfo (threadref *threadid,
+ int fieldset,
+ gdb_ext_thread_info *info)
{
struct remote_state *rs = get_remote_state ();
int result;
/* Encoding: 'q':8,'M':8,count:16,done:8,argthreadid:64,(threadid:64)* */
-static int
-parse_threadlist_response (char *pkt, int result_limit,
- threadref *original_echo, threadref *resultlist,
- int *doneflag)
+int
+remote_target::parse_threadlist_response (char *pkt, int result_limit,
+ threadref *original_echo,
+ threadref *resultlist,
+ int *doneflag)
{
struct remote_state *rs = get_remote_state ();
char *limit;
/* Fetch the next batch of threads from the remote. Returns -1 if the
qL packet is not supported, 0 on error and 1 on success. */
-static int
-remote_get_threadlist (int startflag, threadref *nextthread, int result_limit,
- int *done, int *result_count, threadref *threadlist)
+int
+remote_target::remote_get_threadlist (int startflag, threadref *nextthread,
+ int result_limit, int *done, int *result_count,
+ threadref *threadlist)
{
struct remote_state *rs = get_remote_state ();
int result = 1;
STEPFUNCTION returns false. If the packet is not supported,
returns -1. */
-static int
-remote_threadlist_iterator (rmt_thread_action stepfunction, void *context,
- int looplimit)
+int
+remote_target::remote_threadlist_iterator (rmt_thread_action stepfunction,
+ void *context, int looplimit)
{
struct remote_state *rs = get_remote_state ();
int done, i, result_count;
#define CRAZY_MAX_THREADS 1000
-static ptid_t
-remote_current_thread (ptid_t oldpid)
+ptid_t
+remote_target::remote_current_thread (ptid_t oldpid)
{
struct remote_state *rs = get_remote_state ();
/* List remote threads using the deprecated qL packet. */
-static int
-remote_get_threads_with_ql (struct target_ops *ops,
- struct threads_listing_context *context)
+int
+remote_target::remote_get_threads_with_ql (threads_listing_context *context)
{
if (remote_threadlist_iterator (remote_newthread_step, context,
CRAZY_MAX_THREADS) >= 0)
/* List remote threads using qXfer:threads:read. */
-static int
-remote_get_threads_with_qxfer (struct target_ops *ops,
- struct threads_listing_context *context)
+int
+remote_target::remote_get_threads_with_qxfer (threads_listing_context *context)
{
#if defined(HAVE_LIBEXPAT)
if (packet_support (PACKET_qXfer_threads) == PACKET_ENABLE)
{
gdb::optional<gdb::char_vector> xml
- = target_read_stralloc (ops, TARGET_OBJECT_THREADS, NULL);
+ = target_read_stralloc (this, TARGET_OBJECT_THREADS, NULL);
if (xml && (*xml)[0] != '\0')
{
/* List remote threads using qfThreadInfo/qsThreadInfo. */
-static int
-remote_get_threads_with_qthreadinfo (struct target_ops *ops,
- struct threads_listing_context *context)
+int
+remote_target::remote_get_threads_with_qthreadinfo (threads_listing_context *context)
{
struct remote_state *rs = get_remote_state ();
/* We have a few different mechanisms to fetch the thread list. Try
them all, starting with the most preferred one first, falling
back to older methods. */
- if (remote_get_threads_with_qxfer (this, &context)
- || remote_get_threads_with_qthreadinfo (this, &context)
- || remote_get_threads_with_ql (this, &context))
+ if (remote_get_threads_with_qxfer (&context)
+ || remote_get_threads_with_qthreadinfo (&context)
+ || remote_get_threads_with_ql (&context))
{
struct thread_info *tp, *tmp;
if (!context.contains_thread (tp->ptid))
{
/* Not found. */
- delete_thread (tp->ptid);
+ delete_thread (tp);
}
}
remote_notice_new_inferior (item.ptid, executing);
- remote_thread_info *info = get_remote_thread_info (item.ptid);
+ thread_info *tp = find_thread_ptid (item.ptid);
+ remote_thread_info *info = get_remote_thread_info (tp);
info->core = item.core;
info->extra = std::move (item.extra);
info->name = std::move (item.name);
remote_target::extra_thread_info (thread_info *tp)
{
struct remote_state *rs = get_remote_state ();
- int result;
int set;
threadref id;
struct gdb_ext_thread_info threadinfo;
- static char display_buf[100]; /* arbitrary... */
- int n = 0; /* position in display_buf */
if (rs->remote_desc == 0) /* paranoia */
internal_error (__FILE__, __LINE__,
server doesn't know about it. */
return NULL;
+ std::string &extra = get_remote_thread_info (tp)->extra;
+
+ /* If already have cached info, use it. */
+ if (!extra.empty ())
+ return extra.c_str ();
+
if (packet_support (PACKET_qXfer_threads) == PACKET_ENABLE)
{
- struct thread_info *info = find_thread_ptid (tp->ptid);
-
- if (info != NULL && info->priv != NULL)
- {
- const std::string &extra = get_remote_thread_info (info)->extra;
- return !extra.empty () ? extra.c_str () : NULL;
- }
- else
- return NULL;
+ /* If we're using qXfer:threads:read, then the extra info is
+ included in the XML. So if we didn't have anything cached,
+ it's because there's really no extra info. */
+ return NULL;
}
if (rs->use_threadextra_query)
getpkt (&rs->buf, &rs->buf_size, 0);
if (rs->buf[0] != 0)
{
- n = std::min (strlen (rs->buf) / 2, sizeof (display_buf));
- result = hex2bin (rs->buf, (gdb_byte *) display_buf, n);
- display_buf [result] = '\0';
- return display_buf;
+ extra.resize (strlen (rs->buf) / 2);
+ hex2bin (rs->buf, (gdb_byte *) &extra[0], extra.size ());
+ return extra.c_str ();
}
}
if (threadinfo.active)
{
if (*threadinfo.shortname)
- n += xsnprintf (&display_buf[0], sizeof (display_buf) - n,
- " Name: %s,", threadinfo.shortname);
+ string_appendf (extra, " Name: %s", threadinfo.shortname);
if (*threadinfo.display)
- n += xsnprintf (&display_buf[n], sizeof (display_buf) - n,
- " State: %s,", threadinfo.display);
+ {
+ if (!extra.empty ())
+ extra += ',';
+ string_appendf (extra, " State: %s", threadinfo.display);
+ }
if (*threadinfo.more_display)
- n += xsnprintf (&display_buf[n], sizeof (display_buf) - n,
- " Priority: %s", threadinfo.more_display);
-
- if (n > 0)
{
- /* For purely cosmetic reasons, clear up trailing commas. */
- if (',' == display_buf[n-1])
- display_buf[n-1] = ' ';
- return display_buf;
+ if (!extra.empty ())
+ extra += ',';
+ string_appendf (extra, " Priority: %s", threadinfo.more_display);
}
+ return extra.c_str ();
}
return NULL;
}
ptid_t
remote_target::get_ada_task_ptid (long lwp, long thread)
{
- return ptid_build (ptid_get_pid (inferior_ptid), lwp, 0);
+ return ptid_t (ptid_get_pid (inferior_ptid), lwp, 0);
}
\f
/* Restart the remote side; this is an extended protocol operation. */
-static void
-extended_remote_restart (void)
+void
+remote_target::extended_remote_restart ()
{
struct remote_state *rs = get_remote_state ();
void
remote_target::close ()
{
- 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. */
terminal_ours ();
- 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.
Reset inferior_ptid to null_ptid first, as otherwise has_stack_frame
inferior_ptid = null_ptid;
discard_all_inferiors ();
- /* We are closing the remote target, so we should discard
+ trace_reset_local_state ();
+
+ delete this;
+}
+
+remote_target::~remote_target ()
+{
+ struct remote_state *rs = get_remote_state ();
+
+ /* Check for NULL because we may get here with a partially
+ constructed target/connection. */
+ if (rs->remote_desc == nullptr)
+ return;
+
+ serial_close (rs->remote_desc);
+
+ /* We are destroying the remote target, so we should discard
everything of this target. */
- discard_pending_stop_replies_in_queue (rs);
+ discard_pending_stop_replies_in_queue ();
- if (remote_async_inferior_event_token)
- delete_async_event_handler (&remote_async_inferior_event_token);
+ if (rs->remote_async_inferior_event_token)
+ delete_async_event_handler (&rs->remote_async_inferior_event_token);
remote_notif_state_xfree (rs->notif_state);
-
- trace_reset_local_state ();
}
/* Query the remote side for the text, data and bss offsets. */
-static void
-get_offsets (void)
+void
+remote_target::get_offsets ()
{
struct remote_state *rs = get_remote_state ();
char *buf;
}
/* Send interrupt_sequence to remote target. */
-static void
-send_interrupt_sequence (void)
+
+void
+remote_target::send_interrupt_sequence ()
{
struct remote_state *rs = get_remote_state ();
ask the remote which is the current thread with qC. The former
method avoids a roundtrip. */
-static ptid_t
-get_current_thread (char *wait_status)
+ptid_t
+remote_target::get_current_thread (char *wait_status)
{
ptid_t ptid = null_ptid;
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 (char *wait_status)
+void
+remote_target::add_current_inferior_and_thread (char *wait_status)
{
struct remote_state *rs = get_remote_state ();
int fake_pid_p = 0;
{
struct target_waitstatus *ws = &thread->suspend.waitstatus;
- switch_to_thread (thread->ptid);
- stop_pc = get_frame_pc (get_current_frame ());
+ switch_to_thread (thread);
+ thread->suspend.stop_pc = get_frame_pc (get_current_frame ());
set_current_sal_from_frame (get_current_frame ());
thread->suspend.waitstatus_pending_p = 0;
on initial connection. We mark these threads as stopped and print
their current frame before giving the user the prompt. */
-static void
-process_initial_stop_replies (int from_tty)
+void
+remote_target::process_initial_stop_replies (int from_tty)
{
int pending_stop_replies = stop_reply_queue_length ();
struct inferior *inf;
if (non_stop)
{
- thread = any_live_thread_of_process (inf->pid);
- notice_new_inferior (thread->ptid,
- thread->state == THREAD_RUNNING,
+ thread = any_live_thread_of_inferior (inf);
+ notice_new_inferior (thread, thread->state == THREAD_RUNNING,
from_tty);
}
}
if (inf->needs_setup)
{
- thread = any_live_thread_of_process (inf->pid);
+ thread = any_live_thread_of_inferior (inf);
switch_to_thread_no_regs (thread);
setup_inferior (0);
}
first = thread;
if (!non_stop)
- set_running (thread->ptid, 0);
+ thread->set_running (false);
else if (thread->state != THREAD_STOPPED)
continue;
/* 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_parse (this, notif, rs->buf);
remote_notif_get_pending_events (notif);
}
/* Symbol look-up. */
-static void
-remote_check_symbols (void)
+void
+remote_target::remote_check_symbols ()
{
char *msg, *reply, *tmp;
int end;
instead of any data function descriptor. */
sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch (),
sym_addr,
- target_stack);
+ current_top_target ());
xsnprintf (msg, get_remote_packet_size (), "qSymbol:%s:%s",
phex_nz (sym_addr, addr_size), &reply[8]);
not reported). The third argument may be NULL; if not NULL, it
is a NUL-terminated string taken from the packet following
this feature's name and an equals sign. */
- void (*func) (const struct protocol_feature *, enum packet_support,
- const char *);
+ void (*func) (remote_target *remote, const struct protocol_feature *,
+ enum packet_support, const char *);
/* The corresponding packet for this feature. Only used if
FUNC is remote_supported_packet. */
};
static void
-remote_supported_packet (const struct protocol_feature *feature,
+remote_supported_packet (remote_target *remote,
+ const struct protocol_feature *feature,
enum packet_support support,
const char *argument)
{
remote_protocol_packets[feature->packet].support = support;
}
-static void
-remote_packet_size (const struct protocol_feature *feature,
- enum packet_support support, const char *value)
+void
+remote_target::remote_packet_size (const protocol_feature *feature,
+ enum packet_support support, const char *value)
{
struct remote_state *rs = get_remote_state ();
rs->explicit_packet_size = packet_size;
}
+void
+remote_packet_size (remote_target *remote, const protocol_feature *feature,
+ enum packet_support support, const char *value)
+{
+ remote->remote_packet_size (feature, support, value);
+}
+
static const struct protocol_feature remote_protocol_features[] = {
{ "PacketSize", PACKET_DISABLE, remote_packet_size, -1 },
{ "qXfer:auxv:read", PACKET_DISABLE, remote_supported_packet,
msg->append (append);
}
-static void
-remote_query_supported (void)
+void
+remote_target::remote_query_supported ()
{
struct remote_state *rs = get_remote_state ();
char *next;
seen[i] = 1;
feature = &remote_protocol_features[i];
- feature->func (feature, is_supported, value);
+ feature->func (this, feature, is_supported, value);
break;
}
}
const struct protocol_feature *feature;
feature = &remote_protocol_features[i];
- feature->func (feature, feature->default_support, NULL);
+ feature->func (this, feature, feature->default_support, NULL);
}
}
is probably wedged --- offer to quit/disconnect.
*/
-static void
-remote_serial_quit_handler (void)
+void
+remote_target::remote_serial_quit_handler ()
{
struct remote_state *rs = get_remote_state ();
}
}
+/* The remote_target that is current while the quit handler is
+ overridden with remote_serial_quit_handler. */
+static remote_target *curr_quit_handler_target;
+
+static void
+remote_serial_quit_handler ()
+{
+ curr_quit_handler_target->remote_serial_quit_handler ();
+}
+
/* Remove any of the remote.c targets from target stack. Upper targets depend
on it so remove them first. */
void
remote_target::open_1 (const char *name, int from_tty, int extended_p)
{
- struct remote_state *rs = get_remote_state ();
+ remote_target *curr_remote = get_current_remote_target ();
if (name == 0)
error (_("To open a remote debug connection, you need to specify what\n"
"serial device is attached to the remote system\n"
"(e.g. /dev/ttyS0, /dev/ttya, COM1, etc.)."));
- /* See FIXME above. */
- if (!target_async_permitted)
- wait_forever_enabled_p = 1;
-
/* If we're connected to a running target, target_preopen will kill it.
Ask this question first, before target_preopen has a chance to kill
anything. */
- if (rs->remote_desc != NULL && !have_inferiors ())
+ if (curr_remote != NULL && !have_inferiors ())
{
if (from_tty
&& !query (_("Already connected to a remote target. Disconnect? ")))
/* Here the possibly existing remote target gets unpushed. */
target_preopen (from_tty);
- /* Make sure we send the passed signals list the next time we resume. */
- xfree (rs->last_pass_packet);
- rs->last_pass_packet = NULL;
-
- /* Make sure we send the program signals list the next time we
- resume. */
- xfree (rs->last_program_signals_packet);
- rs->last_program_signals_packet = NULL;
-
remote_fileio_reset ();
reopen_exec_file ();
reread_symbols ();
+ remote_target *remote
+ = (extended_p ? new extended_remote_target () : new remote_target ());
+ target_ops_up target_holder (remote);
+
+ remote_state *rs = remote->get_remote_state ();
+
+ /* See FIXME above. */
+ if (!target_async_permitted)
+ rs->wait_forever_enabled_p = 1;
+
rs->remote_desc = remote_serial_open (name);
if (!rs->remote_desc)
perror_with_name (name);
puts_filtered ("\n");
}
- remote_target *target
- = extended_p ? &extended_remote_ops : &remote_ops;
- push_target (target); /* Switch to using remote target now. */
+ /* Switch to using the remote target now. */
+ push_target (remote);
+ /* The target stack owns the target now. */
+ target_holder.release ();
/* Register extra event sources in the event loop. */
- remote_async_inferior_event_token
+ rs->remote_async_inferior_event_token
= create_async_event_handler (remote_async_inferior_event_handler,
- NULL);
- rs->notif_state = remote_notif_state_allocate ();
+ remote);
+ rs->notif_state = remote_notif_state_allocate (remote);
/* Reset the target state; these things will be queried either by
remote_query_supported or as they are needed. */
around this. Eventually a mechanism that allows
wait_for_inferior() to expect/get timeouts will be
implemented. */
- wait_forever_enabled_p = 0;
+ rs->wait_forever_enabled_p = 0;
}
/* First delete any symbols previously loaded from shared libraries. */
TRY
{
- target->start_remote (from_tty, extended_p);
+ remote->start_remote (from_tty, extended_p);
}
CATCH (ex, RETURN_MASK_ALL)
{
/* Pop the partially set up target - unless something else did
already before throwing the exception. */
- if (rs->remote_desc != NULL)
+ if (ex.error != TARGET_CLOSE_ERROR)
remote_unpush_target ();
- if (target_async_permitted)
- wait_forever_enabled_p = 1;
throw_exception (ex);
}
END_CATCH
}
- remote_btrace_reset ();
+ remote_btrace_reset (rs);
if (target_async_permitted)
- wait_forever_enabled_p = 1;
+ rs->wait_forever_enabled_p = 1;
}
/* Detach the specified process. */
-static void
-remote_detach_pid (int pid)
+void
+remote_target::remote_detach_pid (int pid)
{
struct remote_state *rs = get_remote_state ();
any breakpoints in the target program or it'll die when it hits
one. */
-static void
-remote_detach_1 (int from_tty, inferior *inf)
+void
+remote_target::remote_detach_1 (inferior *inf, int from_tty)
{
int pid = ptid_get_pid (inferior_ptid);
struct remote_state *rs = get_remote_state ();
- struct thread_info *tp = find_thread_ptid (inferior_ptid);
int is_fork_parent;
if (!target_has_execution)
if (from_tty && !rs->extended && number_of_live_inferiors () == 1)
puts_filtered (_("Ending remote debugging.\n"));
+ struct thread_info *tp = find_thread_ptid (inferior_ptid);
+
/* Check to see if we are detaching a fork parent. Note that if we
are detaching a fork child, tp == NULL. */
is_fork_parent = (tp != NULL
{
/* Save the pid as a string before mourning, since that will
unpush the remote target, and we need the string after. */
- std::string infpid = target_pid_to_str (pid_to_ptid (pid));
+ std::string infpid = target_pid_to_str (ptid_t (pid));
target_mourn_inferior (inferior_ptid);
if (print_inferior_events)
else
{
inferior_ptid = null_ptid;
- detach_inferior (pid);
+ detach_inferior (current_inferior ());
}
}
void
remote_target::detach (inferior *inf, int from_tty)
{
- remote_detach_1 (from_tty, inf);
+ remote_detach_1 (inf, from_tty);
}
void
extended_remote_target::detach (inferior *inf, int from_tty)
{
- remote_detach_1 (from_tty, inf);
+ remote_detach_1 (inf, from_tty);
}
/* Target follow-fork function for remote targets. On entry, and
if (exec_file)
printf_unfiltered (_("Attaching to program: %s, %s\n"), exec_file,
- target_pid_to_str (pid_to_ptid (pid)));
+ target_pid_to_str (ptid_t (pid)));
else
printf_unfiltered (_("Attaching to %s\n"),
- target_pid_to_str (pid_to_ptid (pid)));
+ target_pid_to_str (ptid_t (pid)));
gdb_flush (gdb_stdout);
}
}
else if (strcmp (rs->buf, "OK") != 0)
error (_("Attaching to %s failed with: %s"),
- target_pid_to_str (pid_to_ptid (pid)),
+ target_pid_to_str (ptid_t (pid)),
rs->buf);
break;
case PACKET_UNKNOWN:
error (_("This target does not support attaching to a process"));
default:
error (_("Attaching to %s failed"),
- target_pid_to_str (pid_to_ptid (pid)));
+ target_pid_to_str (ptid_t (pid)));
}
set_current_inferior (remote_add_inferior (0, pid, 1, 0));
- inferior_ptid = pid_to_ptid (pid);
+ inferior_ptid = ptid_t (pid);
if (target_is_non_stop_p ())
{
/* Get list of threads. */
update_thread_list ();
- thread = first_thread_of_process (pid);
+ thread = first_thread_of_inferior (current_inferior ());
if (thread)
inferior_ptid = thread->ptid;
else
- inferior_ptid = pid_to_ptid (pid);
+ inferior_ptid = ptid_t (pid);
/* Invalidate our notion of the remote current thread. */
record_currthread (rs, minus_one_ptid);
if (target_can_async_p ())
{
struct notif_event *reply
- = remote_notif_parse (¬if_client_stop, wait_status);
+ = remote_notif_parse (this, ¬if_client_stop, wait_status);
push_stop_reply ((struct stop_reply *) reply);
/* Check for the availability of vCont. This function should also check
the response. */
-static void
-remote_vcont_probe (struct remote_state *rs)
+void
+remote_target::remote_vcont_probe ()
{
+ remote_state *rs = get_remote_state ();
char *buf;
strcpy (rs->buf, "vCont?");
the thread to be stepped and/or signalled is given in the global
INFERIOR_PTID. */
-static char *
-append_resumption (char *p, char *endp,
- ptid_t ptid, int step, enum gdb_signal siggnal)
+char *
+remote_target::append_resumption (char *p, char *endp,
+ ptid_t ptid, int step, gdb_signal siggnal)
{
struct remote_state *rs = get_remote_state ();
ptid_t nptid;
/* All (-1) threads of process. */
- nptid = ptid_build (ptid_get_pid (ptid), -1, 0);
+ nptid = ptid_t (ptid_get_pid (ptid), -1, 0);
p += xsnprintf (p, endp - p, ":");
p = write_ptid (p, endp, nptid);
/* Append a vCont continue-with-signal action for threads that have a
non-zero stop signal. */
-static char *
-append_pending_thread_resumptions (char *p, char *endp, ptid_t ptid)
+char *
+remote_target::append_pending_thread_resumptions (char *p, char *endp,
+ ptid_t ptid)
{
struct thread_info *thread;
/* Set the target running, using the packets that use Hc
(c/s/C/S). */
-static void
-remote_resume_with_hc (struct target_ops *ops,
- ptid_t ptid, int step, enum gdb_signal siggnal)
+void
+remote_target::remote_resume_with_hc (ptid_t ptid, int step,
+ gdb_signal siggnal)
{
struct remote_state *rs = get_remote_state ();
struct thread_info *thread;
resume_clear_thread_private_info (thread);
buf = rs->buf;
- if (execution_direction == EXEC_REVERSE)
+ if (::execution_direction == EXEC_REVERSE)
{
/* We don't pass signals to the target in reverse exec mode. */
if (info_verbose && siggnal != GDB_SIGNAL_0)
This function issues a strict subset of all possible vCont commands
at the moment. */
-static int
-remote_resume_with_vcont (ptid_t ptid, int step, enum gdb_signal siggnal)
+int
+remote_target::remote_resume_with_vcont (ptid_t ptid, int step,
+ enum gdb_signal siggnal)
{
struct remote_state *rs = get_remote_state ();
char *p;
char *endp;
/* No reverse execution actions defined for vCont. */
- if (execution_direction == EXEC_REVERSE)
+ if (::execution_direction == EXEC_REVERSE)
return 0;
if (packet_support (PACKET_vCont) == PACKET_SUPPORT_UNKNOWN)
- remote_vcont_probe (rs);
+ remote_vcont_probe ();
if (packet_support (PACKET_vCont) == PACKET_DISABLE)
return 0;
/* Prefer vCont, and fallback to s/c/S/C, which use Hc. */
if (!remote_resume_with_vcont (ptid, step, siggnal))
- remote_resume_with_hc (this, ptid, step, siggnal);
+ remote_resume_with_hc (ptid, step, siggnal);
/* We are about to start executing the inferior, let's register it
with the event loop. NOTE: this is the one place where all the
rs->waiting_for_stop_reply = 1;
}
-static void check_pending_events_prevent_wildcard_vcont
- (int *may_global_wildcard_vcont);
static int is_pending_fork_parent_thread (struct thread_info *thread);
/* Private per-inferior info for target remote processes. */
return static_cast<remote_inferior *> (inf->priv.get ());
}
-/* Structure used to track the construction of a vCont packet in the
+/* Class used to track the construction of a vCont packet in the
outgoing packet buffer. This is used to send multiple vCont
packets if we have more actions than would fit a single packet. */
-struct vcont_builder
+class vcont_builder
{
+public:
+ explicit vcont_builder (remote_target *remote)
+ : m_remote (remote)
+ {
+ restart ();
+ }
+
+ void flush ();
+ void push_action (ptid_t ptid, bool step, gdb_signal siggnal);
+
+private:
+ void restart ();
+
+ /* The remote target. */
+ remote_target *m_remote;
+
/* Pointer to the first action. P points here if no action has been
appended yet. */
- char *first_action;
+ char *m_first_action;
/* Where the next action will be appended. */
- char *p;
+ char *m_p;
/* The end of the buffer. Must never write past this. */
- char *endp;
+ char *m_endp;
};
/* Prepare the outgoing buffer for a new vCont packet. */
-static void
-vcont_builder_restart (struct vcont_builder *builder)
+void
+vcont_builder::restart ()
{
- struct remote_state *rs = get_remote_state ();
+ struct remote_state *rs = m_remote->get_remote_state ();
- builder->p = rs->buf;
- builder->endp = rs->buf + get_remote_packet_size ();
- builder->p += xsnprintf (builder->p, builder->endp - builder->p, "vCont");
- builder->first_action = builder->p;
+ m_p = rs->buf;
+ m_endp = rs->buf + m_remote->get_remote_packet_size ();
+ m_p += xsnprintf (m_p, m_endp - m_p, "vCont");
+ m_first_action = m_p;
}
/* If the vCont packet being built has any action, send it to the
remote end. */
-static void
-vcont_builder_flush (struct vcont_builder *builder)
+void
+vcont_builder::flush ()
{
struct remote_state *rs;
- if (builder->p == builder->first_action)
+ if (m_p == m_first_action)
return;
- rs = get_remote_state ();
- putpkt (rs->buf);
- getpkt (&rs->buf, &rs->buf_size, 0);
+ rs = m_remote->get_remote_state ();
+ m_remote->putpkt (rs->buf);
+ m_remote->getpkt (&rs->buf, &rs->buf_size, 0);
if (strcmp (rs->buf, "OK") != 0)
error (_("Unexpected vCont reply in non-stop mode: %s"), rs->buf);
}
what we've got so far to the remote end and start over a new vCont
packet (with the new action). */
-static void
-vcont_builder_push_action (struct vcont_builder *builder,
- ptid_t ptid, int step, enum gdb_signal siggnal)
+void
+vcont_builder::push_action (ptid_t ptid, bool step, gdb_signal siggnal)
{
char buf[MAX_ACTION_SIZE + 1];
- char *endp;
- size_t rsize;
- endp = append_resumption (buf, buf + sizeof (buf),
- ptid, step, siggnal);
+ char *endp = m_remote->append_resumption (buf, buf + sizeof (buf),
+ ptid, step, siggnal);
/* Check whether this new action would fit in the vCont packet along
with previous actions. If not, send what we've got so far and
start a new vCont packet. */
- rsize = endp - buf;
- if (rsize > builder->endp - builder->p)
+ size_t rsize = endp - buf;
+ if (rsize > m_endp - m_p)
{
- vcont_builder_flush (builder);
- vcont_builder_restart (builder);
+ flush ();
+ restart ();
/* Should now fit. */
- gdb_assert (rsize <= builder->endp - builder->p);
+ gdb_assert (rsize <= m_endp - m_p);
}
- memcpy (builder->p, buf, rsize);
- builder->p += rsize;
- *builder->p = '\0';
+ memcpy (m_p, buf, rsize);
+ m_p += rsize;
+ *m_p = '\0';
}
/* to_commit_resume implementation. */
struct thread_info *tp;
int any_process_wildcard;
int may_global_wildcard_vcont;
- struct vcont_builder vcont_builder;
/* If connected in all-stop mode, we'd send the remote resume
request directly from remote_resume. Likewise if
we end up with too many actions for a single packet vcont_builder
flushes the current vCont packet to the remote side and starts a
new one. */
- vcont_builder_restart (&vcont_builder);
+ struct vcont_builder vcont_builder (this);
/* Threads first. */
ALL_NON_EXITED_THREADS (tp)
continue;
}
- vcont_builder_push_action (&vcont_builder, tp->ptid,
+ vcont_builder.push_action (tp->ptid,
remote_thr->last_resume_step,
remote_thr->last_resume_sig);
remote_thr->vcont_resumed = 1;
continue action for each running process, if any. */
if (may_global_wildcard_vcont)
{
- vcont_builder_push_action (&vcont_builder, minus_one_ptid,
- 0, GDB_SIGNAL_0);
+ vcont_builder.push_action (minus_one_ptid,
+ false, GDB_SIGNAL_0);
}
else
{
{
if (get_remote_inferior (inf)->may_wildcard_vcont)
{
- vcont_builder_push_action (&vcont_builder,
- pid_to_ptid (inf->pid),
- 0, GDB_SIGNAL_0);
+ vcont_builder.push_action (ptid_t (inf->pid),
+ false, GDB_SIGNAL_0);
}
}
}
}
- vcont_builder_flush (&vcont_builder);
+ vcont_builder.flush ();
}
\f
thread, all threads of a remote process, or all threads of all
processes. */
-static void
-remote_stop_ns (ptid_t ptid)
+void
+remote_target::remote_stop_ns (ptid_t ptid)
{
struct remote_state *rs = get_remote_state ();
char *p = rs->buf;
char *endp = rs->buf + get_remote_packet_size ();
if (packet_support (PACKET_vCont) == PACKET_SUPPORT_UNKNOWN)
- remote_vcont_probe (rs);
+ remote_vcont_probe ();
if (!rs->supports_vCont.t)
error (_("Remote server does not support stopping threads"));
if (ptid_is_pid (ptid))
/* All (-1) threads of process. */
- nptid = ptid_build (ptid_get_pid (ptid), -1, 0);
+ nptid = ptid_t (ptid_get_pid (ptid), -1, 0);
else
{
/* Small optimization: if we already have a stop reply for
interrupt the remote target. It is undefined which thread of which
process reports the interrupt. */
-static void
-remote_interrupt_as (void)
+void
+remote_target::remote_interrupt_as ()
{
struct remote_state *rs = get_remote_state ();
reports the interrupt. Throws an error if the packet is not
supported by the server. */
-static void
-remote_interrupt_ns (void)
+void
+remote_target::remote_interrupt_ns ()
{
struct remote_state *rs = get_remote_state ();
char *p = rs->buf;
/* Ask the user what to do when an interrupt is received. */
-static void
-interrupt_query (void)
+void
+remote_target::interrupt_query ()
{
struct remote_state *rs = get_remote_state ();
int core;
} *stop_reply_p;
-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 void
stop_reply_xfree (struct stop_reply *r)
{
/* Return the length of the stop reply queue. */
-static int
-stop_reply_queue_length (void)
+int
+remote_target::stop_reply_queue_length ()
{
- return QUEUE_length (stop_reply_p, stop_reply_queue);
+ remote_state *rs = get_remote_state ();
+ return rs->stop_reply_queue.size ();
}
-static void
-remote_notif_stop_parse (struct notif_client *self, char *buf,
+void
+remote_notif_stop_parse (remote_target *remote,
+ struct notif_client *self, char *buf,
struct notif_event *event)
{
- remote_parse_stop_reply (buf, (struct stop_reply *) event);
+ remote->remote_parse_stop_reply (buf, (struct stop_reply *) event);
}
static void
-remote_notif_stop_ack (struct notif_client *self, char *buf,
+remote_notif_stop_ack (remote_target *remote,
+ struct notif_client *self, char *buf,
struct notif_event *event)
{
struct stop_reply *stop_reply = (struct stop_reply *) event;
/* acknowledge */
- putpkt (self->ack_command);
+ putpkt (remote, 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);
+ remote->push_stop_reply (stop_reply);
}
static int
-remote_notif_stop_can_get_pending_events (struct notif_client *self)
+remote_notif_stop_can_get_pending_events (remote_target *remote,
+ 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);
+ remote_state *rs = remote->get_remote_state ();
+ mark_async_event_handler (rs->remote_async_inferior_event_token);
return 0;
}
REMOTE_NOTIF_STOP,
};
-/* A parameter to pass data in and out. */
-
-struct queue_iter_param
-{
- void *input;
- struct stop_reply *output;
-};
-
/* Determine if THREAD_PTID is a pending fork parent thread. ARG contains
the pid of the process that owns the threads we want to check, or
-1 if we want to check all threads. */
return is_pending_fork_parent (ws, pid, thread->ptid);
}
-/* Check whether EVENT is a fork event, and if it is, remove the
- fork child from the context list passed in DATA. */
-
-static int
-remove_child_of_pending_fork (QUEUE (stop_reply_p) *q,
- QUEUE_ITER (stop_reply_p) *iter,
- stop_reply_p event,
- void *data)
-{
- struct queue_iter_param *param = (struct queue_iter_param *) data;
- struct threads_listing_context *context
- = (struct threads_listing_context *) param->input;
-
- if (event->ws.kind == TARGET_WAITKIND_FORKED
- || event->ws.kind == TARGET_WAITKIND_VFORKED
- || event->ws.kind == TARGET_WAITKIND_THREAD_EXITED)
- context->remove_thread (event->ws.value.related_pid);
-
- return 1;
-}
-
/* If CONTEXT contains any fork child threads that have not been
reported yet, remove them from the CONTEXT list. If such a
thread exists it is because we are stopped at a fork catchpoint
and have not yet called follow_fork, which will set up the
host-side data structures for the new process. */
-static void
-remove_new_fork_children (struct threads_listing_context *context)
+void
+remote_target::remove_new_fork_children (threads_listing_context *context)
{
struct thread_info * thread;
int pid = -1;
struct notif_client *notif = ¬if_client_stop;
- struct queue_iter_param param;
/* For any threads stopped at a fork event, remove the corresponding
fork child threads from the CONTEXT list. */
in process PID and remove those fork child threads from the
CONTEXT list as well. */
remote_notif_get_pending_events (notif);
- param.input = context;
- param.output = NULL;
- QUEUE_iterate (stop_reply_p, stop_reply_queue,
- remove_child_of_pending_fork, ¶m);
-}
-
-/* Check whether EVENT would prevent a global or process wildcard
- vCont action. */
-
-static int
-check_pending_event_prevents_wildcard_vcont_callback
- (QUEUE (stop_reply_p) *q,
- QUEUE_ITER (stop_reply_p) *iter,
- stop_reply_p event,
- void *data)
-{
- struct inferior *inf;
- int *may_global_wildcard_vcont = (int *) data;
-
- if (event->ws.kind == TARGET_WAITKIND_NO_RESUMED
- || event->ws.kind == TARGET_WAITKIND_NO_HISTORY)
- return 1;
-
- if (event->ws.kind == TARGET_WAITKIND_FORKED
- || event->ws.kind == TARGET_WAITKIND_VFORKED)
- *may_global_wildcard_vcont = 0;
-
- inf = find_inferior_ptid (event->ptid);
-
- /* This may be the first time we heard about this process.
- Regardless, we must not do a global wildcard resume, otherwise
- we'd resume this process too. */
- *may_global_wildcard_vcont = 0;
- if (inf != NULL)
- get_remote_inferior (inf)->may_wildcard_vcont = false;
-
- return 1;
+ for (auto &event : get_remote_state ()->stop_reply_queue)
+ if (event->ws.kind == TARGET_WAITKIND_FORKED
+ || event->ws.kind == TARGET_WAITKIND_VFORKED
+ || event->ws.kind == TARGET_WAITKIND_THREAD_EXITED)
+ context->remove_thread (event->ws.value.related_pid);
}
/* Check whether any event pending in the vStopped queue would prevent
and clear the event inferior's may_wildcard_vcont flag if we can't
do a process-wide wildcard resume (vCont;c:pPID.-1). */
-static void
-check_pending_events_prevent_wildcard_vcont (int *may_global_wildcard)
+void
+remote_target::check_pending_events_prevent_wildcard_vcont
+ (int *may_global_wildcard)
{
struct notif_client *notif = ¬if_client_stop;
remote_notif_get_pending_events (notif);
- QUEUE_iterate (stop_reply_p, stop_reply_queue,
- check_pending_event_prevents_wildcard_vcont_callback,
- may_global_wildcard);
-}
+ for (auto &event : get_remote_state ()->stop_reply_queue)
+ {
+ if (event->ws.kind == TARGET_WAITKIND_NO_RESUMED
+ || event->ws.kind == TARGET_WAITKIND_NO_HISTORY)
+ continue;
-/* Remove stop replies in the queue if its pid is equal to the given
- inferior's pid. */
+ if (event->ws.kind == TARGET_WAITKIND_FORKED
+ || event->ws.kind == TARGET_WAITKIND_VFORKED)
+ *may_global_wildcard = 0;
-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 = (struct queue_iter_param *) data;
- struct inferior *inf = (struct inferior *) param->input;
+ struct inferior *inf = find_inferior_ptid (event->ptid);
- if (ptid_get_pid (event->ptid) == inf->pid)
- {
- stop_reply_xfree (event);
- QUEUE_remove_elem (stop_reply_p, q, iter);
+ /* This may be the first time we heard about this process.
+ Regardless, we must not do a global wildcard resume, otherwise
+ we'd resume this process too. */
+ *may_global_wildcard = 0;
+ if (inf != NULL)
+ get_remote_inferior (inf)->may_wildcard_vcont = false;
}
-
- return 1;
}
/* Discard all pending stop replies of inferior INF. */
-static void
-discard_pending_stop_replies (struct inferior *inf)
+void
+remote_target::discard_pending_stop_replies (struct inferior *inf)
{
- struct queue_iter_param param;
struct stop_reply *reply;
struct remote_state *rs = get_remote_state ();
struct remote_notif_state *rns = rs->notif_state;
rns->pending_event[notif_client_stop.id] = NULL;
}
- param.input = inf;
- param.output = NULL;
/* Discard the stop replies we have already pulled with
vStopped. */
- QUEUE_iterate (stop_reply_p, stop_reply_queue,
- remove_stop_reply_for_inferior, ¶m);
-}
-
-/* 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 = (struct queue_iter_param *) data;
- struct remote_state *rs = (struct remote_state *) param->input;
-
- if (event->rs == rs)
- {
- stop_reply_xfree (event);
- QUEUE_remove_elem (stop_reply_p, q, iter);
- }
-
- return 1;
+ auto iter = std::remove_if (rs->stop_reply_queue.begin (),
+ rs->stop_reply_queue.end (),
+ [=] (const stop_reply_up &event)
+ {
+ return event->ptid.pid () == inf->pid;
+ });
+ rs->stop_reply_queue.erase (iter, rs->stop_reply_queue.end ());
}
/* Discard the stop replies for RS in stop_reply_queue. */
-static void
-discard_pending_stop_replies_in_queue (struct remote_state *rs)
+void
+remote_target::discard_pending_stop_replies_in_queue ()
{
- struct queue_iter_param param;
+ remote_state *rs = get_remote_state ();
- 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 = (struct queue_iter_param *) data;
- ptid_t *ptid = (ptid_t *) param->input;
-
- if (ptid_match (event->ptid, *ptid))
- {
- param->output = event;
- QUEUE_remove_elem (stop_reply_p, q, iter);
- return 0;
- }
-
- return 1;
+ auto iter = std::remove_if (rs->stop_reply_queue.begin (),
+ rs->stop_reply_queue.end (),
+ [=] (const stop_reply_up &event)
+ {
+ return event->rs == rs;
+ });
+ rs->stop_reply_queue.erase (iter, rs->stop_reply_queue.end ());
}
/* 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 *
+remote_target::remote_notif_remove_queued_reply (ptid_t ptid)
{
- struct queue_iter_param param;
+ remote_state *rs = get_remote_state ();
- param.input = &ptid;
- param.output = NULL;
+ auto iter = std::find_if (rs->stop_reply_queue.begin (),
+ rs->stop_reply_queue.end (),
+ [=] (const stop_reply_up &event)
+ {
+ return event->ptid.matches (ptid);
+ });
+ struct stop_reply *result;
+ if (iter == rs->stop_reply_queue.end ())
+ result = nullptr;
+ else
+ {
+ result = iter->release ();
+ rs->stop_reply_queue.erase (iter);
+ }
- 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;
+ return result;
}
/* Look for a queued stop reply belonging to PTID. If one is found,
found. If there are still queued events left to process, tell the
event loop to get back to target_wait soon. */
-static struct stop_reply *
-queued_stop_reply (ptid_t ptid)
+struct stop_reply *
+remote_target::queued_stop_reply (ptid_t ptid)
{
+ remote_state *rs = get_remote_state ();
struct stop_reply *r = remote_notif_remove_queued_reply (ptid);
- 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);
+ if (!rs->stop_reply_queue.empty ())
+ {
+ /* There's still at least an event left. */
+ mark_async_event_handler (rs->remote_async_inferior_event_token);
+ }
return r;
}
know that we now have at least one queued event left to pass to the
core side, tell the event loop to get back to target_wait soon. */
-static void
-push_stop_reply (struct stop_reply *new_event)
+void
+remote_target::push_stop_reply (struct stop_reply *new_event)
{
- QUEUE_enque (stop_reply_p, stop_reply_queue, new_event);
+ remote_state *rs = get_remote_state ();
+ rs->stop_reply_queue.push_back (stop_reply_up (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));
+ int (rs->stop_reply_queue.size ()));
- 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 = (ptid_t *) data;
-
- return !(ptid_equal (*ptid, event->ptid)
- && event->ws.kind == TARGET_WAITKIND_STOPPED);
+ mark_async_event_handler (rs->remote_async_inferior_event_token);
}
/* Returns true if we have a stop reply for PTID. */
-static int
-peek_stop_reply (ptid_t ptid)
+int
+remote_target::peek_stop_reply (ptid_t ptid)
{
- return !QUEUE_iterate (stop_reply_p, stop_reply_queue,
- stop_reply_match_ptid_and_ws, &ptid);
+ remote_state *rs = get_remote_state ();
+ for (auto &event : rs->stop_reply_queue)
+ if (ptid == event->ptid
+ && event->ws.kind == TARGET_WAITKIND_STOPPED)
+ return 1;
+ return 0;
}
/* Helper for remote_parse_stop_reply. Return nonzero if the substring
/* Parse the stop reply in BUF. Either the function succeeds, and the
result is stored in EVENT, or throws an error. */
-static void
-remote_parse_stop_reply (char *buf, struct stop_reply *event)
+void
+remote_target::remote_parse_stop_reply (char *buf, stop_reply *event)
{
remote_arch_state *rsa = NULL;
ULONGEST addr;
}
else
error (_("unknown stop reply packet: %s"), buf);
- event->ptid = pid_to_ptid (pid);
+ event->ptid = ptid_t (pid);
}
break;
case 'N':
*/
void
-remote_notif_get_pending_events (struct notif_client *nc)
+remote_target::remote_notif_get_pending_events (notif_client *nc)
{
struct remote_state *rs = get_remote_state ();
nc->name);
/* acknowledge */
- nc->ack (nc, rs->buf, rs->notif_state->pending_event[nc->id]);
+ nc->ack (this, nc, rs->buf, rs->notif_state->pending_event[nc->id]);
rs->notif_state->pending_event[nc->id] = NULL;
while (1)
if (strcmp (rs->buf, "OK") == 0)
break;
else
- remote_notif_ack (nc, rs->buf);
+ remote_notif_ack (this, nc, rs->buf);
}
}
else
}
}
+/* Wrapper around remote_target::remote_notif_get_pending_events to
+ avoid having to export the whole remote_target class. */
+
+void
+remote_notif_get_pending_events (remote_target *remote, notif_client *nc)
+{
+ remote->remote_notif_get_pending_events (nc);
+}
+
/* 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. */
-static ptid_t
-process_stop_reply (struct stop_reply *stop_reply,
- struct target_waitstatus *status)
+ptid_t
+remote_target::process_stop_reply (struct stop_reply *stop_reply,
+ struct target_waitstatus *status)
{
ptid_t ptid;
VEC_iterate (cached_reg_t, stop_reply->regcache, ix, reg);
ix++)
{
- regcache_raw_supply (regcache, reg->num, reg->data);
+ regcache->raw_supply (reg->num, reg->data);
xfree (reg->data);
}
/* The non-stop mode version of target_wait. */
-static ptid_t
-remote_wait_ns (ptid_t ptid, struct target_waitstatus *status, int options)
+ptid_t
+remote_target::wait_ns (ptid_t ptid, struct target_waitstatus *status, int options)
{
struct remote_state *rs = get_remote_state ();
struct stop_reply *stop_reply;
/* Wait until the remote machine stops, then return, storing status in
STATUS just as `wait' would. */
-static ptid_t
-remote_wait_as (ptid_t ptid, struct target_waitstatus *status, int options)
+ptid_t
+remote_target::wait_as (ptid_t ptid, target_waitstatus *status, int options)
{
struct remote_state *rs = get_remote_state ();
ptid_t event_ptid = null_ptid;
int ret;
int is_notif;
int forever = ((options & TARGET_WNOHANG) == 0
- && wait_forever_enabled_p);
+ && rs->wait_forever_enabled_p);
if (!rs->waiting_for_stop_reply)
{
for a stop reply. See the comments in putpkt_binary. Set
waiting_for_stop_reply to 0 temporarily. */
rs->waiting_for_stop_reply = 0;
- remote_fileio_request (buf, rs->ctrlc_pending_p);
+ remote_fileio_request (this, buf, rs->ctrlc_pending_p);
rs->ctrlc_pending_p = 0;
/* GDB handled the File-I/O request, and the target is running
again. Keep waiting for events. */
rs->waiting_for_stop_reply = 0;
stop_reply
- = (struct stop_reply *) remote_notif_parse (¬if_client_stop,
+ = (struct stop_reply *) remote_notif_parse (this,
+ ¬if_client_stop,
rs->buf);
event_ptid = process_stop_reply (stop_reply, status);
ptid_t event_ptid;
if (target_is_non_stop_p ())
- event_ptid = remote_wait_ns (ptid, status, options);
+ event_ptid = wait_ns (ptid, status, options);
else
- event_ptid = remote_wait_as (ptid, status, options);
+ event_ptid = wait_as (ptid, status, options);
if (target_is_async_p ())
{
+ remote_state *rs = get_remote_state ();
+
/* If there are are events left in the queue tell the event loop
to return here. */
- if (!QUEUE_is_empty (stop_reply_p, stop_reply_queue))
- mark_async_event_handler (remote_async_inferior_event_token);
+ if (!rs->stop_reply_queue.empty ())
+ mark_async_event_handler (rs->remote_async_inferior_event_token);
}
return event_ptid;
/* Fetch a single register using a 'p' packet. */
-static int
-fetch_register_using_p (struct regcache *regcache, struct packet_reg *reg)
+int
+remote_target::fetch_register_using_p (struct regcache *regcache,
+ packet_reg *reg)
{
struct gdbarch *gdbarch = regcache->arch ();
struct remote_state *rs = get_remote_state ();
/* If this register is unfetchable, tell the regcache. */
if (buf[0] == 'x')
{
- regcache_raw_supply (regcache, reg->regnum, NULL);
+ regcache->raw_supply (reg->regnum, NULL);
return 1;
}
regp[i++] = fromhex (p[0]) * 16 + fromhex (p[1]);
p += 2;
}
- regcache_raw_supply (regcache, reg->regnum, regp);
+ regcache->raw_supply (reg->regnum, regp);
return 1;
}
/* Fetch the registers included in the target's 'g' packet. */
-static int
-send_g_packet (void)
+int
+remote_target::send_g_packet ()
{
struct remote_state *rs = get_remote_state ();
int buf_len;
return buf_len / 2;
}
-static void
-process_g_packet (struct regcache *regcache)
+void
+remote_target::process_g_packet (struct regcache *regcache)
{
struct gdbarch *gdbarch = regcache->arch ();
struct remote_state *rs = get_remote_state ();
gdb_assert (r->offset * 2 < strlen (rs->buf));
/* The register isn't available, mark it as such (at
the same time setting the value to zero). */
- regcache_raw_supply (regcache, r->regnum, NULL);
+ regcache->raw_supply (r->regnum, NULL);
}
else
- regcache_raw_supply (regcache, r->regnum,
- regs + r->offset);
+ regcache->raw_supply (r->regnum, regs + r->offset);
}
}
}
-static void
-fetch_registers_using_g (struct regcache *regcache)
+void
+remote_target::fetch_registers_using_g (struct regcache *regcache)
{
send_g_packet ();
process_g_packet (regcache);
/* Make the remote selected traceframe match GDB's selected
traceframe. */
-static void
-set_remote_traceframe (void)
+void
+remote_target::set_remote_traceframe ()
{
int newnum;
struct remote_state *rs = get_remote_state ();
int i;
set_remote_traceframe ();
- set_general_thread (regcache_get_ptid (regcache));
+ set_general_thread (regcache->ptid ());
if (regnum >= 0)
{
return;
/* This register is not available. */
- regcache_raw_supply (regcache, reg->regnum, NULL);
+ regcache->raw_supply (reg->regnum, NULL);
return;
}
if (!fetch_register_using_p (regcache, &rsa->regs[i]))
{
/* This register is not available. */
- regcache_raw_supply (regcache, i, NULL);
+ regcache->raw_supply (i, NULL);
}
}
/* Make sure all the necessary registers are cached. */
for (i = 0; i < gdbarch_num_regs (regcache->arch ()); i++)
if (rsa->regs[i].in_g_packet)
- regcache_raw_update (regcache, rsa->regs[i].regnum);
+ regcache->raw_update (rsa->regs[i].regnum);
break;
case PACKET_ENABLE:
break;
/* Helper: Attempt to store REGNUM using the P packet. Return fail IFF
packet was not recognized. */
-static int
-store_register_using_P (const struct regcache *regcache,
- struct packet_reg *reg)
+int
+remote_target::store_register_using_P (const struct regcache *regcache,
+ packet_reg *reg)
{
struct gdbarch *gdbarch = regcache->arch ();
struct remote_state *rs = get_remote_state ();
xsnprintf (buf, get_remote_packet_size (), "P%s=", phex_nz (reg->pnum, 0));
p = buf + strlen (buf);
- regcache_raw_collect (regcache, reg->regnum, regp);
+ regcache->raw_collect (reg->regnum, regp);
bin2hex (regp, p, register_size (gdbarch, reg->regnum));
putpkt (rs->buf);
getpkt (&rs->buf, &rs->buf_size, 0);
/* Store register REGNUM, or all registers if REGNUM == -1, from the
contents of the register cache buffer. FIXME: ignores errors. */
-static void
-store_registers_using_G (const struct regcache *regcache)
+void
+remote_target::store_registers_using_G (const struct regcache *regcache)
{
struct remote_state *rs = get_remote_state ();
remote_arch_state *rsa = rs->get_remote_arch_state (regcache->arch ());
struct packet_reg *r = &rsa->regs[i];
if (r->in_g_packet)
- regcache_raw_collect (regcache, r->regnum, regs + r->offset);
+ regcache->raw_collect (r->regnum, regs + r->offset);
}
}
int i;
set_remote_traceframe ();
- set_general_thread (regcache_get_ptid (regcache));
+ set_general_thread (regcache->ptid ());
if (regnum >= 0)
{
clean. In cases like this, the user should clear "remote
X-packet". */
-static void
-check_binary_download (CORE_ADDR addr)
+void
+remote_target::check_binary_download (CORE_ADDR addr)
{
struct remote_state *rs = get_remote_state ();
-> $m1000,4#??
<- eeeeffffeeeedddd */
-static enum target_xfer_status
-remote_write_bytes_aux (const char *header, CORE_ADDR memaddr,
- const gdb_byte *myaddr, ULONGEST len_units,
- int unit_size, ULONGEST *xfered_len_units,
- char packet_format, int use_length)
+target_xfer_status
+remote_target::remote_write_bytes_aux (const char *header, CORE_ADDR memaddr,
+ const gdb_byte *myaddr,
+ ULONGEST len_units,
+ int unit_size,
+ ULONGEST *xfered_len_units,
+ char packet_format, int use_length)
{
struct remote_state *rs = get_remote_state ();
char *p;
'enum target_xfer_status' value). Save the number of bytes
transferred in *XFERED_LEN. Only transfer a single packet. */
-static enum target_xfer_status
-remote_write_bytes (CORE_ADDR memaddr, const gdb_byte *myaddr, ULONGEST len,
- int unit_size, ULONGEST *xfered_len)
+target_xfer_status
+remote_target::remote_write_bytes (CORE_ADDR memaddr, const gdb_byte *myaddr,
+ ULONGEST len, int unit_size,
+ ULONGEST *xfered_len)
{
const char *packet_format = NULL;
See the comment of remote_write_bytes_aux for an example of
memory read/write exchange between gdb and the stub. */
-static enum target_xfer_status
-remote_read_bytes_1 (CORE_ADDR memaddr, gdb_byte *myaddr, ULONGEST len_units,
- int unit_size, ULONGEST *xfered_len_units)
+target_xfer_status
+remote_target::remote_read_bytes_1 (CORE_ADDR memaddr, gdb_byte *myaddr,
+ ULONGEST len_units,
+ int unit_size, ULONGEST *xfered_len_units)
{
struct remote_state *rs = get_remote_state ();
int buf_size_bytes; /* Max size of packet output buffer. */
For interface/parameters/return description see target.h,
to_xfer_partial. */
-static enum target_xfer_status
-remote_xfer_live_readonly_partial (struct target_ops *ops, gdb_byte *readbuf,
- ULONGEST memaddr, ULONGEST len,
- int unit_size, ULONGEST *xfered_len)
+target_xfer_status
+remote_target::remote_xfer_live_readonly_partial (gdb_byte *readbuf,
+ ULONGEST memaddr,
+ ULONGEST len,
+ int unit_size,
+ ULONGEST *xfered_len)
{
struct target_section *secp;
struct target_section_table *table;
- secp = target_section_by_addr (ops, memaddr);
+ secp = target_section_by_addr (this, memaddr);
if (secp != NULL
&& (bfd_get_section_flags (secp->the_bfd_section->owner,
secp->the_bfd_section)
struct target_section *p;
ULONGEST memend = memaddr + len;
- table = target_get_section_table (ops);
+ table = target_get_section_table (this);
for (p = table->sections; p < table->sections_end; p++)
{
first if the requested memory is unavailable in traceframe.
Otherwise, fall back to remote_read_bytes_1. */
-static enum target_xfer_status
-remote_read_bytes (struct target_ops *ops, CORE_ADDR memaddr,
- gdb_byte *myaddr, ULONGEST len, int unit_size,
- ULONGEST *xfered_len)
+target_xfer_status
+remote_target::remote_read_bytes (CORE_ADDR memaddr,
+ gdb_byte *myaddr, ULONGEST len, int unit_size,
+ ULONGEST *xfered_len)
{
if (len == 0)
return TARGET_XFER_EOF;
}
/* This goes through the topmost target again. */
- res = remote_xfer_live_readonly_partial (ops, myaddr, memaddr,
+ res = remote_xfer_live_readonly_partial (myaddr, memaddr,
len, unit_size, xfered_len);
if (res == TARGET_XFER_OK)
return TARGET_XFER_OK;
FORMAT and the remaining arguments, then gets the reply. Returns
whether the packet was a success, a failure, or unknown. */
-static enum packet_result remote_send_printf (const char *format, ...)
- ATTRIBUTE_PRINTF (1, 2);
-
-static enum packet_result
-remote_send_printf (const char *format, ...)
+packet_result
+remote_target::remote_send_printf (const char *format, ...)
{
struct remote_state *rs = get_remote_state ();
int max_size = get_remote_packet_size ();
}
}
-static enum target_xfer_status
-remote_flash_write (struct target_ops *ops, ULONGEST address,
- ULONGEST length, ULONGEST *xfered_len,
- const gdb_byte *data)
+target_xfer_status
+remote_target::remote_flash_write (ULONGEST address,
+ ULONGEST length, ULONGEST *xfered_len,
+ const gdb_byte *data)
{
scoped_restore restore_timeout
= make_scoped_restore (&remote_timeout, remote_flash_timeout);
sequence, as that would break communication with the remote server.
See remote_serial_quit_handler for more detail. */
-static int
-readchar (int timeout)
+int
+remote_target::readchar (int timeout)
{
int ch;
struct remote_state *rs = get_remote_state ();
{
+ scoped_restore restore_quit_target
+ = make_scoped_restore (&curr_quit_handler_target, this);
scoped_restore restore_quit
- = make_scoped_restore (&quit_handler, remote_serial_quit_handler);
+ = make_scoped_restore (&quit_handler, ::remote_serial_quit_handler);
rs->got_ctrlc_during_io = 0;
communication with the remote server. See
remote_serial_quit_handler for more detail. */
-static void
-remote_serial_write (const char *str, int len)
+void
+remote_target::remote_serial_write (const char *str, int len)
{
struct remote_state *rs = get_remote_state ();
+ scoped_restore restore_quit_target
+ = make_scoped_restore (&curr_quit_handler_target, this);
scoped_restore restore_quit
- = make_scoped_restore (&quit_handler, remote_serial_quit_handler);
+ = make_scoped_restore (&quit_handler, ::remote_serial_quit_handler);
rs->got_ctrlc_during_io = 0;
}
int
-putpkt (const char *buf)
+remote_target::putpkt (const char *buf)
{
return putpkt_binary (buf, strlen (buf));
}
+/* Wrapper around remote_target::putpkt to avoid exporting
+ remote_target. */
+
+int
+putpkt (remote_target *remote, const char *buf)
+{
+ return remote->putpkt (buf);
+}
+
/* Send a packet to the remote machine, with error checking. The data
of the packet is in BUF. The string in BUF can be at most
get_remote_packet_size () - 5 to account for the $, # and checksum,
and for a possible /0 if we are debugging (remote_debug) and want
to print the sent packet as a string. */
-static int
-putpkt_binary (const char *buf, int cnt)
+int
+remote_target::putpkt_binary (const char *buf, int cnt)
{
struct remote_state *rs = get_remote_state ();
int i;
/* Come here after finding the start of a frame when we expected an
ack. Do our best to discard the rest of this packet. */
-static void
-skip_frame (void)
+void
+remote_target::skip_frame ()
{
int c;
trailing NULL) on success. (could be extended to return one of the
SERIAL status indications). */
-static long
-read_frame (char **buf_p,
- long *sizeof_buf)
+long
+remote_target::read_frame (char **buf_p, long *sizeof_buf)
{
unsigned char csum;
long bc;
don't have to change all the calls to getpkt to deal with the
return value, because at the moment I don't know what the right
thing to do it for those. */
+
void
-getpkt (char **buf,
- long *sizeof_buf,
- int forever)
+remote_target::getpkt (char **buf, long *sizeof_buf, int forever)
{
getpkt_sane (buf, sizeof_buf, forever);
}
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 *is_notif)
+int
+remote_target::getpkt_or_notif_sane_1 (char **buf, long *sizeof_buf,
+ int forever, int expecting_notif,
+ int *is_notif)
{
struct remote_state *rs = get_remote_state ();
int c;
}
}
-static int
-getpkt_sane (char **buf, long *sizeof_buf, int forever)
+int
+remote_target::getpkt_sane (char **buf, long *sizeof_buf, int forever)
{
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,
- int *is_notif)
+int
+remote_target::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,
is_notif);
}
-/* Check whether EVENT is a fork event for the process specified
- by the pid passed in DATA, and if it is, kill the fork child. */
-
-static int
-kill_child_of_pending_fork (QUEUE (stop_reply_p) *q,
- QUEUE_ITER (stop_reply_p) *iter,
- stop_reply_p event,
- void *data)
-{
- struct queue_iter_param *param = (struct queue_iter_param *) data;
- int parent_pid = *(int *) param->input;
-
- if (is_pending_fork_parent (&event->ws, parent_pid, event->ptid))
- {
- struct remote_state *rs = get_remote_state ();
- int child_pid = ptid_get_pid (event->ws.value.related_pid);
- int res;
-
- res = remote_vkill (child_pid, rs);
- if (res != 0)
- error (_("Can't kill fork child process %d"), child_pid);
- }
-
- return 1;
-}
-
/* Kill any new fork children of process PID that haven't been
processed by follow_fork. */
-static void
-kill_new_fork_children (int pid, struct remote_state *rs)
+void
+remote_target::kill_new_fork_children (int pid)
{
+ remote_state *rs = get_remote_state ();
struct thread_info *thread;
struct notif_client *notif = ¬if_client_stop;
- struct queue_iter_param param;
/* Kill the fork child threads of any threads in process PID
that are stopped at a fork event. */
if (is_pending_fork_parent (ws, pid, thread->ptid))
{
- struct remote_state *rs = get_remote_state ();
- int child_pid = ptid_get_pid (ws->value.related_pid);
+ int child_pid = ws->value.related_pid.pid ();
int res;
- res = remote_vkill (child_pid, rs);
+ res = remote_vkill (child_pid);
if (res != 0)
error (_("Can't kill fork child process %d"), child_pid);
}
/* Check for any pending fork events (not reported or processed yet)
in process PID and kill those fork child threads as well. */
remote_notif_get_pending_events (notif);
- param.input = &pid;
- param.output = NULL;
- QUEUE_iterate (stop_reply_p, stop_reply_queue,
- kill_child_of_pending_fork, ¶m);
+ for (auto &event : rs->stop_reply_queue)
+ if (is_pending_fork_parent (&event->ws, pid, event->ptid))
+ {
+ int child_pid = event->ws.value.related_pid.pid ();
+ int res;
+
+ res = remote_vkill (child_pid);
+ if (res != 0)
+ error (_("Can't kill fork child process %d"), child_pid);
+ }
}
\f
kill the child task. We need to do this before killing the
parent task because if this is a vfork then the parent will
be sleeping. */
- kill_new_fork_children (pid, rs);
+ kill_new_fork_children (pid);
- res = remote_vkill (pid, rs);
+ res = remote_vkill (pid);
if (res == 0)
{
target_mourn_inferior (inferior_ptid);
/* Send a kill request to the target using the 'vKill' packet. */
-static int
-remote_vkill (int pid, struct remote_state *rs)
+int
+remote_target::remote_vkill (int pid)
{
if (packet_support (PACKET_vKill) == PACKET_DISABLE)
return -1;
+ remote_state *rs = get_remote_state ();
+
/* Tell the remote target to detach. */
xsnprintf (rs->buf, get_remote_packet_size (), "vKill;%x", pid);
putpkt (rs->buf);
/* Send a kill request to the target using the 'k' packet. */
-static void
-remote_kill_k (void)
+void
+remote_target::remote_kill_k ()
{
/* Catch errors so the user can quit from gdb even when we
aren't on speaking terms with the remote system. */
{
struct remote_state *rs = get_remote_state ();
+ /* We're no longer interested in notification events of an inferior
+ that exited or was killed/detached. */
+ discard_pending_stop_replies (current_inferior ());
+
/* In 'target remote' mode with one inferior, we close the connection. */
if (!rs->extended && number_of_live_inferiors () <= 1)
{
return packet_support (PACKET_QDisableRandomization) == PACKET_ENABLE;
}
-static void
-extended_remote_disable_randomization (int val)
+void
+remote_target::extended_remote_disable_randomization (int val)
{
struct remote_state *rs = get_remote_state ();
char *reply;
error (_("Bogus QDisableRandomization reply from target: %s"), reply);
}
-static int
-extended_remote_run (const std::string &args)
+int
+remote_target::extended_remote_run (const std::string &args)
{
struct remote_state *rs = get_remote_state ();
int len;
or "QEnvironmentUnsetVariable". VALUE is the variable to be
sent. */
-static void
-send_environment_packet (struct remote_state *rs,
- const char *action,
- const char *packet,
- const char *value)
+void
+remote_target::send_environment_packet (const char *action,
+ const char *packet,
+ const char *value)
{
+ remote_state *rs = get_remote_state ();
+
/* Convert the environment variable to an hex string, which
is the best format to be transmitted over the wire. */
std::string encoded_value = bin2hex ((const gdb_byte *) value,
/* Helper function to handle the QEnvironment* packets. */
-static void
-extended_remote_environment_support (struct remote_state *rs)
+void
+remote_target::extended_remote_environment_support ()
{
+ remote_state *rs = get_remote_state ();
+
if (packet_support (PACKET_QEnvironmentReset) != PACKET_DISABLE)
{
putpkt ("QEnvironmentReset");
if (packet_support (PACKET_QEnvironmentHexEncoded) != PACKET_DISABLE)
for (const std::string &el : e->user_set_env ())
- send_environment_packet (rs, "set", "QEnvironmentHexEncoded",
+ send_environment_packet ("set", "QEnvironmentHexEncoded",
el.c_str ());
if (packet_support (PACKET_QEnvironmentUnset) != PACKET_DISABLE)
for (const std::string &el : e->user_unset_env ())
- send_environment_packet (rs, "unset", "QEnvironmentUnset", el.c_str ());
+ send_environment_packet ("unset", "QEnvironmentUnset", el.c_str ());
}
/* Helper function to set the current working directory for the
inferior in the remote target. */
-static void
-extended_remote_set_inferior_cwd (struct remote_state *rs)
+void
+remote_target::extended_remote_set_inferior_cwd ()
{
if (packet_support (PACKET_QSetWorkingDir) != PACKET_DISABLE)
{
const char *inferior_cwd = get_inferior_cwd ();
+ remote_state *rs = get_remote_state ();
if (inferior_cwd != NULL)
{
rs->buf);
}
- extended_remote_environment_support (rs);
+ extended_remote_environment_support ();
- extended_remote_set_inferior_cwd (rs);
+ extended_remote_set_inferior_cwd ();
/* Now restart the remote server. */
run_worked = extended_remote_run (args) != -1;
if (!exec_bfd)
error (_("command cannot be used without an exec file"));
- /* Make sure the remote is pointing at the right process. */
- set_general_process ();
-
if (args != NULL && strcmp (args, "-r") == 0)
{
read_only = 1;
into remote target. The number of bytes written to the remote
target is returned, or -1 for error. */
-static enum target_xfer_status
-remote_write_qxfer (const char *object_name,
- const char *annex, const gdb_byte *writebuf,
- ULONGEST offset, LONGEST len, ULONGEST *xfered_len,
- struct packet_config *packet)
+target_xfer_status
+remote_target::remote_write_qxfer (const char *object_name,
+ const char *annex, const gdb_byte *writebuf,
+ ULONGEST offset, LONGEST len,
+ ULONGEST *xfered_len,
+ struct packet_config *packet)
{
int i, buf_len;
ULONGEST n;
EOF. PACKET is checked and updated to indicate whether the remote
target supports this object. */
-static enum target_xfer_status
-remote_read_qxfer (const char *object_name,
- const char *annex,
- gdb_byte *readbuf, ULONGEST offset, LONGEST len,
- ULONGEST *xfered_len,
- struct packet_config *packet)
+target_xfer_status
+remote_target::remote_read_qxfer (const char *object_name,
+ const char *annex,
+ gdb_byte *readbuf, ULONGEST offset,
+ LONGEST len,
+ ULONGEST *xfered_len,
+ struct packet_config *packet)
{
struct remote_state *rs = get_remote_state ();
LONGEST i, n, packet_len;
return remote_write_bytes (offset, writebuf, len, unit_size,
xfered_len);
else
- return remote_read_bytes (this, offset, readbuf, len, unit_size,
+ return remote_read_bytes (offset, readbuf, len, unit_size,
xfered_len);
}
switch (object)
{
case TARGET_OBJECT_FLASH:
- return remote_flash_write (this, offset, len, xfered_len,
+ return remote_flash_write (offset, len, xfered_len,
writebuf);
default:
{
std::vector<mem_region> result;
gdb::optional<gdb::char_vector> text
- = target_read_stralloc (target_stack, TARGET_OBJECT_MEMORY_MAP, NULL);
+ = target_read_stralloc (current_top_target (), TARGET_OBJECT_MEMORY_MAP, NULL);
if (text)
result = parse_memory_map (text->data ());
static void
packet_command (const char *args, int from_tty)
{
- struct remote_state *rs = get_remote_state ();
+ remote_target *remote = get_current_remote_target ();
- if (!rs->remote_desc)
+ if (remote == nullptr)
error (_("command can only be used with remote target"));
+ remote->packet_command (args, from_tty);
+}
+
+void
+remote_target::packet_command (const char *args, int from_tty)
+{
if (!args)
error (_("remote-packet command requires packet text as argument"));
puts_filtered ("\n");
putpkt (args);
+ remote_state *rs = get_remote_state ();
+
getpkt (&rs->buf, &rs->buf_size, 0);
puts_filtered ("received: ");
print_packet (rs->buf);
{
int sample_thread = SAMPLE_THREAD;
int pid = ptid_get_pid (inferior_ptid);
- ptid_t ptid = ptid_build (pid, sample_thread, 0);
+ ptid_t ptid = ptid_t (pid, sample_thread, 0);
if (remote_thread_alive (ptid))
printf_filtered ("PASS: Thread alive test\n");
/* Do not try this during initial connection, when we do not know
whether there is a running but stopped thread. */
if (!target_has_execution || ptid_equal (inferior_ptid, null_ptid))
- return beneath->read_description ();
+ return beneath ()->read_description ();
if (!VEC_empty (remote_g_packet_guess_s, data->guesses))
{
an architecture, but it's too tricky to do safely. */
}
- return beneath->read_description ();
+ return beneath ()->read_description ();
}
/* Remote file transfer support. This is host-initiated I/O, not
the packet buffer and *ATTACHMENT_LEN will be set to the
attachment's length. */
-static int
-remote_hostio_send_command (int command_bytes, int which_packet,
- int *remote_errno, char **attachment,
- int *attachment_len)
+int
+remote_target::remote_hostio_send_command (int command_bytes, int which_packet,
+ int *remote_errno, char **attachment,
+ int *attachment_len)
{
struct remote_state *rs = get_remote_state ();
int ret, bytes_read;
arguments will use. Return 0 on success, or -1 if an error
occurs (and set *REMOTE_ERRNO). */
-static int
-remote_hostio_set_filesystem (struct inferior *inf, int *remote_errno)
+int
+remote_target::remote_hostio_set_filesystem (struct inferior *inf,
+ int *remote_errno)
{
struct remote_state *rs = get_remote_state ();
int required_pid = (inf == NULL || inf->fake_pid_p) ? 0 : inf->pid;
/* Implementation of to_fileio_open. */
-static int
-remote_hostio_open (struct target_ops *self,
- struct inferior *inf, const char *filename,
- int flags, int mode, int warn_if_slow,
- int *remote_errno)
+int
+remote_target::remote_hostio_open (inferior *inf, const char *filename,
+ int flags, int mode, int warn_if_slow,
+ int *remote_errno)
{
struct remote_state *rs = get_remote_state ();
char *p = rs->buf;
int flags, int mode, int warn_if_slow,
int *remote_errno)
{
- return remote_hostio_open (this, inf, filename, flags, mode, warn_if_slow,
+ return remote_hostio_open (inf, filename, flags, mode, warn_if_slow,
remote_errno);
}
/* Implementation of to_fileio_pwrite. */
-static int
-remote_hostio_pwrite (struct target_ops *self,
- int fd, const gdb_byte *write_buf, int len,
- ULONGEST offset, int *remote_errno)
+int
+remote_target::remote_hostio_pwrite (int fd, const gdb_byte *write_buf, int len,
+ ULONGEST offset, int *remote_errno)
{
struct remote_state *rs = get_remote_state ();
char *p = rs->buf;
remote_target::fileio_pwrite (int fd, const gdb_byte *write_buf, int len,
ULONGEST offset, int *remote_errno)
{
- return remote_hostio_pwrite (this, fd, write_buf, len, offset, remote_errno);
+ return remote_hostio_pwrite (fd, write_buf, len, offset, remote_errno);
}
/* Helper for the implementation of to_fileio_pread. Read the file
from the remote side with vFile:pread. */
-static int
-remote_hostio_pread_vFile (struct target_ops *self,
- int fd, gdb_byte *read_buf, int len,
- ULONGEST offset, int *remote_errno)
+int
+remote_target::remote_hostio_pread_vFile (int fd, gdb_byte *read_buf, int len,
+ ULONGEST offset, int *remote_errno)
{
struct remote_state *rs = get_remote_state ();
char *p = rs->buf;
/* Implementation of to_fileio_pread. */
-static int
-remote_hostio_pread (struct target_ops *self,
- int fd, gdb_byte *read_buf, int len,
- ULONGEST offset, int *remote_errno)
+int
+remote_target::remote_hostio_pread (int fd, gdb_byte *read_buf, int len,
+ ULONGEST offset, int *remote_errno)
{
int ret;
struct remote_state *rs = get_remote_state ();
cache->bufsize = get_remote_packet_size ();
cache->buf = (gdb_byte *) xrealloc (cache->buf, cache->bufsize);
- ret = remote_hostio_pread_vFile (self, cache->fd, cache->buf, cache->bufsize,
+ ret = remote_hostio_pread_vFile (cache->fd, cache->buf, cache->bufsize,
cache->offset, remote_errno);
if (ret <= 0)
{
remote_target::fileio_pread (int fd, gdb_byte *read_buf, int len,
ULONGEST offset, int *remote_errno)
{
- return remote_hostio_pread (this, fd, read_buf, len, offset, remote_errno);
+ return remote_hostio_pread (fd, read_buf, len, offset, remote_errno);
}
/* Implementation of to_fileio_close. */
-static int
-remote_hostio_close (struct target_ops *self, int fd, int *remote_errno)
+int
+remote_target::remote_hostio_close (int fd, int *remote_errno)
{
struct remote_state *rs = get_remote_state ();
char *p = rs->buf;
int
remote_target::fileio_close (int fd, int *remote_errno)
{
- return remote_hostio_close (this, fd, remote_errno);
+ return remote_hostio_close (fd, remote_errno);
}
/* Implementation of to_fileio_unlink. */
-static int
-remote_hostio_unlink (struct target_ops *self,
- struct inferior *inf, const char *filename,
- int *remote_errno)
+int
+remote_target::remote_hostio_unlink (inferior *inf, const char *filename,
+ int *remote_errno)
{
struct remote_state *rs = get_remote_state ();
char *p = rs->buf;
remote_target::fileio_unlink (struct inferior *inf, const char *filename,
int *remote_errno)
{
- return remote_hostio_unlink (this, inf, filename, remote_errno);
+ return remote_hostio_unlink (inf, filename, remote_errno);
}
/* Implementation of to_fileio_readlink. */
/* Try opening a file to probe support. The supplied
filename is irrelevant, we only care about whether
the stub recognizes the packet or not. */
- fd = remote_hostio_open (this, NULL, "just probing",
+ fd = remote_hostio_open (NULL, "just probing",
FILEIO_O_RDONLY, 0700, 0,
&remote_errno);
if (fd >= 0)
- remote_hostio_close (this, fd, &remote_errno);
+ remote_hostio_close (fd, &remote_errno);
ps = packet_support (PACKET_vFile_open);
}
class scoped_remote_fd
{
public:
- explicit scoped_remote_fd (int fd)
- : m_fd (fd)
+ scoped_remote_fd (remote_target *remote, int fd)
+ : m_remote (remote), m_fd (fd)
{
}
try
{
int remote_errno;
- remote_hostio_close (find_target_at (process_stratum),
- m_fd, &remote_errno);
+ m_remote->remote_hostio_close (m_fd, &remote_errno);
}
catch (...)
{
}
private:
+ /* The remote target. */
+ remote_target *m_remote;
+
/* The owned remote I/O file descriptor. */
int m_fd;
};
void
remote_file_put (const char *local_file, const char *remote_file, int from_tty)
{
- struct cleanup *back_to;
+ remote_target *remote = get_current_remote_target ();
+
+ if (remote == nullptr)
+ error (_("command can only be used with remote target"));
+
+ remote->remote_file_put (local_file, remote_file, from_tty);
+}
+
+void
+remote_target::remote_file_put (const char *local_file, const char *remote_file,
+ int from_tty)
+{
int retcode, remote_errno, bytes, io_size;
- gdb_byte *buffer;
int bytes_in_buffer;
int saw_eof;
ULONGEST offset;
- struct remote_state *rs = get_remote_state ();
-
- if (!rs->remote_desc)
- error (_("command can only be used with remote target"));
gdb_file_up file = gdb_fopen_cloexec (local_file, "rb");
if (file == NULL)
perror_with_name (local_file);
scoped_remote_fd fd
- (remote_hostio_open (find_target_at (process_stratum), NULL,
- remote_file, (FILEIO_O_WRONLY | FILEIO_O_CREAT
- | FILEIO_O_TRUNC),
- 0700, 0, &remote_errno));
+ (this, remote_hostio_open (NULL,
+ remote_file, (FILEIO_O_WRONLY | FILEIO_O_CREAT
+ | FILEIO_O_TRUNC),
+ 0700, 0, &remote_errno));
if (fd.get () == -1)
remote_hostio_error (remote_errno);
/* Send up to this many bytes at once. They won't all fit in the
remote packet limit, so we'll transfer slightly fewer. */
io_size = get_remote_packet_size ();
- buffer = (gdb_byte *) xmalloc (io_size);
- back_to = make_cleanup (xfree, buffer);
+ gdb::byte_vector buffer (io_size);
bytes_in_buffer = 0;
saw_eof = 0;
{
if (!saw_eof)
{
- bytes = fread (buffer + bytes_in_buffer, 1,
+ bytes = fread (buffer.data () + bytes_in_buffer, 1,
io_size - bytes_in_buffer,
file.get ());
if (bytes == 0)
bytes += bytes_in_buffer;
bytes_in_buffer = 0;
- retcode = remote_hostio_pwrite (find_target_at (process_stratum),
- fd.get (), buffer, bytes,
+ retcode = remote_hostio_pwrite (fd.get (), buffer.data (), bytes,
offset, &remote_errno);
if (retcode < 0)
/* Short write. Save the rest of the read data for the next
write. */
bytes_in_buffer = bytes - retcode;
- memmove (buffer, buffer + retcode, bytes_in_buffer);
+ memmove (buffer.data (), buffer.data () + retcode, bytes_in_buffer);
}
offset += retcode;
}
- if (remote_hostio_close (find_target_at (process_stratum),
- fd.release (), &remote_errno))
+ if (remote_hostio_close (fd.release (), &remote_errno))
remote_hostio_error (remote_errno);
if (from_tty)
printf_filtered (_("Successfully sent file \"%s\".\n"), local_file);
- do_cleanups (back_to);
}
void
remote_file_get (const char *remote_file, const char *local_file, int from_tty)
{
- struct cleanup *back_to;
- int remote_errno, bytes, io_size;
- gdb_byte *buffer;
- ULONGEST offset;
- struct remote_state *rs = get_remote_state ();
+ remote_target *remote = get_current_remote_target ();
- if (!rs->remote_desc)
+ if (remote == nullptr)
error (_("command can only be used with remote target"));
+ remote->remote_file_get (remote_file, local_file, from_tty);
+}
+
+void
+remote_target::remote_file_get (const char *remote_file, const char *local_file,
+ int from_tty)
+{
+ int remote_errno, bytes, io_size;
+ ULONGEST offset;
+
scoped_remote_fd fd
- (remote_hostio_open (find_target_at (process_stratum), NULL,
- remote_file, FILEIO_O_RDONLY, 0, 0,
- &remote_errno));
+ (this, remote_hostio_open (NULL,
+ remote_file, FILEIO_O_RDONLY, 0, 0,
+ &remote_errno));
if (fd.get () == -1)
remote_hostio_error (remote_errno);
/* Send up to this many bytes at once. They won't all fit in the
remote packet limit, so we'll transfer slightly fewer. */
io_size = get_remote_packet_size ();
- buffer = (gdb_byte *) xmalloc (io_size);
- back_to = make_cleanup (xfree, buffer);
+ gdb::byte_vector buffer (io_size);
offset = 0;
while (1)
{
- bytes = remote_hostio_pread (find_target_at (process_stratum),
- fd.get (), buffer, io_size, offset,
+ bytes = remote_hostio_pread (fd.get (), buffer.data (), io_size, offset,
&remote_errno);
if (bytes == 0)
/* Success, but no bytes, means end-of-file. */
offset += bytes;
- bytes = fwrite (buffer, 1, bytes, file.get ());
+ bytes = fwrite (buffer.data (), 1, bytes, file.get ());
if (bytes == 0)
perror_with_name (local_file);
}
- if (remote_hostio_close (find_target_at (process_stratum),
- fd.release (), &remote_errno))
+ if (remote_hostio_close (fd.release (), &remote_errno))
remote_hostio_error (remote_errno);
if (from_tty)
printf_filtered (_("Successfully fetched file \"%s\".\n"), remote_file);
- do_cleanups (back_to);
}
void
remote_file_delete (const char *remote_file, int from_tty)
{
- int retcode, remote_errno;
- struct remote_state *rs = get_remote_state ();
+ remote_target *remote = get_current_remote_target ();
- if (!rs->remote_desc)
+ if (remote == nullptr)
error (_("command can only be used with remote target"));
- retcode = remote_hostio_unlink (find_target_at (process_stratum),
- NULL, remote_file, &remote_errno);
+ remote->remote_file_delete (remote_file, from_tty);
+}
+
+void
+remote_target::remote_file_delete (const char *remote_file, int from_tty)
+{
+ int retcode, remote_errno;
+
+ retcode = remote_hostio_unlink (NULL, remote_file, &remote_errno);
if (retcode == -1)
remote_hostio_error (remote_errno);
/* Recursive routine to walk through command list including loops, and
download packets for each command. */
-static void
-remote_download_command_source (int num, ULONGEST addr,
- struct command_line *cmds)
+void
+remote_target::remote_download_command_source (int num, ULONGEST addr,
+ struct command_line *cmds)
{
struct remote_state *rs = get_remote_state ();
struct command_line *cmd;
remote_target::traceframe_info ()
{
gdb::optional<gdb::char_vector> text
- = target_read_stralloc (target_stack, TARGET_OBJECT_TRACEFRAME_INFO,
+ = target_read_stralloc (current_top_target (), TARGET_OBJECT_TRACEFRAME_INFO,
NULL);
if (text)
return parse_traceframe_info (text->data ());
/* Reset our idea of our target's btrace configuration. */
static void
-remote_btrace_reset (void)
+remote_btrace_reset (remote_state *rs)
{
- struct remote_state *rs = get_remote_state ();
-
memset (&rs->btrace_config, 0, sizeof (rs->btrace_config));
}
/* Synchronize the configuration with the target. */
-static void
-btrace_sync_conf (const struct btrace_config *conf)
+void
+remote_target::btrace_sync_conf (const btrace_config *conf)
{
struct packet_config *packet;
struct remote_state *rs;
btrace_read_config (struct btrace_config *conf)
{
gdb::optional<gdb::char_vector> xml
- = target_read_stralloc (target_stack, TARGET_OBJECT_BTRACE_CONF, "");
+ = target_read_stralloc (current_top_target (), TARGET_OBJECT_BTRACE_CONF, "");
if (xml)
parse_xml_btrace_conf (conf, xml->data ());
}
/* Maybe reopen target btrace. */
-static void
-remote_btrace_maybe_reopen (void)
+void
+remote_target::remote_btrace_maybe_reopen ()
{
struct remote_state *rs = get_remote_state ();
struct thread_info *tp;
}
gdb::optional<gdb::char_vector> xml
- = target_read_stralloc (target_stack, TARGET_OBJECT_BTRACE, annex);
+ = target_read_stralloc (current_top_target (), TARGET_OBJECT_BTRACE, annex);
if (!xml)
return BTRACE_ERR_UNKNOWN;
xsnprintf (annex, annex_size, "%x", pid);
}
- filename = target_read_stralloc (target_stack,
+ filename = target_read_stralloc (current_top_target (),
TARGET_OBJECT_EXEC_FILE, annex);
return filename ? filename->data () : nullptr;
struct remote_state *rs = get_remote_state ();
if (packet_support (PACKET_vCont) == PACKET_SUPPORT_UNKNOWN)
- remote_vcont_probe (rs);
+ remote_vcont_probe ();
return rs->supports_vCont.s && rs->supports_vCont.S;
}
static void
remote_async_inferior_event_handler (gdb_client_data data)
{
- inferior_event_handler (INF_REG_EVENT, NULL);
+ inferior_event_handler (INF_REG_EVENT, data);
}
void
/* If there are pending events in the stop reply queue tell the
event loop to process them. */
- if (!QUEUE_is_empty (stop_reply_p, stop_reply_queue))
- mark_async_event_handler (remote_async_inferior_event_token);
+ if (!rs->stop_reply_queue.empty ())
+ mark_async_event_handler (rs->remote_async_inferior_event_token);
/* For simplicity, below we clear the pending events token
without remembering whether it is marked, so here we always
mark it. If there's actually no pending notification to
/* If the core is disabling async, it doesn't want to be
disturbed with target events. Clear all async event sources
too. */
- clear_async_event_handler (remote_async_inferior_event_token);
+ clear_async_event_handler (rs->remote_async_inferior_event_token);
if (target_is_non_stop_p ())
clear_async_event_handler (rs->notif_state->get_pending_events_token);
}
static void
remote_new_objfile (struct objfile *objfile)
{
- struct remote_state *rs = get_remote_state ();
+ remote_target *remote = get_current_remote_target ();
- if (rs->remote_desc != 0) /* Have a remote connection. */
- remote_check_symbols ();
+ if (remote != NULL) /* Have a remote connection. */
+ remote->remote_check_symbols ();
}
/* Pull all the tracepoints defined on the target and create local
"is %s.\n"), value);
}
+/* Return true if the vCont;r action is supported by the remote
+ stub. */
+
+bool
+remote_target::vcont_r_supported ()
+{
+ if (packet_support (PACKET_vCont) == PACKET_SUPPORT_UNKNOWN)
+ remote_vcont_probe ();
+
+ return (packet_support (PACKET_vCont) == PACKET_ENABLE
+ && get_remote_state ()->supports_vCont.r);
+}
+
/* The "set/show range-stepping" set hook. */
static void
set_range_stepping (const 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. */
+ /* When 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 (packet_support (PACKET_vCont) == PACKET_SUPPORT_UNKNOWN)
- remote_vcont_probe (rs);
-
- if (packet_support (PACKET_vCont) == PACKET_ENABLE
- && rs->supports_vCont.r)
- return;
- }
-
- warning (_("Range stepping is not supported by the current target"));
+ remote_target *remote = get_current_remote_target ();
+ if (remote == NULL
+ || !remote->vcont_r_supported ())
+ warning (_("Range stepping is not supported by the current target"));
}
}
= register_program_space_data_with_cleanup (NULL,
remote_pspace_data_cleanup);
- /* 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. */
- remote_state = new struct remote_state ();
-
add_target (remote_target_info, remote_target::open);
add_target (extended_remote_target_info, extended_remote_target::open);
/* Hook into new objfile notification. */
gdb::observers::new_objfile.attach (remote_new_objfile);
- /* We're no longer interested in notification events of an inferior
- when it exits. */
- gdb::observers::inferior_exit.attach (discard_pending_stop_replies);
#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, _("\
/* Take advantage of the fact that the TID field is not used, to tag
special ptids with it set to != 0. */
- magic_null_ptid = ptid_build (42000, -1, 1);
- not_sent_ptid = ptid_build (42000, -2, 1);
- any_thread_ptid = ptid_build (42000, 0, 1);
+ magic_null_ptid = ptid_t (42000, -1, 1);
+ not_sent_ptid = ptid_t (42000, -2, 1);
+ any_thread_ptid = ptid_t (42000, 0, 1);
}