aboutsummaryrefslogtreecommitdiff
path: root/gdb/remote.c
diff options
context:
space:
mode:
authorDaniel Jacobowitz <drow@false.org>2006-07-12 18:50:18 +0000
committerDaniel Jacobowitz <drow@false.org>2006-07-12 18:50:18 +0000
commit0876f84a6a8150efc48e1a6658531994906acea2 (patch)
treea4bd8e1fcc052f1159ce803f241a579254ad18c1 /gdb/remote.c
parent13547ab600a0929b12f354dc144f1aef37938f30 (diff)
downloadgdb-0876f84a6a8150efc48e1a6658531994906acea2.zip
gdb-0876f84a6a8150efc48e1a6658531994906acea2.tar.gz
gdb-0876f84a6a8150efc48e1a6658531994906acea2.tar.bz2
gdb/
* 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_unescape_input): New function. (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. gdb/doc/ * 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. gdb/gdbserver/ * 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): Update call to handle_query.
Diffstat (limited to 'gdb/remote.c')
-rw-r--r--gdb/remote.c182
1 files changed, 147 insertions, 35 deletions
diff --git a/gdb/remote.c b/gdb/remote.c
index eef8bf2..6e1a8fa 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -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 protocol_feature *feature,
== 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 protocol_feature *feature,
}
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
@@ -3728,6 +3728,52 @@ remote_escape_output (const gdb_byte *buffer, int len,
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)
+ {
+ warning (_("Received too much data from remote target;"
+ " ignoring overflow."));
+ return output_index;
+ }
+
+ 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
@@ -4040,8 +4086,7 @@ remote_files_info (struct target_ops *ignore)
/* 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)
@@ -4051,7 +4096,7 @@ readchar (int timeout)
ch = serial_readchar (remote_desc, timeout);
if (ch >= 0)
- return (ch & 0x7f);
+ return ch;
switch ((enum serial_rc) ch)
{
@@ -4335,7 +4380,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
@@ -4414,7 +4459,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)
{
@@ -4475,11 +4521,11 @@ getpkt_sane (char **buf, long *sizeof_buf, int forever)
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. */
@@ -4492,7 +4538,7 @@ getpkt_sane (char **buf, long *sizeof_buf, int forever)
printf_unfiltered (_("Ignoring packet error, continuing...\n"));
serial_write (remote_desc, "+", 1);
- return 1;
+ return -1;
}
static void
@@ -5097,6 +5143,90 @@ 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)
+{
+ static char *finished_object;
+ static char *finished_annex;
+ static ULONGEST finished_offset;
+
+ struct remote_state *rs = get_remote_state ();
+ unsigned int total = 0;
+ LONGEST i, n, packet_len;
+
+ if (packet->support == PACKET_DISABLE)
+ return -1;
+
+ /* Check whether we've cached an end-of-object packet that matches
+ this request. */
+ if (finished_object)
+ {
+ if (strcmp (object_name, finished_object) == 0
+ && strcmp (annex ? annex : "", finished_annex) == 0
+ && offset == finished_offset)
+ return 0;
+
+ /* Otherwise, we're now reading something different. Discard
+ the cache. */
+ xfree (finished_object);
+ xfree (finished_annex);
+ finished_object = NULL;
+ finished_annex = NULL;
+ }
+
+ /* Request only enough to fit in a single packet. The actual data
+ may not, since we don't know how much of it will need to be escaped;
+ the target is free to respond with slightly less data. We subtract
+ five to account for the response type and the protocol frame. */
+ n = min (get_remote_packet_size () - 5, len);
+ snprintf (rs->buf, 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));
+ 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;
+
+ if (rs->buf[0] != 'l' && rs->buf[0] != 'm')
+ 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, n);
+
+ /* 'l' is an EOF marker, possibly including a final block of data,
+ or possibly empty. Record it to bypass the next read, if one is
+ issued. */
+ if (rs->buf[0] == 'l')
+ {
+ finished_object = xstrdup (object_name);
+ finished_annex = xstrdup (annex ? annex : "");
+ finished_offset = offset + i;
+ }
+
+ return i;
+}
+
static LONGEST
remote_xfer_partial (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
@@ -5145,27 +5275,9 @@ remote_xfer_partial (struct target_ops *ops, enum target_object object,
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;
@@ -5913,8 +6025,8 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
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",