blob: d5eb40ce57857db839b0da7e21f7af8869464ab7 [file] [log] [blame]
/* Remote target communications for serial-line targets in custom GDB protocol
Copyright (C) 1988-2021 Free Software Foundation, Inc.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* See the GDB User Guide for details of the GDB remote protocol. */
#include "defs.h"
#include <ctype.h>
#include <fcntl.h>
#include "inferior.h"
#include "infrun.h"
#include "bfd.h"
#include "symfile.h"
#include "target.h"
#include "process-stratum-target.h"
#include "gdbcmd.h"
#include "objfiles.h"
#include "gdb-stabs.h"
#include "gdbthread.h"
#include "remote.h"
#include "remote-notif.h"
#include "regcache.h"
#include "value.h"
#include "observable.h"
#include "solib.h"
#include "cli/cli-decode.h"
#include "cli/cli-setshow.h"
#include "target-descriptions.h"
#include "gdb_bfd.h"
#include "gdbsupport/filestuff.h"
#include "gdbsupport/rsp-low.h"
#include "disasm.h"
#include "location.h"
#include "gdbsupport/gdb_sys_time.h"
#include "gdbsupport/event-loop.h"
#include "event-top.h"
#include "inf-loop.h"
#include <signal.h>
#include "serial.h"
#include "gdbcore.h"
#include "remote-fileio.h"
#include "gdb/fileio.h"
#include <sys/stat.h>
#include "xml-support.h"
#include "memory-map.h"
#include "tracepoint.h"
#include "ax.h"
#include "ax-gdb.h"
#include "gdbsupport/agent.h"
#include "btrace.h"
#include "record-btrace.h"
#include <algorithm>
#include "gdbsupport/scoped_restore.h"
#include "gdbsupport/environ.h"
#include "gdbsupport/byte-vector.h"
#include "gdbsupport/search.h"
#include <algorithm>
#include <unordered_map>
#include "async-event.h"
#include "gdbsupport/selftest.h"
/* The remote target. */
static const char remote_doc[] = N_("\
Use a remote computer via a serial line, using a gdb-specific protocol.\n\
Specify the serial device it is connected to\n\
(e.g. /dev/ttyS0, /dev/ttya, COM1, etc.).");
/* See remote.h */
bool remote_debug = false;
#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;
typedef std::unique_ptr<stop_reply> 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 threadids 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.
The size of the buffer is always at least REMOTE_PACKET_SIZE;
REMOTE_PACKET_SIZE should be used to limit the length of outgoing
packets. */
gdb::char_vector buf;
/* 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;
/* Whether vCont support was probed already. This is a workaround
until packet_support is per-connection. */
bool supports_vCont_probed;
/* 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"),
remote_doc
};
class remote_target : public process_stratum_target
{
public:
remote_target () = default;
~remote_target () override;
const target_info &info () const override
{ return remote_target_info; }
const char *connection_string () override;
thread_control_capabilities get_thread_control_capabilities () override
{ return tc_schedlock; }
/* Open a remote connection. */
static void open (const char *, int);
void close () override;
void detach (inferior *, int) override;
void disconnect (const char *, int) override;
void commit_resumed () override;
void resume (ptid_t, int, enum gdb_signal) override;
ptid_t wait (ptid_t, struct target_waitstatus *, target_wait_flags) override;
bool has_pending_events () override;
void fetch_registers (struct regcache *, int) override;
void store_registers (struct regcache *, int) override;
void prepare_to_store (struct regcache *) override;
void files_info () override;
int insert_breakpoint (struct gdbarch *, struct bp_target_info *) override;
int remove_breakpoint (struct gdbarch *, struct bp_target_info *,
enum remove_bp_reason) override;
bool stopped_by_sw_breakpoint () override;
bool supports_stopped_by_sw_breakpoint () override;
bool stopped_by_hw_breakpoint () override;
bool supports_stopped_by_hw_breakpoint () override;
bool stopped_by_watchpoint () override;
bool stopped_data_address (CORE_ADDR *) override;
bool watchpoint_addr_within_range (CORE_ADDR, CORE_ADDR, int) override;
int can_use_hw_breakpoint (enum bptype, int, int) override;
int insert_hw_breakpoint (struct gdbarch *, struct bp_target_info *) override;
int remove_hw_breakpoint (struct gdbarch *, struct bp_target_info *) override;
int region_ok_for_hw_watchpoint (CORE_ADDR, int) override;
int insert_watchpoint (CORE_ADDR, int, enum target_hw_bp_type,
struct expression *) override;
int remove_watchpoint (CORE_ADDR, int, enum target_hw_bp_type,
struct expression *) override;
void kill () override;
void load (const char *, int) override;
void mourn_inferior () override;
void pass_signals (gdb::array_view<const unsigned char>) override;
int set_syscall_catchpoint (int, bool, int,
gdb::array_view<const int>) override;
void program_signals (gdb::array_view<const unsigned char>) override;
bool thread_alive (ptid_t ptid) override;
const char *thread_name (struct thread_info *) override;
void update_thread_list () override;
std::string pid_to_str (ptid_t) override;
const char *extra_thread_info (struct thread_info *) override;
ptid_t get_ada_task_ptid (long lwp, ULONGEST thread) override;
thread_info *thread_handle_to_thread_info (const gdb_byte *thread_handle,
int handle_len,
inferior *inf) override;
gdb::byte_vector thread_info_to_thread_handle (struct thread_info *tp)
override;
void stop (ptid_t) override;
void interrupt () override;
void pass_ctrlc () override;
enum target_xfer_status xfer_partial (enum target_object object,
const char *annex,
gdb_byte *readbuf,
const gdb_byte *writebuf,
ULONGEST offset, ULONGEST len,
ULONGEST *xfered_len) override;
ULONGEST get_memory_xfer_limit () override;
void rcmd (const char *command, struct ui_file *output) override;
char *pid_to_exec_file (int pid) override;
void log_command (const char *cmd) override
{
serial_log_command (this, cmd);
}
CORE_ADDR get_thread_local_address (ptid_t ptid,
CORE_ADDR load_module_addr,
CORE_ADDR offset) override;
bool can_execute_reverse () override;
std::vector<mem_region> memory_map () override;
void flash_erase (ULONGEST address, LONGEST length) override;
void flash_done () override;
const struct target_desc *read_description () override;
int search_memory (CORE_ADDR start_addr, ULONGEST search_space_len,
const gdb_byte *pattern, ULONGEST pattern_len,
CORE_ADDR *found_addrp) override;
bool can_async_p () override;
bool is_async_p () override;
void async (int) override;
int async_wait_fd () override;
void thread_events (int) override;
int can_do_single_step () override;
void terminal_inferior () override;
void terminal_ours () override;
bool supports_non_stop () override;
bool supports_multi_process () override;
bool supports_disable_randomization () override;
bool filesystem_is_local () override;
int fileio_open (struct inferior *inf, const char *filename,
int flags, int mode, int warn_if_slow,
int *target_errno) override;
int fileio_pwrite (int fd, const gdb_byte *write_buf, int len,
ULONGEST offset, int *target_errno) override;
int fileio_pread (int fd, gdb_byte *read_buf, int len,
ULONGEST offset, int *target_errno) override;
int fileio_fstat (int fd, struct stat *sb, int *target_errno) override;
int fileio_close (int fd, int *target_errno) override;
int fileio_unlink (struct inferior *inf,
const char *filename,
int *target_errno) override;
gdb::optional<std::string>
fileio_readlink (struct inferior *inf,
const char *filename,
int *target_errno) override;
bool supports_enable_disable_tracepoint () override;
bool supports_string_tracing () override;
bool supports_evaluation_of_breakpoint_conditions () override;
bool can_run_breakpoint_commands () override;
void trace_init () override;
void download_tracepoint (struct bp_location *location) override;
bool can_download_tracepoint () override;
void download_trace_state_variable (const trace_state_variable &tsv) override;
void enable_tracepoint (struct bp_location *location) override;
void disable_tracepoint (struct bp_location *location) override;
void trace_set_readonly_regions () override;
void trace_start () override;
int get_trace_status (struct trace_status *ts) override;
void get_tracepoint_status (struct breakpoint *tp, struct uploaded_tp *utp)
override;
void trace_stop () override;
int trace_find (enum trace_find_type type, int num,
CORE_ADDR addr1, CORE_ADDR addr2, int *tpp) override;
bool get_trace_state_variable_value (int tsv, LONGEST *val) override;
int save_trace_data (const char *filename) override;
int upload_tracepoints (struct uploaded_tp **utpp) override;
int upload_trace_state_variables (struct uploaded_tsv **utsvp) override;
LONGEST get_raw_trace_data (gdb_byte *buf, ULONGEST offset, LONGEST len) override;
int get_min_fast_tracepoint_insn_len () override;
void set_disconnected_tracing (int val) override;
void set_circular_trace_buffer (int val) override;
void set_trace_buffer_size (LONGEST val) override;
bool set_trace_notes (const char *user, const char *notes,
const char *stopnotes) override;
int core_of_thread (ptid_t ptid) override;
int verify_memory (const gdb_byte *data,
CORE_ADDR memaddr, ULONGEST size) override;
bool get_tib_address (ptid_t ptid, CORE_ADDR *addr) override;
void set_permissions () override;
bool static_tracepoint_marker_at (CORE_ADDR,
struct static_tracepoint_marker *marker)
override;
std::vector<static_tracepoint_marker>
static_tracepoint_markers_by_strid (const char *id) override;
traceframe_info_up traceframe_info () override;
bool use_agent (bool use) override;
bool can_use_agent () override;
struct btrace_target_info *enable_btrace (ptid_t ptid,
const struct btrace_config *conf) override;
void disable_btrace (struct btrace_target_info *tinfo) override;
void teardown_btrace (struct btrace_target_info *tinfo) override;
enum btrace_error read_btrace (struct btrace_data *data,
struct btrace_target_info *btinfo,
enum btrace_read_type type) override;
const struct btrace_config *btrace_conf (const struct btrace_target_info *) override;
bool augmented_libraries_svr4_read () override;
void follow_fork (inferior *, ptid_t, target_waitkind, bool, bool) override;
void follow_exec (inferior *, ptid_t, const char *) override;
int insert_fork_catchpoint (int) override;
int remove_fork_catchpoint (int) override;
int insert_vfork_catchpoint (int) override;
int remove_vfork_catchpoint (int) override;
int insert_exec_catchpoint (int) override;
int remove_exec_catchpoint (int) override;
enum exec_direction_kind execution_direction () override;
bool supports_memory_tagging () override;
bool fetch_memtags (CORE_ADDR address, size_t len,
gdb::byte_vector &tags, int type) override;
bool store_memtags (CORE_ADDR address, size_t len,
const gdb::byte_vector &tags, int type) override;
public: /* Remote specific methods. */
void remote_download_command_source (int num, ULONGEST addr,
struct command_line *cmds);
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);
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);
int remote_hostio_send_command (int command_bytes, int which_packet,
int *remote_errno, const 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);
int remote_hostio_unlink (inferior *inf, const char *filename,
int *remote_errno);
struct remote_state *get_remote_state ();
long get_remote_packet_size (void);
long get_memory_packet_size (struct memory_packet_config *config);
long get_memory_write_packet_size ();
long get_memory_read_packet_size ();
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);
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);
thread_info *add_current_inferior_and_thread (const char *wait_status);
ptid_t wait_ns (ptid_t ptid, struct target_waitstatus *status,
target_wait_flags options);
ptid_t wait_as (ptid_t ptid, target_waitstatus *status,
target_wait_flags options);
ptid_t process_stop_reply (struct stop_reply *stop_reply,
target_waitstatus *status);
ptid_t select_thread_for_ambiguous_stop_reply
(const struct target_waitstatus *status);
void remote_notice_new_inferior (ptid_t currthread, bool executing);
void print_one_stopped_thread (thread_info *thread);
void process_initial_stop_replies (int from_tty);
thread_info *remote_add_thread (ptid_t ptid, bool running, bool executing);
void btrace_sync_conf (const btrace_config *conf);
void remote_btrace_maybe_reopen ();
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 ();
void check_pending_events_prevent_wildcard_vcont
(bool *may_global_wildcard_vcont);
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 (const char *buf, stop_reply *event);
void remote_stop_ns (ptid_t ptid);
void remote_interrupt_as ();
void remote_interrupt_ns ();
char *remote_get_noisy_reply ();
int remote_query_attached (int pid);
inferior *remote_add_inferior (bool fake_pid_p, int pid, int attached,
int try_open_exec);
ptid_t remote_current_thread (ptid_t oldpid);
ptid_t get_current_thread (const char *wait_status);
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 ();
char *write_ptid (char *buf, const char *endbuf, ptid_t ptid);
int remote_unpack_thread_info_response (const char *pkt, threadref *expectedref,
gdb_ext_thread_info *info);
int remote_get_threadinfo (threadref *threadid, int fieldset,
gdb_ext_thread_info *info);
int parse_threadlist_response (const 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);
int remote_threadlist_iterator (rmt_thread_action stepfunction,
void *context, int looplimit);
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);
void extended_remote_restart ();
void get_offsets ();
void remote_check_symbols ();
void remote_supported_packet (const struct protocol_feature *feature,
enum packet_support support,
const char *argument);
void remote_query_supported ();
void remote_packet_size (const protocol_feature *feature,
packet_support support, const char *value);
void remote_serial_quit_handler ();
void remote_detach_pid (int pid);
void remote_vcont_probe ();
void remote_resume_with_hc (ptid_t ptid, int step,
gdb_signal siggnal);
void send_interrupt_sequence ();
void interrupt_query ();
void remote_notif_get_pending_events (notif_client *nc);
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);
void set_remote_traceframe ();
void check_binary_download (CORE_ADDR addr);
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_write_bytes (CORE_ADDR memaddr,
const gdb_byte *myaddr, ULONGEST len,
int unit_size, ULONGEST *xfered_len);
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_xfer_live_readonly_partial (gdb_byte *readbuf,
ULONGEST memaddr,
ULONGEST len,
int unit_size,
ULONGEST *xfered_len);
target_xfer_status remote_read_bytes (CORE_ADDR memaddr,
gdb_byte *myaddr, ULONGEST len,
int unit_size,
ULONGEST *xfered_len);
packet_result remote_send_printf (const char *format, ...)
ATTRIBUTE_PRINTF (2, 3);
target_xfer_status remote_flash_write (ULONGEST address,
ULONGEST length, ULONGEST *xfered_len,
const gdb_byte *data);
int readchar (int timeout);
void remote_serial_write (const char *str, int len);
int putpkt (const char *buf);
int putpkt_binary (const char *buf, int cnt);
int putpkt (const gdb::char_vector &buf)
{
return putpkt (buf.data ());
}
void skip_frame ();
long read_frame (gdb::char_vector *buf_p);
void getpkt (gdb::char_vector *buf, int forever);
int getpkt_or_notif_sane_1 (gdb::char_vector *buf, int forever,
int expecting_notif, int *is_notif);
int getpkt_sane (gdb::char_vector *buf, int forever);
int getpkt_or_notif_sane (gdb::char_vector *buf, int forever,
int *is_notif);
int remote_vkill (int pid);
void remote_kill_k ();
void extended_remote_disable_randomization (int val);
int extended_remote_run (const std::string &args);
void send_environment_packet (const char *action,
const char *packet,
const char *value);
void extended_remote_environment_support ();
void extended_remote_set_inferior_cwd ();
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_read_qxfer (const char *object_name,
const char *annex,
gdb_byte *readbuf, ULONGEST offset,
LONGEST len,
ULONGEST *xfered_len,
struct packet_config *packet);
void push_stop_reply (struct stop_reply *new_event);
bool vcont_r_supported ();
void packet_command (const char *args, int from_tty);
private: /* data fields */
/* The remote state. Don't reference this directly. Use the
get_remote_state method instead. */
remote_state m_remote_state;
};
static const target_info extended_remote_target_info = {
"extended-remote",
N_("Extended remote serial target in gdb-specific protocol"),
remote_doc
};
/* Set up the extended remote target by extending the standard remote
target and adding to it. */
class extended_remote_target final : public remote_target
{
public:
const target_info &info () const override
{ return extended_remote_target_info; }
/* Open an extended-remote connection. */
static void open (const char *, int);
bool can_create_inferior () override { return true; }
void create_inferior (const char *, const std::string &,
char **, int) override;
void detach (inferior *, int) override;
bool can_attach () override { return true; }
void attach (const char *, int) override;
void post_attach (int) override;
bool supports_disable_randomization () override;
};
/* Per-program-space data key. */
static const struct program_space_key<char, gdb::xfree_deleter<char>>
remote_pspace_data;
/* 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 std::string remote_exec_file_var;
/* 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.
The alignment chosen is arbitrary; usually data bus width is
important here, not the possibly larger cache line size. */
enum { REMOTE_ALIGN_WRITES = 16 };
/* Prototypes for local functions. */
static int hexnumlen (ULONGEST num);
static int stubhex (int ch);
static int hexnumstr (char *, ULONGEST);
static int hexnumnstr (char *, ULONGEST, int);
static CORE_ADDR remote_address_masked (CORE_ADDR);
static void print_packet (const char *);
static int stub_unpack_int (const char *buff, int fieldlength);
struct packet_config;
static void show_packet_config_cmd (struct packet_config *config);
static void show_remote_protocol_packet_cmd (struct ui_file *file,
int from_tty,
struct cmd_list_element *c,
const char *value);
static ptid_t read_ptid (const char *buf, const char **obuf);
static void remote_async_inferior_event_handler (gdb_client_data);
static bool remote_read_description_p (struct target_ops *target);
static void remote_console_output (const char *msg);
static void remote_btrace_reset (remote_state *rs);
static void remote_unpush_and_throw (remote_target *target);
/* For "remote". */
static struct cmd_list_element *remote_cmdlist;
/* For "set remote" and "show remote". */
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 bool use_range_stepping = true;
/* From the remote target's point of view, each thread is in one of these three
states. */
enum class resume_state
{
/* Not resumed - we haven't been asked to resume this thread. */
NOT_RESUMED,
/* We have been asked to resume this thread, but haven't sent a vCont action
for it yet. We'll need to consider it next time commit_resume is
called. */
RESUMED_PENDING_VCONT,
/* We have been asked to resume this thread, and we have sent a vCont action
for it. */
RESUMED,
};
/* Information about a thread's pending vCont-resume. Used when a thread is in
the remote_resume_state::RESUMED_PENDING_VCONT state. remote_target::resume
stores this information which is then picked up by
remote_target::commit_resume to know which is the proper action for this
thread to include in the vCont packet. */
struct resumed_pending_vcont_info
{
/* True if the last resume call for this thread was a step request, false
if a continue request. */
bool step;
/* The signal specified in the last resume call for this thread. */
gdb_signal sig;
};
/* Private data that we'll store in (struct thread_info)->priv. */
struct remote_thread_info : public private_thread_info
{
std::string extra;
std::string name;
int core = -1;
/* Thread handle, perhaps a pthread_t or thread_t value, stored as a
sequence of bytes. */
gdb::byte_vector thread_handle;
/* Whether the target stopped for a breakpoint/watchpoint. */
enum target_stop_reason stop_reason = TARGET_STOPPED_BY_NO_REASON;
/* This is set to the data address of the access causing the target
to stop for a watchpoint. */
CORE_ADDR watch_data_address = 0;
/* Get the thread's resume state. */
enum resume_state get_resume_state () const
{
return m_resume_state;
}
/* Put the thread in the NOT_RESUMED state. */
void set_not_resumed ()
{
m_resume_state = resume_state::NOT_RESUMED;
}
/* Put the thread in the RESUMED_PENDING_VCONT state. */
void set_resumed_pending_vcont (bool step, gdb_signal sig)
{
m_resume_state = resume_state::RESUMED_PENDING_VCONT;
m_resumed_pending_vcont_info.step = step;
m_resumed_pending_vcont_info.sig = sig;
}
/* Get the information this thread's pending vCont-resumption.
Must only be called if the thread is in the RESUMED_PENDING_VCONT resume
state. */
const struct resumed_pending_vcont_info &resumed_pending_vcont_info () const
{
gdb_assert (m_resume_state == resume_state::RESUMED_PENDING_VCONT);
return m_resumed_pending_vcont_info;
}
/* Put the thread in the VCONT_RESUMED state. */
void set_resumed ()
{
m_resume_state = resume_state::RESUMED;
}
private:
/* Resume state for this thread. This is used to implement vCont action
coalescing (only when the target operates in non-stop mode).
remote_target::resume moves the thread to the RESUMED_PENDING_VCONT state,
which notes that this thread must be considered in the next commit_resume
call.
remote_target::commit_resume sends a vCont packet with actions for the
threads in the RESUMED_PENDING_VCONT state and moves them to the
VCONT_RESUMED state.
When reporting a stop to the core for a thread, that thread is moved back
to the NOT_RESUMED state. */
enum resume_state m_resume_state = resume_state::NOT_RESUMED;
/* Extra info used if the thread is in the RESUMED_PENDING_VCONT state. */
struct resumed_pending_vcont_info m_resumed_pending_vcont_info;
};
remote_state::remote_state ()
: buf (400)
{
}
remote_state::~remote_state ()
{
xfree (this->last_pass_packet);
xfree (this->last_program_signals_packet);
xfree (this->finished_object);
xfree (this->finished_annex);
}
/* Utility: generate error from an incoming stub packet. */
static void
trace_error (char *buf)
{
if (*buf++ != 'E')
return; /* not an error msg */
switch (*buf)
{
case '1': /* malformed packet error */
if (*++buf == '0') /* general case: */
error (_("remote.c: error in outgoing packet."));
else
error (_("remote.c: error in outgoing packet at field #%ld."),
strtol (buf, NULL, 16));
default:
error (_("Target returns error code '%s'."), buf);
}
}
/* Utility: wait for reply from stub, while accepting "O" packets. */
char *
remote_target::remote_get_noisy_reply ()
{
struct remote_state *rs = get_remote_state ();
do /* Loop on reply from remote stub. */
{
char *buf;
QUIT; /* Allow user to bail out with ^C. */
getpkt (&rs->buf, 0);
buf = rs->buf.data ();
if (buf[0] == 'E')
trace_error (buf);
else if (startswith (buf, "qRelocInsn:"))
{
ULONGEST ul;
CORE_ADDR from, to, org_to;
const char *p, *pp;
int adjusted_size = 0;
int relocated = 0;
p = buf + strlen ("qRelocInsn:");
pp = unpack_varlen_hex (p, &ul);
if (*pp != ';')
error (_("invalid qRelocInsn packet: %s"), buf);
from = ul;
p = pp + 1;
unpack_varlen_hex (p, &ul);
to = ul;
org_to = to;
try
{
gdbarch_relocate_instruction (target_gdbarch (), &to, from);
relocated = 1;
}
catch (const gdb_exception &ex)
{
if (ex.error == MEMORY_ERROR)
{
/* Propagate memory errors silently back to the
target. The stub may have limited the range of
addresses we can write to, for example. */
}
else
{
/* Something unexpectedly bad happened. Be verbose
so we can tell what, and propagate the error back
to the stub, so it doesn't get stuck waiting for
a response. */
exception_fprintf (gdb_stderr, ex,
_("warning: relocating instruction: "));
}
putpkt ("E01");
}
if (relocated)
{
adjusted_size = to - org_to;
xsnprintf (buf, rs->buf.size (), "qRelocInsn:%x", adjusted_size);
putpkt (buf);
}
}
else if (buf[0] == 'O' && buf[1] != 'K')
remote_console_output (buf + 1); /* 'O' message from stub */
else
return buf; /* Here's the actual reply. */
}
while (1);
}
struct remote_arch_state *
remote_state::get_remote_arch_state (struct gdbarch *gdbarch)
{
remote_arch_state *rsa;
auto it = this->m_arch_states.find (gdbarch);
if (it == this->m_arch_states.end ())
{
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. */
if (this->buf.size () < rsa->remote_packet_size)
this->buf.resize (2 * rsa->remote_packet_size);
}
else
rsa = &it->second;
return rsa;
}
/* Fetch the global remote target state. */
remote_state *
remote_target::get_remote_state ()
{
/* 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. */
m_remote_state.get_remote_arch_state (target_gdbarch ());
return &m_remote_state;
}
/* Fetch the remote exec-file from the current program space. */
static const char *
get_remote_exec_file (void)
{
char *remote_exec_file;
remote_exec_file = remote_pspace_data.get (current_program_space);
if (remote_exec_file == NULL)
return "";
return remote_exec_file;
}
/* Set the remote exec file for PSPACE. */
static void
set_pspace_remote_exec_file (struct program_space *pspace,
const char *remote_exec_file)
{
char *old_file = remote_pspace_data.get (pspace);
xfree (old_file);
remote_pspace_data.set (pspace, xstrdup (remote_exec_file));
}
/* The "set/show remote exec-file" set command hook. */
static void
set_remote_exec_file (const char *ignored, int from_tty,
struct cmd_list_element *c)
{
set_pspace_remote_exec_file (current_program_space,
remote_exec_file_var.c_str ());
}
/* The "set/show remote exec-file" show command hook. */
static void
show_remote_exec_file (struct ui_file *file, int from_tty,
struct cmd_list_element *cmd, const char *value)
{
fprintf_filtered (file, "%s\n", get_remote_exec_file ());
}
static int
map_regcache_remote_table (struct gdbarch *gdbarch, struct packet_reg *regs)
{
int regnum, num_remote_regs, offset;
struct packet_reg **remote_regs;
for (regnum = 0; regnum < gdbarch_num_regs (gdbarch); regnum++)
{
struct packet_reg *r = &regs[regnum];
if (register_size (gdbarch, regnum) == 0)
/* Do not try to fetch zero-sized (placeholder) registers. */
r->pnum = -1;
else
r->pnum = gdbarch_remote_register_number (gdbarch, regnum);
r->regnum = regnum;
}
/* Define the g/G packet format as the contents of each register
with a remote protocol number, in order of ascending protocol
number. */
remote_regs = XALLOCAVEC (struct packet_reg *, gdbarch_num_regs (gdbarch));
for (num_remote_regs = 0, regnum = 0;
regnum < gdbarch_num_regs (gdbarch);
regnum++)
if (regs[regnum].pnum != -1)
remote_regs[num_remote_regs++] = &regs[regnum];
std::sort (remote_regs, remote_regs + num_remote_regs,
[] (const packet_reg *a, const packet_reg *b)
{ return a->pnum < b->pnum; });
for (regnum = 0, offset = 0; regnum < num_remote_regs; regnum++)
{
remote_regs[regnum]->in_g_packet = 1;
remote_regs[regnum]->offset = offset;
offset += register_size (gdbarch, remote_regs[regnum]->regnum);
}
return offset;
}
/* Given the architecture described by GDBARCH, return the remote
protocol register's number and the register's offset in the g/G
packets of GDB register REGNUM, in PNUM and POFFSET respectively.
If the target does not have a mapping for REGNUM, return false,
otherwise, return true. */
int
remote_register_number_and_offset (struct gdbarch *gdbarch, int regnum,
int *pnum, int *poffset)
{
gdb_assert (regnum < gdbarch_num_regs (gdbarch));
std::vector<packet_reg> regs (gdbarch_num_regs (gdbarch));
map_regcache_remote_table (gdbarch, regs.data ());
*pnum = regs[regnum].pnum;
*poffset = regs[regnum].offset;
return *pnum != -1;
}
remote_arch_state::remote_arch_state (struct gdbarch *gdbarch)
{
/* Use the architecture to build a regnum<->pnum table, which will be
1:1 unless a feature set specifies otherwise. */
this->regs.reset (new packet_reg [gdbarch_num_regs (gdbarch)] ());
/* Record the maximum possible size of the g packet - it may turn out
to be smaller. */
this->sizeof_g_packet
= map_regcache_remote_table (gdbarch, this->regs.get ());
/* Default maximum number of characters in a packet body. Many
remote stubs have a hardwired buffer size of 400 bytes
(c.f. BUFMAX in m68k-stub.c and i386-stub.c). BUFMAX-1 is used
as the maximum packet-size to ensure that the packet and an extra
NUL character can always fit in the buffer. This stops GDB
trashing stubs that try to squeeze an extra NUL into what is
already a full buffer (As of 1999-12-04 that was most stubs). */
this->remote_packet_size = 400 - 1;
/* This one is filled in when a ``g'' packet is received. */
this->actual_register_packet_size = 0;
/* Should rsa->sizeof_g_packet needs more space than the
default, adjust the size accordingly. Remember that each byte is
encoded as two characters. 32 is the overhead for the packet
header / footer. NOTE: cagney/1999-10-26: I suspect that 8
(``$NN:G...#NN'') is a better guess, the below has been padded a
little. */
if (this->sizeof_g_packet > ((this->remote_packet_size - 32) / 2))
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 = current_inferior ()->process_target ();
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. */
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 ());
if (rs->explicit_packet_size)
return rs->explicit_packet_size;
return rsa->remote_packet_size;
}
static struct packet_reg *
packet_reg_from_regnum (struct gdbarch *gdbarch, struct remote_arch_state *rsa,
long regnum)
{
if (regnum < 0 && regnum >= gdbarch_num_regs (gdbarch))
return NULL;
else
{
struct packet_reg *r = &rsa->regs[regnum];
gdb_assert (r->regnum == regnum);
return r;
}
}
static struct packet_reg *
packet_reg_from_pnum (struct gdbarch *gdbarch, struct remote_arch_state *rsa,
LONGEST pnum)
{
int i;
for (i = 0; i < gdbarch_num_regs (gdbarch); i++)
{
struct packet_reg *r = &rsa->regs[i];
if (r->pnum == pnum)
return r;
}
return NULL;
}
/* 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
sometimes preferable to send a break. On other systems such
as the Linux kernel, a break followed by g, which is Magic SysRq g
is required in order to interrupt the execution. */
const char interrupt_sequence_control_c[] = "Ctrl-C";
const char interrupt_sequence_break[] = "BREAK";
const char interrupt_sequence_break_g[] = "BREAK-g";
static const char *const interrupt_sequence_modes[] =
{
interrupt_sequence_control_c,
interrupt_sequence_break,
interrupt_sequence_break_g,
NULL
};
static const char *interrupt_sequence_mode = interrupt_sequence_control_c;
static void
show_interrupt_sequence (struct ui_file *file, int from_tty,
struct cmd_list_element *c,
const char *value)
{
if (interrupt_sequence_mode == interrupt_sequence_control_c)
fprintf_filtered (file,
_("Send the ASCII ETX character (Ctrl-c) "
"to the remote target to interrupt the "
"execution of the program.\n"));
else if (interrupt_sequence_mode == interrupt_sequence_break)
fprintf_filtered (file,
_("send a break signal to the remote target "
"to interrupt the execution of the program.\n"));
else if (interrupt_sequence_mode == interrupt_sequence_break_g)
fprintf_filtered (file,
_("Send a break signal and 'g' a.k.a. Magic SysRq g to "
"the remote target to interrupt the execution "
"of Linux kernel.\n"));
else
internal_error (__FILE__, __LINE__,
_("Invalid value for interrupt_sequence_mode: %s."),
interrupt_sequence_mode);
}
/* This boolean variable specifies whether interrupt_sequence is sent
to the remote target when gdb connects to it.
This is mostly needed when you debug the Linux kernel: The Linux kernel
expects BREAK g which is Magic SysRq g for connecting gdb. */
static bool interrupt_on_connect = false;
/* This variable is used to implement the "set/show remotebreak" commands.
Since these commands are now deprecated in favor of "set/show remote
interrupt-sequence", it no longer has any effect on the code. */
static bool remote_break;
static void
set_remotebreak (const char *args, int from_tty, struct cmd_list_element *c)
{
if (remote_break)
interrupt_sequence_mode = interrupt_sequence_break;
else
interrupt_sequence_mode = interrupt_sequence_control_c;
}
static void
show_remotebreak (struct ui_file *file, int from_tty,
struct cmd_list_element *c,
const char *value)
{
}
/* This variable sets the number of bits in an address that are to be
sent in a memory ("M" or "m") packet. Normally, after stripping
leading zeros, the entire address would be sent. This variable
restricts the address to REMOTE_ADDRESS_SIZE bits. HISTORY: The
initial implementation of remote.c restricted the address sent in
memory packets to ``host::sizeof long'' bytes - (typically 32
bits). Consequently, for 64 bit targets, the upper 32 bits of an
address was never sent. Since fixing this bug may cause a break in
some remote targets this variable is principally provided to
facilitate backward compatibility. */
static unsigned int remote_address_size;
/* User configurable variables for the number of characters in a
memory read/write packet. MIN (rsa->remote_packet_size,
rsa->sizeof_g_packet) is the default. Some targets need smaller
values (fifo overruns, et.al.) and some users need larger values
(speed up transfers). The variables ``preferred_*'' (the user
request), ``current_*'' (what was actually set) and ``forced_*''
(Positive - a soft limit, negative - a hard limit). */
struct memory_packet_config
{
const char *name;
long size;
int fixed_p;
};
/* 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. */
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)
what_they_get = get_fixed_memory_packet_size (config);
else
{
what_they_get = get_remote_packet_size ();
/* Limit the packet to the size specified by the user. */
if (config->size > 0
&& what_they_get > config->size)
what_they_get = config->size;
/* Limit it to the size of the targets ``g'' response unless we have
permission from the stub to use a larger packet size. */
if (rs->explicit_packet_size == 0
&& rsa->actual_register_packet_size > 0
&& what_they_get > rsa->actual_register_packet_size)
what_they_get = rsa->actual_register_packet_size;
}
if (what_they_get < MIN_MEMORY_PACKET_SIZE)
what_they_get = MIN_MEMORY_PACKET_SIZE;
/* Make sure there is room in the global buffer for this packet
(including its trailing NUL byte). */
if (rs->buf.size () < what_they_get + 1)
rs->buf.resize (2 * what_they_get);
return what_they_get;
}
/* Update the size of a read/write packet. If they user wants
something really big then do a sanity check. */
static void
set_memory_packet_size (const char *args, struct memory_packet_config *config)
{
int fixed_p = config->fixed_p;
long size = config->size;
if (args == NULL)
error (_("Argument required (integer, `fixed' or `limited')."));
else if (strcmp (args, "hard") == 0
|| strcmp (args, "fixed") == 0)
fixed_p = 1;
else if (strcmp (args, "soft") == 0
|| strcmp (args, "limit") == 0)
fixed_p = 0;
else
{
char *end;
size = strtoul (args, &end, 0);
if (args == end)
error (_("Invalid %s (bad syntax)."), config->name);
/* Instead of explicitly capping the size of a packet to or
disallowing it, the user is allowed to set the size to
something arbitrarily large. */
}
/* 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, query_size))
error (_("Packet size not changed."));
}
/* Update the config. */
config->fixed_p = fixed_p;
config->size = size;
}
static void
show_memory_packet_size (struct memory_packet_config *config)
{
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_fixed_memory_packet_size (config));
else
{
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");
}
}
/* FIXME: needs to be per-remote-target. */
static struct memory_packet_config memory_write_packet_config =
{
"memory-write-packet-size",
};
static void
set_memory_write_packet_size (const char *args, int from_tty)
{
set_memory_packet_size (args, &memory_write_packet_config);
}
static void
show_memory_write_packet_size (const char *args, int from_tty)
{
show_memory_packet_size (&memory_write_packet_config);
}
/* Show the number of hardware watchpoints that can be used. */
static void
show_hardware_watchpoint_limit (struct ui_file *file, int from_tty,
struct cmd_list_element *c,
const char *value)
{
fprintf_filtered (file, _("The maximum number of target hardware "
"watchpoints is %s.\n"), value);
}
/* Show the length limit (in bytes) for hardware watchpoints. */
static void
show_hardware_watchpoint_length_limit (struct ui_file *file, int from_tty,
struct cmd_list_element *c,
const char *value)
{
fprintf_filtered (file, _("The maximum length (in bytes) of a target "
"hardware watchpoint is %s.\n"), value);
}
/* Show the number of hardware breakpoints that can be used. */
static void
show_hardware_breakpoint_limit (struct ui_file *file, int from_tty,
struct cmd_list_element *c,
const char *value)
{
fprintf_filtered (file, _("The maximum number of target hardware "
"breakpoints is %s.\n"), value);
}
/* Controls the maximum number of characters to display in the debug output
for each remote packet. The remaining characters are omitted. */
static int remote_packet_max_chars = 512;
/* Show the maximum number of characters to display for each remote packet
when remote debugging is enabled. */
static void
show_remote_packet_max_chars (struct ui_file *file, int from_tty,
struct cmd_list_element *c,
const char *value)
{
fprintf_filtered (file, _("Number of remote packet characters to "
"display is %s.\n"), value);
}
long
remote_target::get_memory_write_packet_size ()
{
return get_memory_packet_size (&memory_write_packet_config);
}
/* FIXME: needs to be per-remote-target. */
static struct memory_packet_config memory_read_packet_config =
{
"memory-read-packet-size",
};
static void
set_memory_read_packet_size (const char *args, int from_tty)
{
set_memory_packet_size (args, &memory_read_packet_config);
}
static void
show_memory_read_packet_size (const char *args, int from_tty)
{
show_memory_packet_size (&memory_read_packet_config);
}
long
remote_target::get_memory_read_packet_size ()
{
long size = get_memory_packet_size (&memory_read_packet_config);
/* FIXME: cagney/1999-11-07: Functions like getpkt() need to get an
extra buffer size argument before the memory read size can be
increased beyond this. */
if (size > get_remote_packet_size ())
size = get_remote_packet_size ();
return size;
}
struct packet_config
{
const char *name;
const char *title;
/* If auto, GDB auto-detects support for this packet or feature,
either through qSupported, or by trying the packet and looking
at the response. If true, GDB assumes the target supports this
packet. If false, the packet is disabled. Configs that don't
have an associated command always have this set to auto. */
enum auto_boolean detect;
/* Does the target support this packet? */
enum packet_support support;
};
static enum packet_support packet_config_support (struct packet_config *config);
static enum packet_support packet_support (int packet);
static void
show_packet_config_cmd (struct packet_config *config)
{
const char *support = "internal-error";
switch (packet_config_support (config))
{
case PACKET_ENABLE:
support = "enabled";
break;
case PACKET_DISABLE:
support = "disabled";
break;
case PACKET_SUPPORT_UNKNOWN:
support = "unknown";
break;
}
switch (config->detect)
{
case AUTO_BOOLEAN_AUTO:
printf_filtered (_("Support for the `%s' packet "
"is auto-detected, currently %s.\n"),
config->name, support);
break;
case AUTO_BOOLEAN_TRUE:
case AUTO_BOOLEAN_FALSE:
printf_filtered (_("Support for the `%s' packet is currently %s.\n"),
config->name, support);
break;
}
}
static void
add_packet_config_cmd (struct packet_config *config, const char *name,
const char *title, int legacy)
{
char *set_doc;
char *show_doc;
char *cmd_name;
config->name = name;
config->title = title;
set_doc = xstrprintf ("Set use of remote protocol `%s' (%s) packet.",
name, title);
show_doc = xstrprintf ("Show current use of remote "
"protocol `%s' (%s) packet.",
name, title);
/* set/show TITLE-packet {auto,on,off} */
cmd_name = xstrprintf ("%s-packet", title);
set_show_commands cmds
= add_setshow_auto_boolean_cmd (cmd_name, class_obscure,
&config->detect, set_doc,
show_doc, NULL, /* help_doc */
NULL,
show_remote_protocol_packet_cmd,
&remote_set_cmdlist, &remote_show_cmdlist);
/* The command code copies the documentation strings. */
xfree (set_doc);
xfree (show_doc);
/* set/show remote NAME-packet {auto,on,off} -- legacy. */
if (legacy)
{
char *legacy_name;
legacy_name = xstrprintf ("%s-packet", name);
add_alias_cmd (legacy_name, cmds.set, class_obscure, 0,
&remote_set_cmdlist);
add_alias_cmd (legacy_name, cmds.show, class_obscure, 0,
&remote_show_cmdlist);
}
}
static enum packet_result
packet_check_result (const char *buf)
{
if (buf[0] != '\0')
{
/* The stub recognized the packet request. Check that the
operation succeeded. */
if (buf[0] == 'E'
&& isxdigit (buf[1]) && isxdigit (buf[2])
&& buf[3] == '\0')
/* "Enn" - definitely an error. */
return PACKET_ERROR;
/* Always treat "E." as an error. This will be used for
more verbose error messages, such as E.memtypes. */
if (buf[0] == 'E' && buf[1] == '.')
return PACKET_ERROR;
/* The packet may or may not be OK. Just assume it is. */
return PACKET_OK;
}
else
/* The stub does not support the packet. */
return PACKET_UNKNOWN;
}
static enum packet_result
packet_check_result (const gdb::char_vector &buf)
{
return packet_check_result (buf.data ());
}
static enum packet_result
packet_ok (const char *buf, struct packet_config *config)
{
enum packet_result result;
if (config->detect != AUTO_BOOLEAN_TRUE
&& config->support == PACKET_DISABLE)
internal_error (__FILE__, __LINE__,
_("packet_ok: attempt to use a disabled packet"));
result = packet_check_result (buf);
switch (result)
{
case PACKET_OK:
case PACKET_ERROR:
/* The stub recognized the packet request. */
if (config->support == PACKET_SUPPORT_UNKNOWN)
{
remote_debug_printf ("Packet %s (%s) is supported",
config->name, config->title);
config->support = PACKET_ENABLE;
}
break;
case PACKET_UNKNOWN:
/* The stub does not support the packet. */
if (config->detect == AUTO_BOOLEAN_AUTO
&& config->support == PACKET_ENABLE)
{
/* If the stub previously indicated that the packet was
supported then there is a protocol error. */
error (_("Protocol error: %s (%s) conflicting enabled responses."),
config->name, config->title);
}
else if (config->detect == AUTO_BOOLEAN_TRUE)
{
/* The user set it wrong. */
error (_("Enabled packet %s (%s) not recognized by stub"),
config->name, config->title);
}
remote_debug_printf ("Packet %s (%s) is NOT supported",
config->name, config->title);
config->support = PACKET_DISABLE;
break;
}
return result;
}
static enum packet_result
packet_ok (const gdb::char_vector &buf, struct packet_config *config)
{
return packet_ok (buf.data (), config);
}
enum {
PACKET_vCont = 0,
PACKET_X,
PACKET_qSymbol,
PACKET_P,
PACKET_p,
PACKET_Z0,
PACKET_Z1,
PACKET_Z2,
PACKET_Z3,
PACKET_Z4,
PACKET_vFile_setfs,
PACKET_vFile_open,
PACKET_vFile_pread,
PACKET_vFile_pwrite,
PACKET_vFile_close,
PACKET_vFile_unlink,
PACKET_vFile_readlink,
PACKET_vFile_fstat,
PACKET_qXfer_auxv,
PACKET_qXfer_features,
PACKET_qXfer_exec_file,
PACKET_qXfer_libraries,
PACKET_qXfer_libraries_svr4,
PACKET_qXfer_memory_map,
PACKET_qXfer_osdata,
PACKET_qXfer_threads,
PACKET_qXfer_statictrace_read,
PACKET_qXfer_traceframe_info,
PACKET_qXfer_uib,
PACKET_qGetTIBAddr,
PACKET_qGetTLSAddr,
PACKET_qSupported,
PACKET_qTStatus,
PACKET_QPassSignals,
PACKET_QCatchSyscalls,
PACKET_QProgramSignals,
PACKET_QSetWorkingDir,
PACKET_QStartupWithShell,
PACKET_QEnvironmentHexEncoded,
PACKET_QEnvironmentReset,
PACKET_QEnvironmentUnset,
PACKET_qCRC,
PACKET_qSearch_memory,
PACKET_vAttach,
PACKET_vRun,
PACKET_QStartNoAckMode,
PACKET_vKill,
PACKET_qXfer_siginfo_read,
PACKET_qXfer_siginfo_write,
PACKET_qAttached,
/* Support for conditional tracepoints. */
PACKET_ConditionalTracepoints,
/* Support for target-side breakpoint conditions. */
PACKET_ConditionalBreakpoints,
/* Support for target-side breakpoint commands. */
PACKET_BreakpointCommands,
/* Support for fast tracepoints. */
PACKET_FastTracepoints,
/* Support for static tracepoints. */
PACKET_StaticTracepoints,
/* Support for installing tracepoints while a trace experiment is
running. */
PACKET_InstallInTrace,
PACKET_bc,
PACKET_bs,
PACKET_TracepointSource,
PACKET_QAllow,
PACKET_qXfer_fdpic,
PACKET_QDisableRandomization,
PACKET_QAgent,
PACKET_QTBuffer_size,
PACKET_Qbtrace_off,
PACKET_Qbtrace_bts,
PACKET_Qbtrace_pt,
PACKET_qXfer_btrace,
/* Support for the QNonStop packet. */
PACKET_QNonStop,
/* Support for the QThreadEvents packet. */
PACKET_QThreadEvents,
/* Support for multi-process extensions. */
PACKET_multiprocess_feature,
/* Support for enabling and disabling tracepoints while a trace
experiment is running. */
PACKET_EnableDisableTracepoints_feature,
/* Support for collecting strings using the tracenz bytecode. */
PACKET_tracenz_feature,
/* Support for continuing to run a trace experiment while GDB is
disconnected. */
PACKET_DisconnectedTracing_feature,
/* Support for qXfer:libraries-svr4:read with a non-empty annex. */
PACKET_augmented_libraries_svr4_read_feature,
/* Support for the qXfer:btrace-conf:read packet. */
PACKET_qXfer_btrace_conf,
/* Support for the Qbtrace-conf:bts:size packet. */
PACKET_Qbtrace_conf_bts_size,
/* Support for swbreak+ feature. */
PACKET_swbreak_feature,
/* Support for hwbreak+ feature. */
PACKET_hwbreak_feature,
/* Support for fork events. */
PACKET_fork_event_feature,
/* Support for vfork events. */
PACKET_vfork_event_feature,
/* Support for the Qbtrace-conf:pt:size packet. */
PACKET_Qbtrace_conf_pt_size,
/* Support for exec events. */
PACKET_exec_event_feature,
/* Support for query supported vCont actions. */
PACKET_vContSupported,
/* Support remote CTRL-C. */
PACKET_vCtrlC,
/* Support TARGET_WAITKIND_NO_RESUMED. */
PACKET_no_resumed,
/* Support for memory tagging, allocation tag fetch/store
packets and the tag violation stop replies. */
PACKET_memory_tagging_feature,
PACKET_MAX
};
/* FIXME: needs to be per-remote-target. Ignoring this for now,
assuming all remote targets are the same server (thus all support
the same packets). */
static struct packet_config remote_protocol_packets[PACKET_MAX];
/* Returns the packet's corresponding "set remote foo-packet" command
state. See struct packet_config for more details. */
static enum auto_boolean
packet_set_cmd_state (int packet)
{
return remote_protocol_packets[packet].detect;
}
/* Returns whether a given packet or feature is supported. This takes
into account the state of the corresponding "set remote foo-packet"
command, which may be used to bypass auto-detection. */
static enum packet_support
packet_config_support (struct packet_config *config)
{
switch (config->detect)
{
case AUTO_BOOLEAN_TRUE:
return PACKET_ENABLE;
case AUTO_BOOLEAN_FALSE:
return PACKET_DISABLE;
case AUTO_BOOLEAN_AUTO:
return config->support;
default:
gdb_assert_not_reached (_("bad switch"));
}
}
/* Same as packet_config_support, but takes the packet's enum value as
argument. */
static enum packet_support
packet_support (int packet)
{
struct packet_config *config = &remote_protocol_packets[packet];
return packet_config_support (config);
}
static void
show_remote_protocol_packet_cmd (struct ui_file *file, int from_tty,
struct cmd_list_element *c,
const char *value)
{
struct packet_config *packet;
gdb_assert (c->var.has_value ());
for (packet = remote_protocol_packets;
packet < &remote_protocol_packets[PACKET_MAX];
packet++)
{
if (&packet->detect == &c->var->get<enum auto_boolean> ())
{
show_packet_config_cmd (packet);
return;
}
}
internal_error (__FILE__, __LINE__, _("Could not find config for %s"),
c->name);
}
/* Should we try one of the 'Z' requests? */
enum Z_packet_type
{
Z_PACKET_SOFTWARE_BP,
Z_PACKET_HARDWARE_BP,
Z_PACKET_WRITE_WP,
Z_PACKET_READ_WP,
Z_PACKET_ACCESS_WP,
NR_Z_PACKET_TYPES
};
/* For compatibility with older distributions. Provide a ``set remote
Z-packet ...'' command that updates all the Z packet types. */
static enum auto_boolean remote_Z_packet_detect;
static void
set_remote_protocol_Z_packet_cmd (const char *args, int from_tty,
struct cmd_list_element *c)
{
int i;
for (i = 0; i < NR_Z_PACKET_TYPES; i++)
remote_protocol_packets[PACKET_Z0 + i].detect = remote_Z_packet_detect;
}
static void
show_remote_protocol_Z_packet_cmd (struct ui_file *file, int from_tty,
struct cmd_list_element *c,
const char *value)
{
int i;
for (i = 0; i < NR_Z_PACKET_TYPES; i++)
{
show_packet_config_cmd (&remote_protocol_packets[PACKET_Z0 + i]);
}
}
/* Returns true if the multi-process extensions are in effect. */
static int
remote_multi_process_p (struct remote_state *rs)
{
return packet_support (PACKET_multiprocess_feature) == PACKET_ENABLE;
}
/* Returns true if fork events are supported. */
static int
remote_fork_event_p (struct remote_state *rs)
{
return packet_support (PACKET_fork_event_feature) == PACKET_ENABLE;
}
/* Returns true if vfork events are supported. */
static int
remote_vfork_event_p (struct remote_state *rs)
{
return packet_support (PACKET_vfork_event_feature) == PACKET_ENABLE;
}
/* Returns true if exec events are supported. */
static int
remote_exec_event_p (struct remote_state *rs)
{
return packet_support (PACKET_exec_event_feature) == PACKET_ENABLE;
}
/* Returns true if memory tagging is supported, false otherwise. */
static bool
remote_memory_tagging_p ()
{
return packet_support (PACKET_memory_tagging_feature) == PACKET_ENABLE;
}
/* Insert fork catchpoint target routine. If fork events are enabled
then return success, nothing more to do. */
int
remote_target::insert_fork_catchpoint (int pid)
{
struct remote_state *rs = get_remote_state ();
return !remote_fork_event_p (rs);
}
/* Remove fork catchpoint target routine. Nothing to do, just
return success. */
int
remote_target::remove_fork_catchpoint (int pid)
{
return 0;
}
/* Insert vfork catchpoint target routine. If vfork events are enabled
then return success, nothing more to do. */
int
remote_target::insert_vfork_catchpoint (int pid)
{
struct remote_state *rs = get_remote_state ();
return !remote_vfork_event_p (rs);
}
/* Remove vfork catchpoint target routine. Nothing to do, just
return success. */
int
remote_target::remove_vfork_catchpoint (int pid)
{
return 0;
}
/* Insert exec catchpoint target routine. If exec events are
enabled, just return success. */
int
remote_target::insert_exec_catchpoint (int pid)
{
struct remote_state *rs = get_remote_state ();
return !remote_exec_event_p (rs);
}
/* Remove exec catchpoint target routine. Nothing to do, just
return success. */
int
remote_target::remove_exec_catchpoint (int pid)
{
return 0;
}
/* Take advantage of the fact that the TID field is not used, to tag
special ptids with it set to != 0. */
static const ptid_t magic_null_ptid (42000, -1, 1);
static const ptid_t not_sent_ptid (42000, -2, 1);
static const ptid_t any_thread_ptid (42000, 0, 1);
/* Find out if the stub attached to PID (and hence GDB should offer to
detach instead of killing it when bailing out). */
int
remote_target::remote_query_attached (int pid)
{
struct remote_state *rs = get_remote_state ();
size_t size = get_remote_packet_size ();
if (packet_support (PACKET_qAttached) == PACKET_DISABLE)
return 0;
if (remote_multi_process_p (rs))
xsnprintf (rs->buf.data (), size, "qAttached:%x", pid);
else
xsnprintf (rs->buf.data (), size, "qAttached");
putpkt (rs->buf);
getpkt (&rs->buf, 0);
switch (packet_ok (rs->buf,
&remote_protocol_packets[PACKET_qAttached]))
{
case PACKET_OK:
if (strcmp (rs->buf.data (), "1") == 0)
return 1;
break;
case PACKET_ERROR:
warning (_("Remote failure reply: %s"), rs->buf.data ());
break;
case PACKET_UNKNOWN:
break;
}
return 0;
}
/* Add PID to GDB's inferior table. If FAKE_PID_P is true, then PID
has been invented by GDB, instead of reported by the target. Since
we can be connected to a remote system before before knowing about
any inferior, mark the target with execution when we find the first
inferior. If ATTACHED is 1, then we had just attached to this
inferior. If it is 0, then we just created this inferior. If it
is -1, then try querying the remote stub to find out if it had
attached to the inferior or not. If TRY_OPEN_EXEC is true then
attempt to open this inferior's executable as the main executable
if no main executable is open already. */
inferior *
remote_target::remote_add_inferior (bool fake_pid_p, int pid, int attached,
int try_open_exec)
{
struct inferior *inf;
/* Check whether this process we're learning about is to be
considered attached, or if is to be considered to have been
spawned by the stub. */
if (attached == -1)
attached = remote_query_attached (pid);
if (gdbarch_has_global_solist (target_gdbarch ()))
{
/* If the target shares code across all inferiors, then every
attach adds a new inferior. */
inf = add_inferior (pid);
/* ... and every inferior is bound to the same program space.
However, each inferior may still have its own address
space. */
inf->aspace = maybe_new_address_space ();
inf->pspace = current_program_space;
}
else
{
/* In the traditional debugging scenario, there's a 1-1 match
between program/address spaces. We simply bind the inferior
to the program space's address space. */
inf = current_inferior ();
/* However, if the current inferior is already bound to a
process, find some other empty inferior. */
if (inf->pid != 0)
{
inf = nullptr;
for (inferior *it : all_inferiors ())
if (it->pid == 0)
{
inf = it;
break;
}
}
if (inf == nullptr)
{
/* Since all inferiors were already bound to a process, add
a new inferior. */
inf = add_inferior_with_spaces ();
}
switch_to_inferior_no_thread (inf);
inf->push_target (this);
inferior_appeared (inf, pid);
}
inf->attach_flag = attached;
inf->fake_pid_p = fake_pid_p;
/* If no main executable is currently open then attempt to
open the file that was executed to create this inferior. */
if (try_open_exec && get_exec_file (0) == NULL)
exec_file_locate_attach (pid, 0, 1);
/* Check for exec file mismatch, and let the user solve it. */
validate_exec_file (1);
return inf;
}
static remote_thread_info *get_remote_thread_info (thread_info *thread);
static remote_thread_info *get_remote_thread_info (remote_target *target,
ptid_t ptid);
/* Add thread PTID to GDB's thread list. Tag it as executing/running
according to RUNNING. */
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;
/* GDB historically didn't pull threads in the initial connection
setup. If the remote target doesn't even have a concept of
threads (e.g., a bare-metal target), even if internally we
consider that a single-threaded target, mentioning a new thread
might be confusing to the user. Be silent then, preserving the
age old behavior. */
if (rs->starting_up)
thread = add_thread_silent (this, ptid);
else
thread = add_thread (this, ptid);
/* We start by assuming threads are resumed. That state then gets updated
when we process a matching stop reply. */
get_remote_thread_info (thread)->set_resumed ();
set_executing (this, ptid, executing);
set_running (this, ptid, running);
return thread;
}
/* Come here when we learn about a thread id from the remote target.
It may be the first time we hear about such thread, so take the
opportunity to add it to GDB's thread list. In case this is the
first time we're noticing its corresponding inferior, add it to
GDB's inferior list as well. EXECUTING indicates whether the
thread is (internally) executing or stopped. */
void
remote_target::remote_notice_new_inferior (ptid_t currthread, bool executing)
{
/* In non-stop mode, we assume new found threads are (externally)
running until proven otherwise with a stop reply. In all-stop,
we can only get here if all threads are stopped. */
bool running = target_is_non_stop_p ();
/* 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. */
thread_info *tp = find_thread_ptid (this, 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. */
remote_add_thread (currthread, running, executing);
return;
}
if (!in_thread_list (this, currthread))
{
struct inferior *inf = NULL;
int pid = currthread.pid ();
if (inferior_ptid.is_pid ()
&& pid == inferior_ptid.pid ())
{
/* inferior_ptid has no thread member yet. This can happen
with the vAttach -> remote_wait,"TAAthread:" path if the
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 (this, ptid_t (pid)))
thread_change_ptid (this, inferior_ptid, currthread);
else
{
thread_info *thr
= remote_add_thread (currthread, running, executing);
switch_to_thread (thr);
}
return;
}
if (magic_null_ptid == inferior_ptid)
{
/* inferior_ptid is not set yet. This can happen with the
vRun -> remote_wait,"TAAthread:" path if the 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. */
thread_change_ptid (this, inferior_ptid, currthread);
return;
}
/* When connecting to a target remote, or to a target
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 (find_inferior_pid (this, currthread.pid ()) == NULL)
{
struct remote_state *rs = get_remote_state ();
bool fake_pid_p = !remote_multi_process_p (rs);
inf = remote_add_inferior (fake_pid_p,
currthread.pid (), -1, 1);
}
/* This is really a new thread. Add it. */
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
breakpoints), unless we're just setting up an all-stop
connection. */
if (inf != NULL)
{
struct remote_state *rs = get_remote_state ();
if (!rs->starting_up)
notice_new_inferior (new_thr, executing, 0);
}
}
}
/* Return THREAD's private thread data, creating it if necessary. */
static remote_thread_info *
get_remote_thread_info (thread_info *thread)
{
gdb_assert (thread != NULL);
if (thread->priv == NULL)
thread->priv.reset (new remote_thread_info);
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 (remote_target *target, ptid_t ptid)
{
thread_info *thr = find_thread_ptid (target, ptid);
return get_remote_thread_info (thr);
}
/* Call this function as a result of
1) A halt indication (T packet) containing a thread id
2) A direct query of currthread
3) Successful execution of set thread */
static void
record_currthread (struct remote_state *rs, ptid_t currthread)
{
rs->general_thread = currthread;
}
/* If 'QPassSignals' is supported, tell the remote stub what signals
it can simply pass through to the inferior without reporting. */
void
remote_target::pass_signals (gdb::array_view<const unsigned char> pass_signals)
{
if (packet_support (PACKET_QPassSignals) != PACKET_DISABLE)
{
char *pass_packet, *p;
int count = 0;
struct remote_state *rs = get_remote_state ();
gdb_assert (pass_signals.size () < 256);
for (size_t i = 0; i < pass_signals.size (); i++)
{
if (pass_signals[i])
count++;
}
pass_packet = (char *) xmalloc (count * 3 + strlen ("QPassSignals:") + 1);
strcpy (pass_packet, "QPassSignals:");
p = pass_packet + strlen (pass_packet);
for (size_t i = 0; i < pass_signals.size (); i++)
{
if (pass_signals[i])
{
if (i >= 16)
*p++ = tohex (i >> 4);
*p++ = tohex (i & 15);
if (count)
*p++ = ';';
else
break;
count--;
}
}
*p = 0;
if (!rs->last_pass_packet || strcmp (rs->last_pass_packet, pass_packet))
{
putpkt (pass_packet);
getpkt (&rs->buf, 0);
packet_ok (rs->buf, &remote_protocol_packets[PACKET_QPassSignals]);
xfree (rs->last_pass_packet);
rs->last_pass_packet = pass_packet;
}
else
xfree (pass_packet);
}
}
/* If 'QCatchSyscalls' is supported, tell the remote stub
to report syscalls to GDB. */
int
remote_target::set_syscall_catchpoint (int pid, bool needed, int any_count,
gdb::array_view<const int> syscall_counts)
{
const char *catch_packet;
enum packet_result result;
int n_sysno = 0;
if (packet_support (PACKET_QCatchSyscalls) == PACKET_DISABLE)
{
/* Not supported. */
return 1;
}
if (needed && any_count == 0)
{
/* Count how many syscalls are to be caught. */
for (size_t i = 0; i < syscall_counts.size (); i++)
{
if (syscall_counts[i] != 0)
n_sysno++;
}
}
remote_debug_printf ("pid %d needed %d any_count %d n_sysno %d",
pid, needed, any_count, n_sysno);
std::string built_packet;
if (needed)
{
/* Prepare a packet with the sysno list, assuming max 8+1
characters for a sysno. If the resulting packet size is too
big, fallback on the non-selective packet. */
const int maxpktsz = strlen ("QCatchSyscalls:1") + n_sysno * 9 + 1;
built_packet.reserve (maxpktsz);
built_packet = "QCatchSyscalls:1";
if (any_count == 0)
{
/* Add in each syscall to be caught. */
for (size_t i = 0; i < syscall_counts.size (); i++)
{
if (syscall_counts[i] != 0)
string_appendf (built_packet, ";%zx", i);
}
}
if (built_packet.size () > get_remote_packet_size ())
{
/* catch_packet too big. Fallback to less efficient
non selective mode, with GDB doing the filtering. */
catch_packet = "QCatchSyscalls:1";
}
else
catch_packet = built_packet.c_str ();
}
else
catch_packet = "QCatchSyscalls:0";
struct remote_state *rs = get_remote_state ();
putpkt (catch_packet);
getpkt (&rs->buf, 0);
result = packet_ok (rs->buf, &remote_protocol_packets[PACKET_QCatchSyscalls]);
if (result == PACKET_OK)
return 0;
else
return -1;
}
/* If 'QProgramSignals' is supported, tell the remote stub what
signals it should pass through to the inferior when detaching. */
void
remote_target::program_signals (gdb::array_view<const unsigned char> signals)
{
if (packet_support (PACKET_QProgramSignals) != PACKET_DISABLE)
{
char *packet, *p;
int count = 0;
struct remote_state *rs = get_remote_state ();
gdb_assert (signals.size () < 256);
for (size_t i = 0; i < signals.size (); i++)
{
if (signals[i])
count++;
}
packet = (char *) xmalloc (count * 3 + strlen ("QProgramSignals:") + 1);
strcpy (packet, "QProgramSignals:");
p = packet + strlen (packet);
for (size_t i = 0; i < signals.size (); i++)
{
if (signal_pass_state (i))
{
if (i >= 16)
*p++ = tohex (i >> 4);
*p++ = tohex (i & 15);
if (count)
*p++ = ';';
else
break;
count--;
}
}
*p = 0;
if (!rs->last_program_signals_packet
|| strcmp (rs->last_program_signals_packet, packet) != 0)
{
putpkt (packet);
getpkt (&rs->buf, 0);
packet_ok (rs->buf, &remote_protocol_packets[PACKET_QProgramSignals]);
xfree (rs->last_program_signals_packet);
rs->last_program_signals_packet = packet;
}
else
xfree (packet);
}
}
/* If PTID is MAGIC_NULL_PTID, don't set any thread. If PTID is
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. */
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;
char *buf = rs->buf.data ();
char *endbuf = buf + get_remote_packet_size ();
if (state == ptid)
return;
*buf++ = 'H';
*buf++ = gen ? 'g' : 'c';
if (ptid == magic_null_ptid)
xsnprintf (buf, endbuf - buf, "0");
else if (ptid == any_thread_ptid)
xsnprintf (buf, endbuf - buf, "0");
else if (ptid == minus_one_ptid)
xsnprintf (buf, endbuf - buf, "-1");
else
write_ptid (buf, endbuf, ptid);
putpkt (rs->buf);
getpkt (&rs->buf, 0);
if (gen)
rs->general_thread = ptid;
else
rs->continue_thread = ptid;
}
void
remote_target::set_general_thread (ptid_t ptid)
{
set_thread (ptid, 1);
}
void
remote_target::set_continue_thread (ptid_t ptid)
{
set_thread (ptid, 0);
}
/* Change the remote current process. Which thread within the process
ends up selected isn't important, as long as it is the same process
as what INFERIOR_PTID points to.
This comes from that fact that there is no explicit notion of
"selected process" in the protocol. The selected process for
general operations is the process the selected general thread
belongs to. */
void
remote_target::set_general_process ()
{
struct remote_state *rs = get_remote_state ();
/* If the remote can't handle multiple processes, don't bother. */
if (!remote_multi_process_p (rs))
return;
/* We only need to change the remote current thread if it's pointing
at some other process. */
if (rs->general_thread.pid () != inferior_ptid.pid ())
set_general_thread (inferior_ptid);
}
/* Return nonzero if this is the main thread that we made up ourselves
to model non-threaded targets as single-threaded. */
static int
remote_thread_always_alive (ptid_t ptid)
{
if (ptid == magic_null_ptid)
/* The main thread is always alive. */
return 1;
if (ptid.pid () != 0 && ptid.lwp () == 0)
/* The main thread is always alive. This can happen after a
vAttach, if the remote side doesn't support
multi-threading. */
return 1;
return 0;
}
/* Return nonzero if the thread PTID is still alive on the remote
system. */
bool
remote_target::thread_alive (ptid_t ptid)
{
struct remote_state *rs = get_remote_state ();
char *p, *endp;
/* Check if this is a thread that we made up ourselves to model
non-threaded targets as single-threaded. */
if (remote_thread_always_alive (ptid))
return 1;
p = rs->buf.data ();
endp = p + get_remote_packet_size ();
*p++ = 'T';
write_ptid (p, endp, ptid);
putpkt (rs->buf);
getpkt (&rs->buf, 0);
return (rs->buf[0] == 'O' && rs->buf[1] == 'K');
}
/* Return a pointer to a thread name if we know it and NULL otherwise.
The thread_info object owns the memory for the name. */
const char *
remote_target::thread_name (struct thread_info *info)
{
if (info->priv != NULL)
{
const std::string &name = get_remote_thread_info (info)->name;
return !name.empty () ? name.c_str () : NULL;
}
return NULL;
}
/* About these extended threadlist and threadinfo packets. They are
variable length packets but, the fields within them are often fixed
length. They are redundant enough to send over UDP as is the
remote protocol in general. There is a matching unit test module
in libstub. */
/* WARNING: This threadref data structure comes from the remote O.S.,
libstub protocol encoding, and remote.c. It is not particularly
changable. */
/* Right now, the internal structure is int. We want it to be bigger.
Plan to fix this. */
typedef int gdb_threadref; /* Internal GDB thread reference. */
/* gdb_ext_thread_info is an internal GDB data structure which is
equivalent to the reply of the remote threadinfo packet. */
struct gdb_ext_thread_info
{
threadref threadid; /* External form of thread reference. */
int active; /* Has state interesting to GDB?
regs, stack. */
char display[256]; /* Brief state display, name,
blocked/suspended. */
char shortname[32]; /* To be used to name threads. */
char more_display[256]; /* Long info, statistics, queue depth,
whatever. */
};
/* The volume of remote transfers can be limited by submitting
a mask containing bits specifying the desired information.
Use a union of these values as the 'selection' parameter to
get_thread_info. FIXME: Make these TAG names more thread specific. */
#define TAG_THREADID 1
#define TAG_EXISTS 2
#define TAG_DISPLAY 4
#define TAG_THREADNAME 8
#define TAG_MOREDISPLAY 16
#define BUF_THREAD_ID_SIZE (OPAQUETHREADBYTES * 2)
static const char *unpack_nibble (const char *buf, int *val);
static const char *unpack_byte (const char *buf, int *value);
static char *pack_int (char *buf, int value);
static const char *unpack_int (const char *buf, int *value);
static const char *unpack_string (const char *src, char *dest, int length);
static char *pack_threadid (char *pkt, threadref *id);
static const char *unpack_threadid (const char *inbuf, threadref *id);
void int_to_threadref (threadref *id, int value);
static int threadref_to_int (threadref *ref);
static void copy_threadref (threadref *dest, threadref *src);
static int threadmatch (threadref *dest, threadref *src);
static char *pack_threadinfo_request (char *pkt, int mode,
threadref *id);
static char *pack_threadlist_request (char *pkt, int startflag,
int threadcount,
threadref *nextthread);
static int remote_newthread_step (threadref *ref, void *context);
/* Write a PTID to BUF. ENDBUF points to one-passed-the-end of the
buffer we're allowed to write to. Returns
BUF+CHARACTERS_WRITTEN. */
char *
remote_target::write_ptid (char *buf, const char *endbuf, ptid_t ptid)
{
int pid, tid;
struct remote_state *rs = get_remote_state ();
if (remote_multi_process_p (rs))
{
pid = ptid.pid ();
if (pid < 0)
buf += xsnprintf (buf, endbuf - buf, "p-%x.", -pid);
else
buf += xsnprintf (buf, endbuf - buf, "p%x.", pid);
}
tid = ptid.lwp ();
if (tid < 0)
buf += xsnprintf (buf, endbuf - buf, "-%x", -tid);
else
buf += xsnprintf (buf, endbuf - buf, "%x", tid);
return buf;
}
/* Extract a PTID from BUF. If non-null, OBUF is set to one past the
last parsed char. Returns null_ptid if no thread id is found, and
throws an error if the thread id has an invalid format. */
static ptid_t
read_ptid (const char *buf, const char **obuf)
{
const char *p = buf;
const char *pp;
ULONGEST pid = 0, tid = 0;
if (*p == 'p')
{
/* Multi-process ptid. */
pp = unpack_varlen_hex (p + 1, &pid);
if (*pp != '.')
error (_("invalid remote ptid: %s"), p);
p = pp;
pp = unpack_varlen_hex (p + 1, &tid);
if (obuf)
*obuf = pp;
return ptid_t (pid, tid);
}
/* No multi-process. Just a tid. */
pp = unpack_varlen_hex (p, &tid);
/* Return null_ptid when no thread id is found. */
if (p == pp)
{
if (obuf)
*obuf = pp;
return null_ptid;
}
/* Since the stub is not sending a process id, then default to
what's in inferior_ptid, unless it's null at this point. If so,
then since there's no way to know the pid of the reported
threads, use the magic number. */
if (inferior_ptid == null_ptid)
pid = magic_null_ptid.pid ();
else
pid = inferior_ptid.pid ();
if (obuf)
*obuf = pp;
return ptid_t (pid, tid);
}
static int
stubhex (int ch)
{
if (ch >= 'a' && ch <= 'f')
return ch - 'a' + 10;
if (ch >= '0' && ch <= '9')
return ch - '0';
if (ch >= 'A' && ch <= 'F')
return ch - 'A' + 10;
return -1;
}
static int
stub_unpack_int (const char *buff, int fieldlength)
{
int nibble;
int retval = 0;
while (fieldlength)
{
nibble = stubhex (*buff++);
retval |= nibble;
fieldlength--;
if (fieldlength)
retval = retval << 4;
}
return retval;
}
static const char *
unpack_nibble (const char *buf, int *val)
{
*val = fromhex (*buf++);
return buf;
}
static const char *
unpack_byte (const char *buf, int *value)
{
*value = stub_unpack_int (buf, 2);
return buf + 2;
}
static char *
pack_int (char *buf, int value)
{
buf = pack_hex_byte (buf, (value >> 24) & 0xff);
buf = pack_hex_byte (buf, (value >> 16) & 0xff);
buf = pack_hex_byte (buf, (value >> 8) & 0x0ff);
buf = pack_hex_byte (buf, (value & 0xff));
return buf;
}
static const char *
unpack_int (const char *buf, int *value)
{
*value = stub_unpack_int (buf, 8);
return buf + 8;
}
#if 0 /* Currently unused, uncomment when needed. */
static char *pack_string (char *pkt, char *string);
static char *
pack_string (char *pkt, char *string)
{
char ch;
int len;
len = strlen (string);
if (len > 200)
len = 200; /* Bigger than most GDB packets, junk??? */
pkt = pack_hex_byte (pkt, len);
while (len-- > 0)
{
ch = *string++;
if ((ch == '\0') || (ch == '#'))
ch = '*'; /* Protect encapsulation. */
*pkt++ = ch;
}
return pkt;
}
#endif /* 0 (unused) */
static const char *
unpack_string (const char *src, char *dest, int length)
{
while (length--)
*dest++ = *src++;
*dest = '\0';
return src;
}
static char *
pack_threadid (char *pkt, threadref *id)
{
char *limit;
unsigned char *altid;
altid = (unsigned char *) id;
limit = pkt + BUF_THREAD_ID_SIZE;
while (pkt < limit)
pkt = pack_hex_byte (pkt, *altid++);
return pkt;
}
static const char *
unpack_threadid (const char *inbuf, threadref *id)
{
char *altref;
const char *limit = inbuf + BUF_THREAD_ID_SIZE;
int x, y;
altref = (char *) id;
while (inbuf < limit)
{
x = stubhex (*inbuf++);
y = stubhex (*inbuf++);
*altref++ = (x << 4) | y;
}
return inbuf;
}
/* Externally, threadrefs are 64 bits but internally, they are still
ints. This is due to a mismatch of specifications. We would like
to use 64bit thread references internally. This is an adapter
function. */
void
int_to_threadref (threadref *id, int value)
{
unsigned char *scan;
scan = (unsigned char *) id;
{
int i = 4;
while (i--)
*scan++ = 0;
}
*scan++ = (value >> 24) & 0xff;
*scan++ = (value >> 16) & 0xff;
*scan++ = (value >> 8) & 0xff;
*scan++ = (value & 0xff);
}
static int
threadref_to_int (threadref *ref)
{
int i, value = 0;
unsigned char *scan;
scan = *ref;
scan += 4;
i = 4;
while (i-- > 0)
value = (value << 8) | ((*scan++) & 0xff);
return value;