diff options
author | Daniel Jacobowitz <drow@false.org> | 2006-07-12 18:50:18 +0000 |
---|---|---|
committer | Daniel Jacobowitz <drow@false.org> | 2006-07-12 18:50:18 +0000 |
commit | 0876f84a6a8150efc48e1a6658531994906acea2 (patch) | |
tree | a4bd8e1fcc052f1159ce803f241a579254ad18c1 /gdb/remote.c | |
parent | 13547ab600a0929b12f354dc144f1aef37938f30 (diff) | |
download | gdb-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.c | 182 |
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", |