[rfc] Implementation of qXfer

Daniel Jacobowitz
2006-06-22T03:32:57Z

This is the implementation to go along with the packet I just proposed:
http://sourceware.org/ml/gdb/2006-06/msg00179.html

It doesn't actually cut down the number of packets; I broke that change into
the next patch, since it touches so many files. It does reduce the total
bytes necessary, since the data is now binary encoded instead of hex. Also
included in this patch are gdbserver support for the new packet and general
changes to support packets with embedded NUL characters, in both gdb and
gdbserver.

Eli, I had to do something mildly surprising with texinfo xrefs: you can
reference an anchor which contains colons, but you have to use at least a
two-argument form of @xref. If you use the one-argument form, the "info"
browser will choke trying to parse it. I wanted to keep the anchor named
after the packet description it was attached to. Do the docs look OK?
[I realize they may be a bit tricky to review; the qXfer docs are large,
and they replace the qPart docs but sit somewhere else in the alphabetical
list of packets. There's no rush on this patch, so take your time!]

Does anyone else have any comments on this patch? Otherwise, if there's no
changes to the new packet proposal, I'll commit this after the GCC Summit.
If there are I'll adjust and resubmit it later.

--
Daniel Jacobowitz
CodeSourcery

2006-06-21 Daniel Jacobowitz <dan@codesourcery.com>

* remote.c (PACKET_qXfer_auxv): New, renamed from PACKET_qPart_auxv.
(remote_supported_packet): Remove #if 0.
(remote_protocol_features): Add qPart:auxv:read.
(remote_escape_output, remote_unescape_input): New functions.
(remote_write_bytes): Use remote_escape_output.
(readchar): Don't mask off the high bit.
(read_frame): Use fputstrn_filtered for packet data.
(getpkt_sane): Return the number of bytes read or -1. Use
fputstrn_unfiltered.
(remote_read_qxfer): New.
(remote_xfer_partial): Use it for TARGET_OBJECT_AUXV.
(_initialize_remote): Update packet registration.
* defs.h (fputstrn_filtered): New prototype.
* utils.c (fputstrn_filtered): New.
* NEWS: Mention qXfer.

2006-06-21 Daniel Jacobowitz <dan@codesourcery.com>

* gdb.texinfo (OS Information): Update qPart reference to
qXfer.
(Remote configuration): Likewise.
(Overview): Move @cindex to the start of a paragraph. Talk
about binary data encoding.
(Packets): Refer to the overview for the details of the X
packet encoding.
(General Query Packets): Remove qPart description. Add qXfer
description. Add an anchor to qSupported. Correct feature
table title. Add a new feature for qXfer:auxv:read.
(Interrupts): Add a missing parenthesis.

2006-06-21 Daniel Jacobowitz <dan@codesourcery.com>

* remote-utils.c (remote_escape_output): New.
(putpkt_binary): Renamed from putpkt and adjusted for binary
data.
(putpkt): New wrapper for putpkt_binary.
(readchar): Don't mask off the high bit.
* server.c (decode_xfer_read, write_qxfer_response): New.
(handle_query): Take a packet length argument. Handle
qXfer:auxv:read instead of qPart:auxv:read. Mention it in
the qSupported response.
(main): Call putpkt_binary if a handler sets the packet length.
Save the length of the incoming packet.
* server.h (gdb_byte, remote_escape_output): New.

Index: src/gdb/remote.c
===================================================================
--- src.orig/gdb/remote.c 2006-06-21 17:08:38.000000000 -0400
+++ src/gdb/remote.c 2006-06-21 23:04:53.000000000 -0400
@@ -813,7 +813,7 @@ enum {
PACKET_Z2,
PACKET_Z3,
PACKET_Z4,
- PACKET_qPart_auxv,
+ PACKET_qXfer_auxv,
PACKET_qGetTLSAddr,
PACKET_qSupported,
PACKET_MAX
@@ -2106,7 +2106,6 @@ struct protocol_feature
int packet;
};

-#if 0
static void
remote_supported_packet (const struct protocol_feature *feature,
enum packet_support support,
@@ -2123,7 +2122,6 @@ remote_supported_packet (const struct pr
== PACKET_SUPPORT_UNKNOWN)
remote_protocol_packets[feature->packet].support = support;
}
-#endif

static void
remote_packet_size (const struct protocol_feature *feature,
@@ -2165,7 +2163,9 @@ remote_packet_size (const struct protoco
}

static struct protocol_feature remote_protocol_features[] = {
- { "PacketSize", PACKET_DISABLE, remote_packet_size, -1 }
+ { "PacketSize", PACKET_DISABLE, remote_packet_size, -1 },
+ { "qPart:auxv:read", PACKET_DISABLE, remote_supported_packet,
+ PACKET_qXfer_auxv }
};

static void
@@ -3689,6 +3689,87 @@ remote_address_masked (CORE_ADDR addr)
return addr;
}

+/* Convert BUFFER, binary data at least LEN bytes long, into escaped
+ binary data in OUT_BUF. Set *OUT_LEN to the length of the data
+ encoded in OUT_BUF, and return the number of bytes in OUT_BUF
+ (which may be more than *OUT_LEN due to escape characters). The
+ total number of bytes in the output buffer will be at most
+ OUT_MAXLEN. */
+
+static int
+remote_escape_output (const gdb_byte *buffer, int len,
+ gdb_byte *out_buf, int *out_len,
+ int out_maxlen)
+{
+ int input_index, output_index;
+
+ output_index = 0;
+ for (input_index = 0; input_index < len; input_index++)
+ {
+ gdb_byte b = buffer[input_index];
+
+ if (b == '$' || b == '#' || b == '}')
+ {
+ /* These must be escaped. */
+ if (output_index + 2 > out_maxlen)
+ break;
+ out_buf[output_index++] = '}';
+ out_buf[output_index++] = b ^ 0x20;
+ }
+ else
+ {
+ if (output_index + 1 > out_maxlen)
+ break;
+ out_buf[output_index++] = b;
+ }
+ }
+
+ *out_len = input_index;
+ return output_index;
+}
+
+/* Convert BUFFER, escaped data LEN bytes long, into binary data
+ in OUT_BUF. Return the number of bytes written to OUT_BUF.
+ Raise an error if the total number of bytes exceeds OUT_MAXLEN.
+
+ This function reverses remote_escape_output. It allows more
+ escaped characters than that function does, in particular because
+ '*' must be escaped to avoid the run-length encoding processing
+ in reading packets. */
+
+static int
+remote_unescape_input (const gdb_byte *buffer, int len,
+ gdb_byte *out_buf, int out_maxlen)
+{
+ int input_index, output_index;
+ int escaped;
+
+ output_index = 0;
+ escaped = 0;
+ for (input_index = 0; input_index < len; input_index++)
+ {
+ gdb_byte b = buffer[input_index];
+
+ if (output_index + 1 > out_maxlen)
+ error (_("Received too much data from the target."));
+
+ if (escaped)
+ {
+ out_buf[output_index++] = b ^ 0x20;
+ escaped = 0;
+ }
+ else if (b == '}')
+ escaped = 1;
+ else
+ out_buf[output_index++] = b;
+ }
+
+ if (escaped)
+ error (_("Unmatched escape character in target response."));
+
+ return output_index;
+}
+
/* Determine whether the remote target supports binary downloading.
This is accomplished by sending a no-op memory write of zero length
to the target at the specified address. It does not suffice to send
@@ -3839,24 +3920,7 @@ remote_write_bytes (CORE_ADDR memaddr, g
/* Binary mode. Send target system values byte by byte, in
increasing byte addresses. Only escape certain critical
characters. */
- for (nr_bytes = 0;
- (nr_bytes < todo) && (p - payload_start) < payload_size;
- nr_bytes++)
- {
- switch (myaddr[nr_bytes] & 0xff)
- {
- case '$':
- case '#':
- case 0x7d:
- /* These must be escaped. */
- *p++ = 0x7d;
- *p++ = (myaddr[nr_bytes] & 0xff) ^ 0x20;
- break;
- default:
- *p++ = myaddr[nr_bytes] & 0xff;
- break;
- }
- }
+ p += remote_escape_output (myaddr, todo, p, &nr_bytes, payload_size);
if (nr_bytes < todo)
{
/* Escape chars have filled up the buffer prematurely,
@@ -4018,8 +4082,7 @@ remote_files_info (struct target_ops *ig
/* Stuff for dealing with the packets which are part of this protocol.
See comment at top of file for details. */

-/* Read a single character from the remote end, masking it down to 7
- bits. */
+/* Read a single character from the remote end. */

static int
readchar (int timeout)
@@ -4029,7 +4092,7 @@ readchar (int timeout)
ch = serial_readchar (remote_desc, timeout);

if (ch >= 0)
- return (ch & 0x7f);
+ return ch;

switch ((enum serial_rc) ch)
{
@@ -4313,7 +4376,7 @@ read_frame (char **buf_p,
fprintf_filtered (gdb_stdlog,
"Bad checksum, sentsum=0x%x, csum=0x%x, buf=",
pktcsum, csum);
- fputs_filtered (buf, gdb_stdlog);
+ fputstrn_filtered (buf, bc, 0, gdb_stdlog);
fputs_filtered ("\n", gdb_stdlog);
}
/* Number of characters in buffer ignoring trailing
@@ -4392,7 +4455,8 @@ getpkt (char **buf,
rather than timing out; this is used (in synchronous mode) to wait
for a target that is is executing user code to stop. If FOREVER ==
0, this function is allowed to time out gracefully and return an
- indication of this to the caller. */
+ indication of this to the caller. Otherwise return the number
+ of bytes read. */
static int
getpkt_sane (char **buf, long *sizeof_buf, int forever)
{
@@ -4453,11 +4517,11 @@ getpkt_sane (char **buf, long *sizeof_bu
if (remote_debug)
{
fprintf_unfiltered (gdb_stdlog, "Packet received: ");
- fputstr_unfiltered (*buf, 0, gdb_stdlog);
+ fputstrn_unfiltered (*buf, val, 0, gdb_stdlog);
fprintf_unfiltered (gdb_stdlog, "\n");
}
serial_write (remote_desc, "+", 1);
- return 0;
+ return val;
}

/* Try the whole thing again. */
@@ -4470,7 +4534,7 @@ getpkt_sane (char **buf, long *sizeof_bu

printf_unfiltered (_("Ignoring packet error, continuing...\n"));
serial_write (remote_desc, "+", 1);
- return 1;
+ return -1;
}
\f
static void
@@ -5075,6 +5139,57 @@ the loaded file\n"));
printf_filtered (_("No loaded section named '%s'.\n"), args);
}

+/* Read OBJECT_NAME/ANNEX from the remote target using a qXfer packet.
+ Data at OFFSET, of up to LEN bytes, is read into READBUF; the
+ number of bytes read is returned, or 0 for EOF, or -1 for error.
+ The number of bytes read may be less than LEN without indicating an
+ EOF. PACKET is checked and updated to indicate whether the remote
+ target supports this object. */
+
+static LONGEST
+remote_read_qxfer (struct target_ops *ops, const char *object_name,
+ const char *annex,
+ gdb_byte *readbuf, ULONGEST offset, LONGEST len,
+ struct packet_config *packet)
+{
+ struct remote_state *rs = get_remote_state ();
+ unsigned int total = 0;
+ LONGEST i, n, packet_len;
+
+ if (packet->support == PACKET_DISABLE)
+ return -1;
+
+ n = min ((get_remote_packet_size () - 2) / 2, len);
+ snprintf (rs->buf, get_remote_packet_size (), "qXfer:%s:read:%s:%s,%s",
+ object_name, annex ? annex : "",
+ phex_nz (offset, sizeof offset),
+ phex_nz (n, sizeof n));
+ i = putpkt (rs->buf);
+ if (i < 0)
+ return -1;
+
+ rs->buf[0] = '\0';
+ packet_len = getpkt_sane (&rs->buf, &rs->buf_size, 0);
+ if (packet_len < 0 || packet_ok (rs->buf, packet) != PACKET_OK)
+ return -1;
+
+ /* 'l' is an EOF marker, possibly including data. Right now we don't
+ do anything with this, because the target_xfer_partial interface
+ doesn't have room for it. */
+ if (rs->buf[0] != 'm' && rs->buf[0] != 'l')
+ error (_("Unknown remote qXfer reply: %s"), rs->buf);
+
+ /* 'm' means there is (or at least might be) more data after this
+ batch. That does not make sense unless there's at least one byte
+ of data in this reply. */
+ if (rs->buf[0] == 'm' && packet_len == 1)
+ error (_("Remote qXfer reply contained no data."));
+
+ /* Got some data. */
+ i = remote_unescape_input (rs->buf + 1, packet_len - 1, readbuf, len);
+ return i;
+}
+
static LONGEST
remote_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
@@ -5126,27 +5241,9 @@ remote_xfer_partial (struct target_ops *
break;

case TARGET_OBJECT_AUXV:
- if (remote_protocol_packets[PACKET_qPart_auxv].support != PACKET_DISABLE)
- {
- LONGEST n = min ((get_remote_packet_size () - 2) / 2, len);
- snprintf (rs->buf, get_remote_packet_size (),
- "qPart:auxv:read::%s,%s",
- phex_nz (offset, sizeof offset),
- phex_nz (n, sizeof n));
- i = putpkt (rs->buf);
- if (i < 0)
- return i;
- rs->buf[0] = '\0';
- getpkt (&rs->buf, &rs->buf_size, 0);
- if (packet_ok (rs->buf, &remote_protocol_packets[PACKET_qPart_auxv])
- != PACKET_OK)
- return -1;
- if (strcmp (rs->buf, "OK") == 0)
- return 0; /* Got EOF indicator. */
- /* Got some data. */
- return hex2bin (rs->buf, readbuf, len);
- }
- return -1;
+ gdb_assert (annex == NULL);
+ return remote_read_qxfer (ops, "auxv", annex, readbuf, offset, len,
+ &remote_protocol_packets[PACKET_qXfer_auxv]);

default:
return -1;
@@ -5894,8 +5991,8 @@ Show the maximum size of the address (in
add_packet_config_cmd (&remote_protocol_packets[PACKET_Z4],
"Z4", "access-watchpoint", 0);

- add_packet_config_cmd (&remote_protocol_packets[PACKET_qPart_auxv],
- "qPart:auxv", "read-aux-vector", 0);
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_auxv],
+ "qXfer:auxv:read", "read-aux-vector", 0);

add_packet_config_cmd (&remote_protocol_packets[PACKET_qGetTLSAddr],
"qGetTLSAddr", "get-thread-local-storage-address",
Index: src/gdb/defs.h
===================================================================
--- src.orig/gdb/defs.h 2006-06-21 17:50:26.000000000 -0400
+++ src/gdb/defs.h 2006-06-21 17:50:35.000000000 -0400
@@ -510,6 +510,8 @@ extern void fputstr_filtered (const char

extern void fputstr_unfiltered (const char *str, int quotr, struct ui_file * stream);

+extern void fputstrn_filtered (const char *str, int n, int quotr, struct ui_file * stream);
+
extern void fputstrn_unfiltered (const char *str, int n, int quotr, struct ui_file * stream);

/* Display the host ADDR on STREAM formatted as ``0x%x''. */
Index: src/gdb/gdbserver/remote-utils.c
===================================================================
--- src.orig/gdb/gdbserver/remote-utils.c 2006-06-21 17:17:37.000000000 -0400
+++ src/gdb/gdbserver/remote-utils.c 2006-06-21 18:05:51.000000000 -0400
@@ -276,17 +276,56 @@ hexify (char *hex, const char *bin, int
return i;
}

+/* Convert BUFFER, binary data at least LEN bytes long, into escaped
+ binary data in OUT_BUF. Set *OUT_LEN to the length of the data
+ encoded in OUT_BUF, and return the number of bytes in OUT_BUF
+ (which may be more than *OUT_LEN due to escape characters). The
+ total number of bytes in the output buffer will be at most
+ OUT_MAXLEN. */
+
+int
+remote_escape_output (const gdb_byte *buffer, int len,
+ gdb_byte *out_buf, int *out_len,
+ int out_maxlen)
+{
+ int input_index, output_index;
+
+ output_index = 0;
+ for (input_index = 0; input_index < len; input_index++)
+ {
+ gdb_byte b = buffer[input_index];
+
+ if (b == '$' || b == '#' || b == '}' || b == '*')
+ {
+ /* These must be escaped. */
+ if (output_index + 2 > out_maxlen)
+ break;
+ out_buf[output_index++] = '}';
+ out_buf[output_index++] = b ^ 0x20;
+ }
+ else
+ {
+ if (output_index + 1 > out_maxlen)
+ break;
+ out_buf[output_index++] = b;
+ }
+ }
+
+ *out_len = input_index;
+ return output_index;
+}
+
/* Send a packet to the remote machine, with error checking.
- The data of the packet is in BUF. Returns >= 0 on success, -1 otherwise. */
+ The data of the packet is in BUF, and the length of the
+ packet is in CNT. Returns >= 0 on success, -1 otherwise. */

int
-putpkt (char *buf)
+putpkt_binary (char *buf, int cnt)
{
int i;
unsigned char csum = 0;
char *buf2;
char buf3[1];
- int cnt = strlen (buf);
char *p;

buf2 = malloc (PBUFSIZ);
@@ -353,6 +392,17 @@ putpkt (char *buf)
return 1; /* Success! */
}

+/* Send a packet to the remote machine, with error checking. The data
+ of the packet is in BUF, and the packet should be a NUL-terminated
+ string. Returns >= 0 on success, -1 otherwise. */
+
+int
+putpkt (char *buf)
+{
+ return putpkt_binary (buf, strlen (buf));
+}
+
+
/* Come here when we get an input interrupt from the remote side. This
interrupt should only be active while we are waiting for the child to do
something. About the only thing that should come through is a ^C, which
@@ -439,12 +489,12 @@ disable_async_io (void)
static int
readchar (void)
{
- static char buf[BUFSIZ];
+ static unsigned char buf[BUFSIZ];
static int bufcnt = 0;
- static char *bufp;
+ static unsigned char *bufp;

if (bufcnt-- > 0)
- return *bufp++ & 0x7f;
+ return *bufp++;

bufcnt = read (remote_desc, buf, sizeof (buf));

Index: src/gdb/gdbserver/server.c
===================================================================
--- src.orig/gdb/gdbserver/server.c 2006-06-21 17:15:03.000000000 -0400
+++ src/gdb/gdbserver/server.c 2006-06-21 19:19:58.000000000 -0400
@@ -91,9 +91,48 @@ attach_inferior (int pid, char *statuspt

extern int remote_debug;

+/* Decode a qXfer read request. Return 0 if everything looks OK,
+ or -1 otherwise. */
+
+static int
+decode_xfer_read (char *buf, char **annex, CORE_ADDR *ofs, unsigned int *len)
+{
+ /* Extract and NUL-terminate the annex. */
+ *annex = buf;
+ while (*buf && *buf != ':')
+ buf++;
+ if (*buf == '\0')
+ return -1;
+ *buf++ = 0;
+
+ /* After the read/write marker and annex, qXfer looks like a
+ traditional 'm' packet. */
+ decode_m_packet (buf, ofs, len);
+
+ return 0;
+}
+
+/* Write the response to a successful qXfer read. Returns the
+ length of the (binary) data stored in BUF, corresponding
+ to as much of DATA/LEN as we could fit. IS_MORE controls
+ the first character of the response. */
+static int
+write_qxfer_response (char *buf, unsigned char *data, int len, int is_more)
+{
+ int out_len;
+
+ if (is_more)
+ buf[0] = 'm';
+ else
+ buf[0] = 'l';
+
+ return remote_escape_output (data, len, (unsigned char *) buf + 1, &out_len,
+ PBUFSIZ - 2) + 1;
+}
+
/* Handle all of the extended 'q' packets. */
void
-handle_query (char *own_buf)
+handle_query (char *own_buf, int *new_packet_len_p)
{
static struct inferior_list_entry *thread_ptr;

@@ -144,22 +183,32 @@ handle_query (char *own_buf)
}

if (the_target->read_auxv != NULL
- && strncmp ("qPart:auxv:read::", own_buf, 17) == 0)
+ && strncmp ("qXfer:auxv:read:", own_buf, 16) == 0)
{
- unsigned char data[(PBUFSIZ - 1) / 2];
+ unsigned char *data;
+ int n;
CORE_ADDR ofs;
unsigned int len;
- int n;
- decode_m_packet (&own_buf[17], &ofs, &len); /* "OFS,LEN" */
- if (len > sizeof data)
- len = sizeof data;
- n = (*the_target->read_auxv) (ofs, data, len);
- if (n == 0)
- write_ok (own_buf);
- else if (n < 0)
- write_enn (own_buf);
- else
- convert_int_to_ascii (data, own_buf, n);
+ char *annex;
+
+ /* Reject any annex; grab the offset and length. */
+ if (decode_xfer_read (own_buf + 16, &annex, &ofs, &len) < 0
+ || annex[0] != '\0')
+ {
+ strcpy (own_buf, "E00");
+ return;
+ }
+
+ /* Read one extra byte, as an indicator of whether there is
+ more. */
+ if (len > PBUFSIZ - 2)
+ len = PBUFSIZ - 2;
+ data = malloc (len + 1);
+ n = (*the_target->read_auxv) (ofs, data, len + 1);
+ *new_packet_len_p = write_qxfer_response (own_buf, data, n, n > len);
+
+ free (data);
+
return;
}

@@ -168,6 +217,10 @@ handle_query (char *own_buf)
&& (own_buf[10] == ':' || own_buf[10] == '\0'))
{
sprintf (own_buf, "PacketSize=%x", PBUFSIZ - 1);
+
+ if (the_target->read_auxv != NULL)
+ strcat (own_buf, ";qPart:auxv:read+");
+
return;
}

@@ -440,15 +493,22 @@ main (int argc, char *argv[])

restart:
setjmp (toplevel);
- while (getpkt (own_buf) > 0)
+ while (1)
{
unsigned char sig;
+ int packet_len;
+ int new_packet_len = -1;
+
+ packet_len = getpkt (own_buf);
+ if (packet_len <= 0)
+ break;
+
i = 0;
ch = own_buf[i++];
switch (ch)
{
case 'q':
- handle_query (own_buf);
+ handle_query (own_buf, &new_packet_len);
break;
case 'd':
remote_debug = !remote_debug;
@@ -714,7 +774,10 @@ main (int argc, char *argv[])
break;
}

- putpkt (own_buf);
+ if (new_packet_len != -1)
+ putpkt_binary (own_buf, new_packet_len);
+ else
+ putpkt (own_buf);

if (status == 'W')
fprintf (stderr,
Index: src/gdb/gdbserver/server.h
===================================================================
--- src.orig/gdb/gdbserver/server.h 2006-06-21 17:27:58.000000000 -0400
+++ src/gdb/gdbserver/server.h 2006-06-21 17:54:42.000000000 -0400
@@ -57,6 +57,9 @@ extern char *strerror (int); /* X3.159-1
#endif
#endif

+/* A type used for binary buffers. */
+typedef unsigned char gdb_byte;
+
/* FIXME: This should probably be autoconf'd for. It's an integer type at
least the size of a (void *). */
typedef long long CORE_ADDR;
@@ -133,6 +136,7 @@ extern jmp_buf toplevel;
extern int all_symbols_looked_up;

int putpkt (char *buf);
+int putpkt_binary (char *buf, int len);
int getpkt (char *buf);
void remote_open (char *name);
void remote_close (void);
@@ -155,6 +159,9 @@ void decode_M_packet (char *from, CORE_A

int unhexify (char *bin, const char *hex, int count);
int hexify (char *hex, const char *bin, int count);
+int remote_escape_output (const gdb_byte *buffer, int len,
+ gdb_byte *out_buf, int *out_len,
+ int out_maxlen);

int look_up_one_symbol (const char *name, CORE_ADDR *addrp);

Index: src/gdb/utils.c
===================================================================
--- src.orig/gdb/utils.c 2006-06-21 17:50:49.000000000 -0400
+++ src/gdb/utils.c 2006-06-21 17:51:08.000000000 -0400
@@ -1544,6 +1544,15 @@ fputstr_unfiltered (const char *str, int
}

void
+fputstrn_filtered (const char *str, int n, int quoter,
+ struct ui_file *stream)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ printchar (str[i], fputs_filtered, fprintf_filtered, stream, quoter);
+}
+
+void
fputstrn_unfiltered (const char *str, int n, int quoter,
struct ui_file *stream)
{
Index: src/gdb/doc/gdb.texinfo
===================================================================
--- src.orig/gdb/doc/gdb.texinfo 2006-06-21 18:42:38.000000000 -0400
+++ src/gdb/doc/gdb.texinfo 2006-06-21 22:18:42.000000000 -0400
@@ -6597,7 +6597,7 @@ identified by an integer tag; the meanin
Depending on the configuration and operating system facilities,
@value{GDBN} may be able to show you this information. For remote
targets, this functionality may further depend on the remote stub's
-support of the @samp{qPart:auxv:read} packet, see @ref{Remote
+support of the @samp{qXfer:auxv:read} packet, see @ref{Remote
configuration, auxiliary vector}.

@table @code
@@ -12702,16 +12702,16 @@ downloads.
@item set remote read-aux-vector-packet
@cindex auxiliary vector of remote target
@cindex @code{auxv}, and remote targets
-Set the use of the remote protocol's @samp{qPart:auxv:read} (target
-auxiliary vector read) request. This request is used to fetch the
+Set the use of the remote protocol's @samp{qXfer:auxv:read} (target
+auxiliary vector) request. This request is used to fetch the
remote target's @dfn{auxiliary vector}, see @ref{OS Information,
Auxiliary Vector}. The default setting depends on the remote stub's
support of this request (@value{GDBN} queries the stub when this
-request is first required). @xref{General Query Packets, qPart}, for
+request is first required). @xref{General Query Packets, qXfer}, for
more information about this request.

@item show remote read-aux-vector-packet
-Show the current setting of use of the @samp{qPart:auxv:read} request.
+Show the current setting of use of the @samp{qXfer:auxv:read} request.

@item set remote symbol-lookup-packet
@cindex remote symbol lookup request
@@ -22708,8 +22708,8 @@ when the operation has completed (the ta
exception of @samp{#} and @samp{$} (see @samp{X} packet for additional
exceptions).

-Fields within the packet should be separated using @samp{,} @samp{;} or
@cindex remote protocol, field separator
+Fields within the packet should be separated using @samp{,} @samp{;} or
@samp{:}. Except where otherwise noted all numbers are represented in
@sc{hex} with leading zeros suppressed.

@@ -22717,6 +22717,26 @@ Implementors should note that prior to @
@samp{:} could not appear as the third character in a packet (as it
would potentially conflict with the @var{sequence-id}).

+@cindex remote protocol, binary data
+@anchor{Binary Data}
+Binary data in most packets is encoded either as two hexadecimal
+digits per byte of binary data. This allowed the traditional remote
+protocol to work over connections which were only seven-bit clean.
+Some packets designed more recently assume an eight-bit clean
+connection, and use a more efficient encoding to send and receive
+binary data.
+
+The binary data representation uses @code{7d} (@sc{ascii} @samp{@}})
+as an escape character. Any escaped byte is transmitted as the escape
+character followed by the original character XORed with @code{0x20}.
+For example, the byte @code{0x7d} would be transmitted as the two
+bytes @code{0x7d 0x5d}. The bytes @code{0x23} (@sc{ascii} @samp{#}),
+@code{0x24} (@sc{ascii} @samp{$}), and @code{0x7d} (@sc{ascii}
+@samp{@}}) must always be escaped. Responses sent by the stub
+must also escape @code{0x2a} (@sc{ascii} @samp{*}), so that it
+is not interpreted as the start of a run-length encoded sequence
+(described next).
+
Response @var{data} can be run-length encoded to save space. A @samp{*}
means that the next character is an @sc{ascii} encoding giving a repeat count
which stands for that many repetitions of the character preceding the
@@ -23125,12 +23145,7 @@ The @samp{vCont} packet is not supported
@cindex @samp{X} packet
Write data to memory, where the data is transmitted in binary.
@var{addr} is address, @var{length} is number of bytes,
-@samp{@var{XX}@dots{}} is binary data. The bytes @code{0x23}
-(@sc{ascii} @samp{#}), @code{0x24} (@sc{ascii} @samp{$}), and
-@code{0x7d} (@sc{ascii} @samp{@}}) are escaped using @code{0x7d}
-(@sc{ascii} @samp{@}}), and then XORed with @code{0x20}. For example,
-the byte @code{0x7d} would be transmitted as the two bytes @code{0x7d
-0x5d}.
+@samp{@var{XX}@dots{}} is binary data (@pxref{Binary Data}).

Reply:
@table @samp
@@ -23526,87 +23541,6 @@ Don't use this packet; use the @samp{qTh

Reply: see @code{remote.c:remote_unpack_thread_info_response()}.

-@item qPart:@var{object}:read:@var{annex}:@var{offset},@var{length}
-@cindex read special object, remote request
-@cindex @samp{qPart} packet
-Read uninterpreted bytes from the target's special data area
-identified by the keyword @var{object}. Request @var{length} bytes
-starting at @var{offset} bytes into the data. The content and
-encoding of @var{annex} is specific to the object; it can supply
-additional details about what data to access.
-
-Since this packet is ambiguous with the older @code{qP} packet, we
-plan to rename it.
-
-Here are the specific requests of this form defined so far. All
-@samp{qPart:@var{object}:read:@dots{}} requests use the same reply
-formats, listed below.
-
-@table @samp
-@item qPart:auxv:read::@var{offset},@var{length}
-Access the target's @dfn{auxiliary vector}. @xref{OS Information,
-auxiliary vector}, and see @ref{Remote configuration,
-read-aux-vector-packet}. Note @var{annex} must be empty.
-@end table
-
-Reply:
-@table @samp
-@item OK
-The @var{offset} in the request is at the end of the data.
-There is no more data to be read.
-
-@item @var{XX}@dots{}
-Hex encoded data bytes read.
-This may be fewer bytes than the @var{length} in the request.
-
-@item E00
-The request was malformed, or @var{annex} was invalid.
-
-@item E @var{nn}
-The offset was invalid, or there was an error encountered reading the data.
-@var{nn} is a hex-encoded @code{errno} value.
-
-@item
-An empty reply indicates the @var{object} or @var{annex} string was not
-recognized by the stub.
-@end table
-
-@item qPart:@var{object}:write:@var{annex}:@var{offset}:@var{data}@dots{}
-@cindex write data into object, remote request
-Write uninterpreted bytes into the target's special data area
-identified by the keyword @var{object}, starting at @var{offset} bytes
-into the data. @samp{@var{data}@dots{}} is the hex-encoded data to be
-written. The content and encoding of @var{annex} is specific to the
-object; it can supply additional details about what data to access.
-
-No requests of this form are presently in use. This specification
-serves as a placeholder to document the common format that new
-specific request specifications ought to use.
-
-Reply:
-@table @samp
-@item @var{nn}
-@var{nn} (hex encoded) is the number of bytes written.
-This may be fewer bytes than supplied in the request.
-
-@item E00
-The request was malformed, or @var{annex} was invalid.
-
-@item E @var{nn}
-The offset was invalid, or there was an error encountered writing the data.
-@var{nn} is a hex-encoded @code{errno} value.
-
-@item
-An empty reply indicates the @var{object} or @var{annex} string was not
-recognized by the stub, or that the object does not support writing.
-@end table
-
-@item qPart:@var{object}:@var{operation}:@dots{}
-Requests of this form may be added in the future. When a stub does
-not recognize the @var{object} keyword, or its support for
-@var{object} does not recognize the @var{operation} keyword, the stub
-must respond with an empty packet.
-
@item qRcmd,@var{command}
@cindex execute remote command, remote request
@cindex @samp{qRcmd} packet
@@ -23638,6 +23572,7 @@ packets.)
@cindex supported packets, remote query
@cindex features of the remote protocol
@cindex @samp{qSupported} packet
+@anchor{qSupported}
Tell the remote stub about features supported by @value{GDBN}, and
query the stub for features it supports. This packet allows
@value{GDBN} and the remote stub to take advantage of each others'
@@ -23729,7 +23664,7 @@ These are the currently defined stub fea
@multitable @columnfractions 0.25 0.2 0.2 0.2
@c NOTE: The first row should be @headitem, but we do not yet require
@c a new enough version of Texinfo (4.7) to use @headitem.
-@item Packet Name
+@item Feature Name
@tab Value Required
@tab Default
@tab Probe Allowed
@@ -23739,6 +23674,11 @@ These are the currently defined stub fea
@tab @samp{-}
@tab No

+@item @samp{qXfer:auxv:read}
+@tab No
+@tab @samp{-}
+@tab Yes
+
@end multitable

These are the currently defined stub features, in more detail:
@@ -23755,6 +23695,10 @@ stores packets in a NUL-terminated forma
byte in its buffer for the NUL. If this stub feature is not supported,
@value{GDBN} guesses based on the size of the @samp{g} packet response.

+@item qXfer:auxv:read
+The remote stub understands the @samp{qXfer:auxv:read} packet
+(@pxref{qXfer:auxv:read,Auxiliary Vector Read}).
+
@end table

@item qSymbol::
@@ -23829,6 +23773,98 @@ packets.)
@itemx qTStatus
@xref{Tracepoint Packets}.

+@item qXfer:@var{object}:read:@var{annex}:@var{offset},@var{length}
+@cindex read special object, remote request
+@cindex @samp{qXfer} packet
+Read uninterpreted bytes from the target's special data area
+identified by the keyword @var{object}. Request @var{length} bytes
+starting at @var{offset} bytes into the data. The content and
+encoding of @var{annex} is specific to the object; it can supply
+additional details about what data to access.
+
+Here are the specific requests of this form defined so far. All
+@samp{qXfer:@var{object}:read:@dots{}} requests use the same reply
+formats, listed below.
+
+@table @samp
+@item qXfer:auxv:read::@var{offset},@var{length}
+@anchor{qXfer:auxv:read}
+Access the target's @dfn{auxiliary vector}. @xref{OS Information,
+auxiliary vector}, and see @ref{Remote configuration,
+read-aux-vector-packet}. Note @var{annex} must be empty.
+
+This packet is not probed by default; the remote stub must request it,
+by suppling an appropriate @samp{qSupported} response (@pxref{qSupported}).
+@end table
+
+Reply:
+@table @samp
+@item m @var{data}
+Data @var{data} (@pxref{Binary Data} has been read from the
+target. There may be more data at a higher address (although
+it is permitted to return @samp{m} even for the last valid
+block of data, as long as at least one byte of data was read).
+@var{data} may have fewer bytes than the @var{length} in the
+request.
+
+@item l @var{data}
+Data @var{data} (@pxref{Binary Data} has been read from the target.
+There is no more data to be read. @var{data} may have fewer bytes
+than the @var{length} in the request.
+
+@item l
+The @var{offset} in the request is at the end of the data.
+There is no more data to be read.
+
+@item E00
+The request was malformed, or @var{annex} was invalid.
+
+@item E @var{nn}
+The offset was invalid, or there was an error encountered reading the data.
+@var{nn} is a hex-encoded @code{errno} value.
+
+@item
+An empty reply indicates the @var{object} string was not recognized by
+the stub, or that the object does not support reading.
+@end table
+
+@item qXfer:@var{object}:write:@var{annex}:@var{offset}:@var{data}@dots{}
+@cindex write data into object, remote request
+Write uninterpreted bytes into the target's special data area
+identified by the keyword @var{object}, starting at @var{offset} bytes
+into the data. @samp{@var{data}@dots{}} is the binary-encoded data
+(@pxref{Binary Data}) to be written. The content and encoding of @var{annex}
+is specific to the object; it can supply additional details about what data
+to access.
+
+No requests of this form are presently in use. This specification
+serves as a placeholder to document the common format that new
+specific request specifications ought to use.
+
+Reply:
+@table @samp
+@item @var{nn}
+@var{nn} (hex encoded) is the number of bytes written.
+This may be fewer bytes than supplied in the request.
+
+@item E00
+The request was malformed, or @var{annex} was invalid.
+
+@item E @var{nn}
+The offset was invalid, or there was an error encountered writing the data.
+@var{nn} is a hex-encoded @code{errno} value.
+
+@item
+An empty reply indicates the @var{object} string was not
+recognized by the stub, or that the object does not support writing.
+@end table
+
+@item qXfer:@var{object}:@var{operation}:@dots{}
+Requests of this form may be added in the future. When a stub does
+not recognize the @var{object} keyword, or its support for
+@var{object} does not recognize the @var{operation} keyword, the stub
+must respond with an empty packet.
+
@end table

@node Register Packet Format
@@ -24043,7 +24079,7 @@ transport mechanisms. It is represented
the Overview section (@pxref{Overview}). When a @code{0x03} byte is
transmitted as part of a packet, it is considered to be packet data
and does @emph{not} represent an interrupt. E.g., an @samp{X} packet
-(@pxref{X packet}, used for binary downloads, may include an unescaped
+(@pxref{X packet}), used for binary downloads, may include an unescaped
@code{0x03} as part of its packet.

Stubs are not required to recognize these interrupt mechanisms and the
Index: src/gdb/NEWS
===================================================================
--- src.orig/gdb/NEWS 2006-06-21 23:04:58.000000000 -0400
+++ src/gdb/NEWS 2006-06-21 23:06:47.000000000 -0400
@@ -16,6 +16,16 @@ qSupported:
packets required and improve performance when connected to a remote
target.

+qXfer:auxv:read:
+ Fetch an OS auxilliary vector from the remote stub. This packet is a
+ more efficient replacement for qPart:auxv:read.
+
+* Removed remote packets
+
+qPart:auxv:read:
+ This packet has been replaced by qXfer:auxv:read. Only GDB 6.4 and 6.5
+ used it, and only gdbserver implemented it.
+
*** Changes in GDB 6.5

* New targets