diff options
Diffstat (limited to 'gdb/remote.c')
-rw-r--r-- | gdb/remote.c | 229 |
1 files changed, 142 insertions, 87 deletions
diff --git a/gdb/remote.c b/gdb/remote.c index 66c58c8..e1b54c6 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -1,6 +1,6 @@ /* Remote target communications for serial-line targets in custom GDB protocol - Copyright (C) 1988-2024 Free Software Foundation, Inc. + Copyright (C) 1988-2025 Free Software Foundation, Inc. This file is part of GDB. @@ -19,9 +19,9 @@ /* See the GDB User Guide for details of the GDB remote protocol. */ -#include <ctype.h> #include <fcntl.h> #include "exceptions.h" +#include "gdbsupport/common-inferior.h" #include "inferior.h" #include "infrun.h" #include "bfd.h" @@ -80,6 +80,7 @@ #include "async-event.h" #include "gdbsupport/selftest.h" #include "cli/cli-style.h" +#include "gdbsupport/remote-args.h" /* The remote target. */ @@ -250,6 +251,7 @@ enum { PACKET_vFile_readlink, PACKET_vFile_fstat, PACKET_vFile_stat, + PACKET_vFile_lstat, PACKET_qXfer_auxv, PACKET_qXfer_features, PACKET_qXfer_exec_file, @@ -399,6 +401,10 @@ enum { errors, and so they should not need to check for this feature. */ PACKET_accept_error_message, + /* Not really a packet; this indicates support for sending the vRun + inferior arguments as a single string. */ + PACKET_vRun_single_argument, + PACKET_MAX }; @@ -824,6 +830,11 @@ struct remote_features bool remote_memory_tagging_p () const { return packet_support (PACKET_memory_tagging_feature) == PACKET_ENABLE; } + /* Returns true if there is support for sending vRun inferior arguments + as a single string. */ + bool remote_vrun_single_arg_p () const + { return packet_support (PACKET_vRun_single_argument) == PACKET_ENABLE; } + /* Reset all packets back to "unknown support". Called when opening a new connection to a remote target. */ void reset_all_packet_configs_support (); @@ -1022,8 +1033,8 @@ public: int fileio_fstat (int fd, struct stat *sb, fileio_error *target_errno) override; - int fileio_stat (struct inferior *inf, const char *filename, - struct stat *sb, fileio_error *target_errno) override; + int fileio_lstat (struct inferior *inf, const char *filename, + struct stat *sb, fileio_error *target_errno) override; int fileio_close (int fd, fileio_error *target_errno) override; @@ -1385,7 +1396,8 @@ public: /* Remote specific methods. */ void remote_kill_k (); void extended_remote_disable_randomization (int val); - int extended_remote_run (const std::string &args); + int extended_remote_run (const std::string &remote_exec_file, + const std::string &args); void send_environment_packet (const char *action, const char *packet, @@ -1513,14 +1525,7 @@ remote_register_is_expedited (int regnum) } /* Per-program-space data key. */ -static const registry<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; +static const registry<program_space>::key<std::string> remote_pspace_data; /* The size to align memory write packets, when practical. The protocol does not guarantee any alignment, and gdb will generate short @@ -1850,47 +1855,47 @@ remote_target::get_remote_state () /* Fetch the remote exec-file from the current program space. */ -static const char * +static const std::string & 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; + const std::string *remote_exec_file + = remote_pspace_data.get (current_program_space); + if (remote_exec_file == nullptr) + remote_exec_file = remote_pspace_data.emplace (current_program_space); + 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) + const std::string &filename) { - char *old_file = remote_pspace_data.get (pspace); - - xfree (old_file); - remote_pspace_data.set (pspace, xstrdup (remote_exec_file)); + remote_pspace_data.clear (pspace); + remote_pspace_data.emplace (pspace, filename); } -/* The "set/show remote exec-file" set command hook. */ +/* The "set remote exec-file" callback. */ static void -set_remote_exec_file (const char *ignored, int from_tty, - struct cmd_list_element *c) +set_remote_exec_file_cb (const std::string &filename) { set_pspace_remote_exec_file (current_program_space, - remote_exec_file_var.c_str ()); + filename); } -/* The "set/show remote exec-file" show command hook. */ +/* Implement the "show remote exec-file" command. */ static void show_remote_exec_file (struct ui_file *file, int from_tty, struct cmd_list_element *cmd, const char *value) { - gdb_printf (file, "%s\n", get_remote_exec_file ()); + const std::string &filename = get_remote_exec_file (); + if (filename.empty ()) + gdb_printf (file, _("The remote exec-file is unset, the default remote " + "executable will be used.\n")); + else + gdb_printf (file, "The remote exec-file is \"%s\".\n", filename.c_str ()); } static int @@ -2556,7 +2561,7 @@ packet_check_result (const char *buf) /* The stub recognized the packet request. Check that the operation succeeded. */ if (buf[0] == 'E' - && isxdigit (buf[1]) && isxdigit (buf[2]) + && c_isxdigit (buf[1]) && c_isxdigit (buf[2]) && buf[3] == '\0') /* "Enn" - definitely an error. */ return packet_result::make_numeric_error (buf + 1); @@ -2901,6 +2906,10 @@ remote_target::remote_add_inferior (bool fake_pid_p, int pid, int attached, inf = add_inferior_with_spaces (); } switch_to_inferior_no_thread (inf); + + /* Clear any data left by previous executions. */ + target_pre_inferior (); + inf->push_target (this); inferior_appeared (inf, pid); } @@ -3026,6 +3035,12 @@ remote_target::remote_notice_new_inferior (ptid_t currthread, bool executing) inf = remote_add_inferior (fake_pid_p, currthread.pid (), -1, 1); + + /* Fetch the target description for this inferior. Make sure to + leave the currently selected inferior unchanged. */ + scoped_restore_current_thread restore_thread; + switch_to_inferior_no_thread (inf); + target_find_description (); } /* This is really a new thread. Add it. */ @@ -4656,8 +4671,6 @@ remote_target::get_offsets () if (bss_addr != data_addr) warning (_("Target reported unsupported offsets: %s"), buf); } - else - lose = 1; } else if (startswith (ptr, "TextSeg=")) { @@ -4866,7 +4879,11 @@ remote_target::add_current_inferior_and_thread (const char *wait_status) fake_pid_p = true; } - remote_add_inferior (fake_pid_p, curr_ptid.pid (), -1, 1); + const auto inf = remote_add_inferior (fake_pid_p, curr_ptid.pid (), -1, 1); + switch_to_inferior_no_thread (inf); + + /* Fetch the target description for this inferior. */ + target_find_description (); /* Add the main thread and switch to it. Don't try reading registers yet, since we haven't fetched the target description @@ -4943,7 +4960,7 @@ remote_target::process_initial_stop_replies (int from_tty) event_ptid = target_wait (waiton_ptid, &ws, TARGET_WNOHANG); if (remote_debug) - print_target_wait_results (waiton_ptid, event_ptid, ws); + print_target_wait_results (waiton_ptid, event_ptid, ws, this); switch (ws.kind ()) { @@ -5005,6 +5022,24 @@ remote_target::process_initial_stop_replies (int from_tty) the inferiors. */ if (!non_stop) { + /* Ensure changes to the thread state are propagated to the + frontend. In non-stop mode only the current inferior will be + stopped, but in all-stop mode, all inferiors will change, and + the frontend will need updating. */ + process_stratum_target *finish_target; + ptid_t finish_ptid; + if (non_stop) + { + finish_target = current_inferior ()->process_target (); + finish_ptid = ptid_t (current_inferior ()->pid); + } + else + { + finish_target = nullptr; + finish_ptid = minus_one_ptid; + } + scoped_finish_thread_state finish_state (finish_target, finish_ptid); + { /* At this point, the remote target is not async. It needs to be for the poll in stop_all_threads to consider events from it, so enable @@ -5862,6 +5897,8 @@ static const struct protocol_feature remote_protocol_features[] = { { "error-message", PACKET_ENABLE, remote_supported_packet, PACKET_accept_error_message }, { "binary-upload", PACKET_DISABLE, remote_supported_packet, PACKET_x }, + { "single-inf-arg", PACKET_DISABLE, remote_supported_packet, + PACKET_vRun_single_argument }, }; static char *remote_support_xml; @@ -5973,6 +6010,10 @@ remote_target::remote_query_supported () != AUTO_BOOLEAN_FALSE) remote_query_supported_append (&q, "memory-tagging+"); + if (m_features.packet_set_cmd_state (PACKET_vRun_single_argument) + != AUTO_BOOLEAN_FALSE) + remote_query_supported_append (&q, "single-inf-arg+"); + /* Keep this one last to work around a gdbserver <= 7.10 bug in the qSupported:xmlRegisters=i386 handling. */ if (remote_support_xml != NULL @@ -6164,6 +6205,7 @@ remote_unpush_target (remote_target *target) /* We have to unpush the target from all inferiors, even those that aren't running. */ scoped_restore_current_inferior restore_current_inferior; + scoped_restore_current_program_space restore_program_space; for (inferior *inf : all_inferiors (target)) { @@ -9035,7 +9077,7 @@ remote_target::process_g_packet (struct regcache *regcache) /* Reply describes registers byte by byte, each byte encoded as two hex characters. Suck them all up, then supply them to the - register cacheing/storage mechanism. */ + register caching/storage mechanism. */ p = rs->buf.data (); for (i = 0; i < rsa->sizeof_g_packet; i++) @@ -10814,11 +10856,11 @@ remote_target::extended_remote_disable_randomization (int val) } int -remote_target::extended_remote_run (const std::string &args) +remote_target::extended_remote_run (const std::string &remote_exec_file, + const std::string &args) { struct remote_state *rs = get_remote_state (); int len; - const char *remote_exec_file = get_remote_exec_file (); /* If the user has disabled vRun support, or we have detected that support is not available, do not try it. */ @@ -10828,23 +10870,27 @@ remote_target::extended_remote_run (const std::string &args) strcpy (rs->buf.data (), "vRun;"); len = strlen (rs->buf.data ()); - if (strlen (remote_exec_file) * 2 + len >= get_remote_packet_size ()) + if (remote_exec_file.size () * 2 + len >= get_remote_packet_size ()) error (_("Remote file name too long for run packet")); - len += 2 * bin2hex ((gdb_byte *) remote_exec_file, rs->buf.data () + len, - strlen (remote_exec_file)); + len += 2 * bin2hex ((gdb_byte *) remote_exec_file.data (), + rs->buf.data () + len, + remote_exec_file.size ()); if (!args.empty ()) { - int i; + std::vector<std::string> split_args; + if (!m_features.remote_vrun_single_arg_p ()) + split_args = gdb::remote_args::split (args); + else + split_args.push_back (args); - gdb_argv argv (args.c_str ()); - for (i = 0; argv[i] != NULL; i++) + for (const auto &a : split_args) { - if (strlen (argv[i]) * 2 + 1 + len >= get_remote_packet_size ()) + if (a.size () * 2 + 1 + len >= get_remote_packet_size ()) error (_("Argument list too long for run packet")); rs->buf[len++] = ';'; - len += 2 * bin2hex ((gdb_byte *) argv[i], rs->buf.data () + len, - strlen (argv[i])); + len += 2 * bin2hex ((gdb_byte *) a.c_str (), rs->buf.data () + len, + a.size ()); } } @@ -10872,7 +10918,7 @@ remote_target::extended_remote_run (const std::string &args) "try \"set remote exec-file\"?")); else error (_("Running \"%s\" on the remote target failed"), - remote_exec_file); + remote_exec_file.c_str ()); default: gdb_assert_not_reached ("bad switch"); } @@ -10992,7 +11038,7 @@ extended_remote_target::create_inferior (const char *exec_file, int run_worked; char *stop_reply; struct remote_state *rs = get_remote_state (); - const char *remote_exec_file = get_remote_exec_file (); + const std::string &remote_exec_file = get_remote_exec_file (); /* If running asynchronously, register the target file descriptor with the event loop. */ @@ -11022,7 +11068,7 @@ Remote replied unexpectedly while setting startup-with-shell: %s"), extended_remote_set_inferior_cwd (); /* Now restart the remote server. */ - run_worked = extended_remote_run (args) != -1; + run_worked = extended_remote_run (remote_exec_file, args) != -1; if (!run_worked) { /* vRun was not supported. Fail if we need it to do what the @@ -11650,7 +11696,7 @@ remote_target::remote_write_qxfer (const char *object_name, i = snprintf (rs->buf.data (), max_size, "qXfer:%s:write:%s:%s:", object_name, annex ? annex : "", - phex_nz (offset, sizeof offset)); + phex_nz (offset)); max_size -= (i + 1); /* Escape as much data as fits into rs->buf. */ @@ -11715,8 +11761,8 @@ remote_target::remote_read_qxfer (const char *object_name, snprintf (rs->buf.data (), get_remote_packet_size () - 4, "qXfer:%s:read:%s:%s,%s", object_name, annex ? annex : "", - phex_nz (offset, sizeof offset), - phex_nz (n, sizeof n)); + phex_nz (offset), + phex_nz (n)); i = putpkt (rs->buf); if (i < 0) return TARGET_XFER_E_IO; @@ -11935,7 +11981,7 @@ remote_target::xfer_partial (enum target_object object, while (annex[i] && (i < (get_remote_packet_size () - 8))) { /* Bad caller may have sent forbidden characters. */ - gdb_assert (isprint (annex[i]) && annex[i] != '$' && annex[i] != '#'); + gdb_assert (c_isprint (annex[i]) && annex[i] != '$' && annex[i] != '#'); *p2++ = annex[i]; i++; } @@ -12014,7 +12060,7 @@ remote_target::search_memory (CORE_ADDR start_addr, ULONGEST search_space_len, i = snprintf (rs->buf.data (), max_size, "qSearch:memory:%s;%s;", phex_nz (start_addr, addr_size), - phex_nz (search_space_len, sizeof (search_space_len))); + phex_nz (search_space_len)); max_size -= (i + 1); /* Escape as much data as fits into rs->buf. */ @@ -12185,7 +12231,7 @@ private: for (int i = 0; i < buf.size (); ++i) { gdb_byte c = buf[i]; - if (isprint (c)) + if (c_isprint (c)) gdb_putc (c, &stb); else gdb_printf (&stb, "\\x%02x", (unsigned char) c); @@ -13149,7 +13195,7 @@ remote_target::fileio_readlink (struct inferior *inf, const char *filename, return ret; } -/* Helper function to handle ::fileio_fstat and ::fileio_stat result +/* Helper function to handle ::fileio_fstat and ::fileio_lstat result processing. When this function is called the remote syscall has been performed and we know we didn't get an error back. @@ -13160,10 +13206,10 @@ remote_target::fileio_readlink (struct inferior *inf, const char *filename, data) is to be placed in ST. */ static int -fileio_process_fstat_and_stat_reply (const char *attachment, - int attachment_len, - int expected_len, - struct stat *st) +fileio_process_fstat_and_lstat_reply (const char *attachment, + int attachment_len, + int expected_len, + struct stat *st) { struct fio_stat fst; @@ -13225,15 +13271,15 @@ remote_target::fileio_fstat (int fd, struct stat *st, fileio_error *remote_errno return 0; } - return fileio_process_fstat_and_stat_reply (attachment, attachment_len, - ret, st); + return fileio_process_fstat_and_lstat_reply (attachment, attachment_len, + ret, st); } -/* Implementation of to_fileio_stat. */ +/* Implementation of to_fileio_lstat. */ int -remote_target::fileio_stat (struct inferior *inf, const char *filename, - struct stat *st, fileio_error *remote_errno) +remote_target::fileio_lstat (struct inferior *inf, const char *filename, + struct stat *st, fileio_error *remote_errno) { struct remote_state *rs = get_remote_state (); char *p = rs->buf.data (); @@ -13242,14 +13288,14 @@ remote_target::fileio_stat (struct inferior *inf, const char *filename, if (remote_hostio_set_filesystem (inf, remote_errno) != 0) return {}; - remote_buffer_add_string (&p, &left, "vFile:stat:"); + remote_buffer_add_string (&p, &left, "vFile:lstat:"); remote_buffer_add_bytes (&p, &left, (const gdb_byte *) filename, strlen (filename)); int attachment_len; const char *attachment; - int ret = remote_hostio_send_command (p - rs->buf.data (), PACKET_vFile_stat, + int ret = remote_hostio_send_command (p - rs->buf.data (), PACKET_vFile_lstat, remote_errno, &attachment, &attachment_len); @@ -13258,8 +13304,8 @@ remote_target::fileio_stat (struct inferior *inf, const char *filename, if (ret < 0) return ret; - return fileio_process_fstat_and_stat_reply (attachment, attachment_len, - ret, st); + return fileio_process_fstat_and_lstat_reply (attachment, attachment_len, + ret, st); } /* Implementation of to_filesystem_is_local. */ @@ -13763,7 +13809,7 @@ remote_target::download_tracepoint (struct bp_location *loc) encode_actions_rsp (loc, &tdp_actions, &stepping_actions); tpaddr = loc->address; - strcpy (addrbuf, phex (tpaddr, sizeof (CORE_ADDR))); + strcpy (addrbuf, phex (tpaddr)); ret = snprintf (buf.data (), buf.size (), "QTDP:%x:%s:%c:%lx:%x", b->number, addrbuf, /* address */ (b->enable_state == bp_enabled ? 'E' : 'D'), @@ -14027,7 +14073,7 @@ remote_target::enable_tracepoint (struct bp_location *location) xsnprintf (rs->buf.data (), get_remote_packet_size (), "QTEnable:%x:%s", location->owner->number, - phex (location->address, sizeof (CORE_ADDR))); + phex (location->address)); putpkt (rs->buf); remote_get_noisy_reply (); if (rs->buf[0] == '\0') @@ -14043,7 +14089,7 @@ remote_target::disable_tracepoint (struct bp_location *location) xsnprintf (rs->buf.data (), get_remote_packet_size (), "QTDisable:%x:%s", location->owner->number, - phex (location->address, sizeof (CORE_ADDR))); + phex (location->address)); putpkt (rs->buf); remote_get_noisy_reply (); if (rs->buf[0] == '\0') @@ -15569,7 +15615,7 @@ remote_target::commit_requested_thread_options () *obuf_p++ = ';'; obuf_p += xsnprintf (obuf_p, obuf_endp - obuf_p, "%s", - phex_nz (options, sizeof (options))); + phex_nz (options)); if (tp->ptid != magic_null_ptid) { *obuf_p++ = ':'; @@ -15808,8 +15854,8 @@ create_fetch_memtags_request (gdb::char_vector &packet, CORE_ADDR address, std::string request = string_printf ("qMemTags:%s,%s:%s", phex_nz (address, addr_size), - phex_nz (len, sizeof (len)), - phex_nz (type, sizeof (type))); + phex_nz (len), + phex_nz (type)); strcpy (packet.data (), request.c_str ()); } @@ -15843,8 +15889,8 @@ create_store_memtags_request (gdb::char_vector &packet, CORE_ADDR address, /* Put together the main packet, address and length. */ std::string request = string_printf ("QMemTags:%s,%s:%s:", phex_nz (address, addr_size), - phex_nz (len, sizeof (len)), - phex_nz (type, sizeof (type))); + phex_nz (len), + phex_nz (type)); request += bin2hex (tags.data (), tags.size ()); /* Check if we have exceeded the maximum packet size. */ @@ -16161,9 +16207,7 @@ test_packet_check_result () } /* namespace selftests */ #endif /* GDB_SELF_TEST */ -void _initialize_remote (); -void -_initialize_remote () +INIT_GDB_FILE (remote) { add_target (remote_target_info, remote_target::open); add_target (extended_remote_target_info, extended_remote_target::open); @@ -16422,6 +16466,8 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL, add_packet_config_cmd (PACKET_vFile_stat, "vFile:stat", "hostio-stat", 0); + add_packet_config_cmd (PACKET_vFile_lstat, "vFile:lstat", "hostio-lstat", 0); + add_packet_config_cmd (PACKET_vAttach, "vAttach", "attach", 0); add_packet_config_cmd (PACKET_vRun, "vRun", "run", 0); @@ -16539,6 +16585,10 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL, add_packet_config_cmd (PACKET_accept_error_message, "error-message", "error-message", 0); + add_packet_config_cmd (PACKET_vRun_single_argument, + "single-inferior-argument-feature", + "single-inferior-argument-feature", 0); + /* Assert that we've registered "set remote foo-packet" commands for all packet configs. */ { @@ -16608,10 +16658,15 @@ Transfer files to and from the remote target system."), &remote_cmdlist); add_setshow_string_noescape_cmd ("exec-file", class_files, - &remote_exec_file_var, _("\ -Set the remote pathname for \"run\"."), _("\ -Show the remote pathname for \"run\"."), NULL, - set_remote_exec_file, + _("\ +Set the remote file name for starting inferiors."), _("\ +Show the remote file name for starting inferiors."), _("\ +This is the file name, on the remote target, used when starting an\n\ +inferior, for example with the \"run\", \"start\", or \"starti\"\n\ +commands. This setting is only useful when debugging a remote target,\n\ +otherwise, this setting is not used."), + set_remote_exec_file_cb, + get_remote_exec_file, show_remote_exec_file, &remote_set_cmdlist, &remote_show_cmdlist); |