diff options
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/NEWS | 8 | ||||
-rw-r--r-- | gdb/doc/gdb.texinfo | 3 | ||||
-rw-r--r-- | gdb/remote.c | 108 | ||||
-rw-r--r-- | gdb/remote.h | 35 |
4 files changed, 119 insertions, 35 deletions
@@ -39,6 +39,14 @@ set logging enabled on|off show logging enabled These commands set or show whether logging is enabled or disabled. +* Changed commands + +maint packet + This command can now print a reply, if the reply includes + non-printable characters. Any non-printable characters are printed + as escaped hex, e.g. \x?? where '??' is replaces with the value of + the non-printable character. + * Python API ** New function gdb.add_history(), which takes a gdb.Value object diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 1a944b1..738f2e4 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -39286,6 +39286,9 @@ displays the response packet. @value{GDBN} supplies the initial @samp{$} character, the terminating @samp{#} character, and the checksum. +Any non-printable characters in the reply are printed as escaped hex, +e.g. @samp{\x00}, @samp{\x01}, etc. + @kindex maint print architecture @item maint print architecture @r{[}@var{file}@r{]} Print the entire architecture configuration. The optional argument diff --git a/gdb/remote.c b/gdb/remote.c index 25a4d3c..b426980 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -956,8 +956,6 @@ public: /* Remote specific methods. */ 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 @@ -1030,8 +1028,6 @@ 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; @@ -9495,17 +9491,6 @@ escape_buffer (const char *buf, int n) return std::move (stb.string ()); } -/* Display a null-terminated packet on stdout, for debugging, using C - string notation. */ - -static void -print_packet (const char *buf) -{ - puts_filtered ("\""); - fputstr_filtered (buf, '"', gdb_stdout); - puts_filtered ("\""); -} - int remote_target::putpkt (const char *buf) { @@ -11592,34 +11577,87 @@ remote_target::memory_map () return result; } -static void -packet_command (const char *args, int from_tty) +/* Set of callbacks used to implement the 'maint packet' command. */ + +struct cli_packet_command_callbacks : public send_remote_packet_callbacks { - remote_target *remote = get_current_remote_target (); + /* Called before the packet is sent. BUF is the packet content before + the protocol specific prefix, suffix, and escaping is added. */ - if (remote == nullptr) - error (_("command can only be used with remote target")); + void sending (gdb::array_view<const char> &buf) override + { + puts_filtered ("sending: "); + print_packet (buf); + puts_filtered ("\n"); + } - remote->packet_command (args, from_tty); -} + /* Called with BUF, the reply from the remote target. */ + + void received (gdb::array_view<const char> &buf) override + { + puts_filtered ("received: \""); + print_packet (buf); + puts_filtered ("\"\n"); + } + +private: + + /* Print BUF o gdb_stdout. Any non-printable bytes in BUF are printed as + '\x??' with '??' replaced by the hexadecimal value of the byte. */ + + static void + print_packet (gdb::array_view<const char> &buf) + { + string_file stb; + + for (int i = 0; i < buf.size (); ++i) + { + gdb_byte c = buf[i]; + if (isprint (c)) + fputc_unfiltered (c, &stb); + else + fprintf_unfiltered (&stb, "\\x%02x", (unsigned char) c); + } + + puts_filtered (stb.string ().c_str ()); + } +}; + +/* See remote.h. */ void -remote_target::packet_command (const char *args, int from_tty) +send_remote_packet (gdb::array_view<const char> &buf, + send_remote_packet_callbacks *callbacks) { - if (!args) - error (_("remote-packet command requires packet text as argument")); + if (buf.size () == 0 || buf.data ()[0] == '\0') + error (_("a remote packet must not be empty")); - puts_filtered ("sending: "); - print_packet (args); - puts_filtered ("\n"); - putpkt (args); + remote_target *remote = get_current_remote_target (); + if (remote == nullptr) + error (_("packets can only be sent to a remote target")); - remote_state *rs = get_remote_state (); + callbacks->sending (buf); - getpkt (&rs->buf, 0); - puts_filtered ("received: "); - print_packet (rs->buf.data ()); - puts_filtered ("\n"); + remote->putpkt_binary (buf.data (), buf.size ()); + remote_state *rs = remote->get_remote_state (); + int bytes = remote->getpkt_sane (&rs->buf, 0); + + if (bytes < 0) + error (_("error while fetching packet from remote target")); + + gdb::array_view<const char> view (&rs->buf[0], bytes); + callbacks->received (view); +} + +/* Entry point for the 'maint packet' command. */ + +static void +cli_packet_command (const char *args, int from_tty) +{ + cli_packet_command_callbacks cb; + gdb::array_view<const char> view + = gdb::make_array_view (args, args == nullptr ? 0 : strlen (args)); + send_remote_packet (view, &cb); } #if 0 @@ -14890,7 +14928,7 @@ Argument is a single section name (default: all loaded sections).\n\ To compare only read-only loaded sections, specify the -r option."), &cmdlist); - add_cmd ("packet", class_maintenance, packet_command, _("\ + add_cmd ("packet", class_maintenance, cli_packet_command, _("\ Send an arbitrary packet to a remote target.\n\ maintenance packet TEXT\n\ If GDB is talking to an inferior via the GDB serial protocol, then\n\ diff --git a/gdb/remote.h b/gdb/remote.h index 46bfa01..0178294 100644 --- a/gdb/remote.h +++ b/gdb/remote.h @@ -78,4 +78,39 @@ extern int remote_register_number_and_offset (struct gdbarch *gdbarch, extern void remote_notif_get_pending_events (remote_target *remote, struct notif_client *np); extern bool remote_target_is_non_stop_p (remote_target *t); + +/* An abstract class that represents the set of callbacks that are made + from the send_remote_packet function (declared below). */ + +struct send_remote_packet_callbacks +{ + /* The SENDING callback is called once send_remote_packet has performed + its error checking and setup, just before the packet is sent to the + remote target. BUF is the content of the packet that will be sent + (before any of the protocol specific prefix, suffix, or escaping is + applied). */ + + virtual void sending (gdb::array_view<const char> &buf) = 0; + + /* The RECEIVED callback is called once a reply has been received from + the remote target. The content of the reply is in BUF which can't be + modified, and which is not guaranteed to remain valid after the + RECEIVED call has returned. If you need to preserve the contents of + BUF then a copy should be taken. */ + + virtual void received (gdb::array_view<const char> &buf) = 0; +}; + +/* Send BUF to the current remote target. If BUF points to an empty + string, either zero length, or the first character is the null + character, then an error is thrown. If the current target is not a + remote target then an error is thrown. + + Calls CALLBACKS->sending() just before the packet is sent to the remote + target, and calls CALLBACKS->received() with the reply once this is + received from the remote target. */ + +extern void send_remote_packet (gdb::array_view<const char> &buf, + send_remote_packet_callbacks *callbacks); + #endif |