From: Daniel Jacobowitz Date: Wed, 12 Jul 2006 18:50:18 +0000 (+0000) Subject: gdb/ X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=0876f84a6a8150efc48e1a6658531994906acea2;p=binutils-gdb.git 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. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index c1445bc6178..2140b8876ff 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,20 @@ +2006-07-12 Daniel Jacobowitz + + * 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. + 2006-07-12 Daniel Jacobowitz * target.c (target_read): Stop if target_read_partial returns 0 diff --git a/gdb/NEWS b/gdb/NEWS index 404b0fd5ac6..984585ef684 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -19,6 +19,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 diff --git a/gdb/defs.h b/gdb/defs.h index d472f8de5aa..aab91c2bf0c 100644 --- a/gdb/defs.h +++ b/gdb/defs.h @@ -510,6 +510,8 @@ extern void fputstr_filtered (const char *str, int quotr, struct ui_file * strea 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''. */ diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index fccf6ccdf28..5d8a02a8243 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,17 @@ +2006-07-12 Daniel Jacobowitz + + * 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-07-05 Daniel Jacobowitz * doc/gdb.texinfo (KOD): Remove node. diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index c5669711d1e..a16e4d017fb 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -6597,7 +6597,7 @@ identified by an integer tag; the meanings are well-known but system-specific. 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 @@ -12655,16 +12655,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 @@ -22563,8 +22563,8 @@ when the operation has completed (the target has again stopped). 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. @@ -22572,6 +22572,26 @@ Implementors should note that prior to @value{GDBN} 5.0, the character @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 @@ -22980,12 +23000,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 @@ -23381,87 +23396,6 @@ Don't use this packet; use the @samp{qThreadExtraInfo} query instead 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 @@ -23493,6 +23427,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' @@ -23584,7 +23519,7 @@ These are the currently defined stub features and their properties: @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 @@ -23594,6 +23529,11 @@ These are the currently defined stub features and their properties: @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: @@ -23610,6 +23550,10 @@ stores packets in a NUL-terminated format, it should allow an extra 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 auxiliary vector read}). + @end table @item qSymbol:: @@ -23684,6 +23628,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 auxiliary vector read} +Access the target's @dfn{auxiliary vector}. @xref{OS Information, +auxiliary vector}, and @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 @@ -23898,7 +23934,7 @@ transport mechanisms. It is represented by sending the single byte 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 diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index 5758995ef6c..d9b7672b762 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,11 @@ +2006-07-12 Daniel Jacobowitz + + * 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. + 2006-06-22 Daniel Jacobowitz * remote-utils.c (remote_escape_output, remote_unescape_input): New. diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c index f8803d6555a..4b8120a1d84 100644 --- a/gdb/gdbserver/server.c +++ b/gdb/gdbserver/server.c @@ -91,9 +91,48 @@ attach_inferior (int pid, char *statusptr, int *sigptr) 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,35 @@ 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); + 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); + if (n > len) + *new_packet_len_p = write_qxfer_response (own_buf, data, len, 1); else - convert_int_to_ascii (data, own_buf, n); + *new_packet_len_p = write_qxfer_response (own_buf, data, n, 0); + + free (data); + return; } @@ -168,6 +220,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; } @@ -455,7 +511,7 @@ main (int argc, char *argv[]) switch (ch) { case 'q': - handle_query (own_buf); + handle_query (own_buf, &new_packet_len); break; case 'd': remote_debug = !remote_debug; diff --git a/gdb/remote.c b/gdb/remote.c index eef8bf2f5f4..6e1a8fa2996 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", diff --git a/gdb/utils.c b/gdb/utils.c index 00a060b2c57..6c4afb7daac 100644 --- a/gdb/utils.c +++ b/gdb/utils.c @@ -1543,6 +1543,15 @@ fputstr_unfiltered (const char *str, int quoter, struct ui_file *stream) printchar (*str++, fputs_unfiltered, fprintf_unfiltered, stream, quoter); } +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)