@@ -192,6 +192,12 @@ QThreadOptions in qSupported
QThreadOptions packet, and the qSupported response can contain the
set of thread options the remote stub supports.
+x addr,length
+ Given ADDR and LENGTH, fetch LENGTH units from the memory at address
+ ADDR and send the fetched data in binary format. This packet is
+ equivalent to 'm', except that the data in the response are in
+ binary format.
+
*** Changes in GDB 14
* GDB now supports the AArch64 Scalable Matrix Extension 2 (SME2), which
@@ -43218,6 +43218,33 @@ for success (@pxref{Stop Reply Packets})
@cindex @samp{vStopped} packet
@xref{Notification Packets}.
+@item x @var{addr},@var{length}
+@anchor{x packet}
+@cindex @samp{x} packet
+Read @var{length} addressable memory units starting at address @var{addr}
+(@pxref{addressable memory unit}). Note that @var{addr} does not have to
+be aligned to any particular boundary.
+
+@cindex alignment of remote memory accesses
+@cindex size of remote memory accesses
+@cindex memory, alignment and size of remote accesses
+The stub need not use any particular size or alignment when gathering
+data from memory for the response; even if @var{addr} is word-aligned
+and @var{length} is a multiple of the word size, the stub is free to
+use byte accesses, or not. For this reason, this packet may not be
+suitable for accessing memory-mapped I/O devices.
+
+Reply:
+@table @samp
+@item b @var{XX@dots{}}
+Memory contents as binary data (@pxref{Binary Data}).
+The reply may contain fewer addressable memory units than requested if the
+server was reading from a trace frame memory and was able to read only part
+of the region of memory.
+@item E @var{NN}
+for an error
+@end table
+
@item X @var{addr},@var{length}:@var{XX@dots{}}
@anchor{X packet}
@cindex @samp{X} packet
@@ -193,6 +193,7 @@ struct packet_result
enum {
PACKET_vCont = 0,
PACKET_X,
+ PACKET_x,
PACKET_qSymbol,
PACKET_P,
PACKET_p,
@@ -9585,7 +9586,6 @@ remote_target::remote_read_bytes_1 (CORE_ADDR memaddr, gdb_byte *myaddr,
{
struct remote_state *rs = get_remote_state ();
int buf_size_bytes; /* Max size of packet output buffer. */
- char *p;
int todo_units;
int decoded_bytes;
@@ -9597,23 +9597,79 @@ remote_target::remote_read_bytes_1 (CORE_ADDR memaddr, gdb_byte *myaddr,
todo_units = std::min (len_units,
(ULONGEST) (buf_size_bytes / unit_size) / 2);
- /* Construct "m"<memaddr>","<len>". */
memaddr = remote_address_masked (memaddr);
- p = rs->buf.data ();
- *p++ = 'm';
- p += hexnumstr (p, (ULONGEST) memaddr);
- *p++ = ',';
- p += hexnumstr (p, (ULONGEST) todo_units);
- *p = '\0';
- putpkt (rs->buf);
- getpkt (&rs->buf);
+
+ /* Construct "m/x"<memaddr>","<len>". */
+ auto send_request = [this, rs, memaddr, todo_units] (char format) -> void
+ {
+ char *buffer = rs->buf.data ();
+ *buffer++ = format;
+ buffer += hexnumstr (buffer, (ULONGEST) memaddr);
+ *buffer++ = ',';
+ buffer += hexnumstr (buffer, (ULONGEST) todo_units);
+ *buffer = '\0';
+ putpkt (rs->buf);
+ };
+
+ /* Determine which packet format to use. The target's support for
+ 'x' may be unknown. We just try. If it doesn't work, we try
+ again using 'm'. */
+ char packet_format;
+ if (m_features.packet_support (PACKET_x) == PACKET_DISABLE)
+ packet_format = 'm';
+ else
+ packet_format = 'x';
+
+ send_request (packet_format);
+ int packet_len = getpkt (&rs->buf);
+ if (packet_len < 0)
+ return TARGET_XFER_E_IO;
+
+ if (m_features.packet_support (PACKET_x) == PACKET_SUPPORT_UNKNOWN)
+ {
+ if (rs->buf[0] == '\0')
+ {
+ remote_debug_printf ("binary uploading NOT supported by target");
+ m_features.m_protocol_packets[PACKET_x].support = PACKET_DISABLE;
+
+ /* Try again using 'm'. */
+ packet_format = 'm';
+ send_request (packet_format);
+ packet_len = getpkt (&rs->buf);
+ if (packet_len < 0)
+ return TARGET_XFER_E_IO;
+ }
+ else
+ {
+ remote_debug_printf ("binary uploading supported by target");
+ m_features.m_protocol_packets[PACKET_x].support = PACKET_ENABLE;
+ }
+ }
+
packet_result result = packet_check_result (rs->buf, false);
if (result.status () == PACKET_ERROR)
return TARGET_XFER_E_IO;
- /* Reply describes memory byte by byte, each byte encoded as two hex
- characters. */
- p = rs->buf.data ();
- decoded_bytes = hex2bin (p, myaddr, todo_units * unit_size);
+
+ char *p = rs->buf.data ();
+ if (packet_format == 'x')
+ {
+ if (*p != 'b')
+ return TARGET_XFER_E_IO;
+
+ /* Adjust for 'b'. */
+ p++;
+ packet_len--;
+ decoded_bytes = remote_unescape_input ((const gdb_byte *) p,
+ packet_len, myaddr,
+ todo_units * unit_size);
+ }
+ else
+ {
+ /* Reply describes memory byte by byte, each byte encoded as two hex
+ characters. */
+ decoded_bytes = hex2bin (p, myaddr, todo_units * unit_size);
+ }
+
/* Return what we have. Let higher layers handle partial reads. */
*xfered_len_units = (ULONGEST) (decoded_bytes / unit_size);
return (*xfered_len_units != 0) ? TARGET_XFER_OK : TARGET_XFER_EOF;
@@ -15842,6 +15898,8 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
add_packet_config_cmd (PACKET_X, "X", "binary-download", 1);
+ add_packet_config_cmd (PACKET_x, "x", "binary-upload", 0);
+
add_packet_config_cmd (PACKET_vCont, "vCont", "verbose-resume", 0);
add_packet_config_cmd (PACKET_QPassSignals, "QPassSignals", "pass-signals",
@@ -1333,6 +1333,13 @@ decode_M_packet (const char *from, CORE_ADDR *mem_addr_ptr,
hex2bin (from, *to_p, *len_ptr);
}
+void
+decode_x_packet (const char *from, CORE_ADDR *mem_addr_ptr,
+ unsigned int *len_ptr)
+{
+ decode_m_packet_params (from, mem_addr_ptr, len_ptr, '\0');
+}
+
int
decode_X_packet (char *from, int packet_len, CORE_ADDR *mem_addr_ptr,
unsigned int *len_ptr, unsigned char **to_p)
@@ -1477,12 +1484,13 @@ look_up_one_symbol (const char *name, CORE_ADDR *addrp, int may_ask_gdb)
while it figures out the address of the symbol. */
while (1)
{
+ CORE_ADDR mem_addr;
+ unsigned char *mem_buf;
+ unsigned int mem_len;
+ int new_len = -1;
+
if (cs.own_buf[0] == 'm')
{
- CORE_ADDR mem_addr;
- unsigned char *mem_buf;
- unsigned int mem_len;
-
decode_m_packet (&cs.own_buf[1], &mem_addr, &mem_len);
mem_buf = (unsigned char *) xmalloc (mem_len);
if (read_inferior_memory (mem_addr, mem_buf, mem_len) == 0)
@@ -1493,9 +1501,42 @@ look_up_one_symbol (const char *name, CORE_ADDR *addrp, int may_ask_gdb)
if (putpkt (cs.own_buf) < 0)
return -1;
}
+ else if (cs.own_buf[0] == 'x')
+ {
+ decode_x_packet (&cs.own_buf[1], &mem_addr, &mem_len);
+ mem_buf = (unsigned char *) xmalloc (mem_len);
+ if (read_inferior_memory (mem_addr, mem_buf, mem_len) == 0)
+ {
+ gdb_byte *buffer = (gdb_byte *) cs.own_buf;
+ *buffer++ = 'b';
+
+ int out_len_units;
+ new_len = remote_escape_output (mem_buf, mem_len, 1,
+ buffer,
+ &out_len_units,
+ PBUFSIZ);
+ new_len++; /* For the 'b' marker. */
+
+ if (out_len_units != mem_len)
+ {
+ write_enn (cs.own_buf);
+ new_len = -1;
+ }
+ else
+ suppress_next_putpkt_log ();
+ }
+ else
+ write_enn (cs.own_buf);
+
+ free (mem_buf);
+ int res = ((new_len == -1)
+ ? putpkt (cs.own_buf)
+ : putpkt_binary (cs.own_buf, new_len));
+ if (res < 0)
+ return -1;
+ }
else if (cs.own_buf[0] == 'v')
{
- int new_len = -1;
handle_v_requests (cs.own_buf, len, &new_len);
if (new_len != -1)
putpkt_binary (cs.own_buf, new_len);
@@ -1570,11 +1611,13 @@ relocate_instruction (CORE_ADDR *to, CORE_ADDR oldloc)
wait for the qRelocInsn "response". That requires re-entering
the main loop. For now, this is an adequate approximation; allow
GDB to access memory. */
- while (cs.own_buf[0] == 'm' || cs.own_buf[0] == 'M' || cs.own_buf[0] == 'X')
+ while (cs.own_buf[0] == 'm' || cs.own_buf[0] == 'M'
+ || cs.own_buf[0] == 'X' || cs.own_buf[0] == 'x')
{
CORE_ADDR mem_addr;
unsigned char *mem_buf = NULL;
unsigned int mem_len;
+ int new_len = -1;
if (cs.own_buf[0] == 'm')
{
@@ -1585,6 +1628,33 @@ relocate_instruction (CORE_ADDR *to, CORE_ADDR oldloc)
else
write_enn (cs.own_buf);
}
+ else if (cs.own_buf[0] == 'x')
+ {
+ decode_x_packet (&cs.own_buf[1], &mem_addr, &mem_len);
+ mem_buf = (unsigned char *) xmalloc (mem_len);
+ if (read_inferior_memory (mem_addr, mem_buf, mem_len) == 0)
+ {
+ gdb_byte *buffer = (gdb_byte *) cs.own_buf;
+ *buffer++ = 'b';
+
+ int out_len_units;
+ new_len = remote_escape_output (mem_buf, mem_len, 1,
+ buffer,
+ &out_len_units,
+ PBUFSIZ);
+ new_len++; /* For the 'b' marker. */
+
+ if (out_len_units != mem_len)
+ {
+ write_enn (cs.own_buf);
+ new_len = -1;
+ }
+ else
+ suppress_next_putpkt_log ();
+ }
+ else
+ write_enn (cs.own_buf);
+ }
else if (cs.own_buf[0] == 'X')
{
if (decode_X_packet (&cs.own_buf[1], len - 1, &mem_addr,
@@ -1603,7 +1673,11 @@ relocate_instruction (CORE_ADDR *to, CORE_ADDR oldloc)
write_enn (cs.own_buf);
}
free (mem_buf);
- if (putpkt (cs.own_buf) < 0)
+
+ int res = ((new_len == -1)
+ ? putpkt (cs.own_buf)
+ : putpkt_binary (cs.own_buf, new_len));
+ if (res < 0)
return -1;
len = getpkt (cs.own_buf);
if (len < 0)
@@ -57,6 +57,8 @@ void decode_m_packet (const char *from, CORE_ADDR * mem_addr_ptr,
unsigned int *len_ptr);
void decode_M_packet (const char *from, CORE_ADDR * mem_addr_ptr,
unsigned int *len_ptr, unsigned char **to_p);
+void decode_x_packet (const char *from, CORE_ADDR *mem_addr_ptr,
+ unsigned int *len_ptr);
int decode_X_packet (char *from, int packet_len, CORE_ADDR * mem_addr_ptr,
unsigned int *len_ptr, unsigned char **to_p);
int decode_xfer_write (char *buf, int packet_len,
@@ -4689,6 +4689,35 @@ process_serial_event (void)
else
write_enn (cs.own_buf);
break;
+ case 'x':
+ {
+ require_running_or_break (cs.own_buf);
+ decode_x_packet (&cs.own_buf[1], &mem_addr, &len);
+ int res = gdb_read_memory (mem_addr, mem_buf, len);
+ if (res < 0)
+ write_enn (cs.own_buf);
+ else
+ {
+ gdb_byte *buffer = (gdb_byte *) cs.own_buf;
+ *buffer++ = 'b';
+
+ int out_len_units;
+ new_packet_len = remote_escape_output (mem_buf, res, 1,
+ buffer,
+ &out_len_units,
+ PBUFSIZ);
+ new_packet_len++; /* For the 'b' marker. */
+
+ if (out_len_units != res)
+ {
+ write_enn (cs.own_buf);
+ new_packet_len = -1;
+ }
+ else
+ suppress_next_putpkt_log ();
+ }
+ }
+ break;
case 'X':
require_running_or_break (cs.own_buf);
if (decode_X_packet (&cs.own_buf[1], packet_len - 1,