From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 6633 invoked by alias); 2 Jun 2007 19:33:38 -0000 Received: (qmail 6623 invoked by uid 22791); 2 Jun 2007 19:33:36 -0000 X-Spam-Check-By: sourceware.org Received: from mtagate5.de.ibm.com (HELO mtagate5.de.ibm.com) (195.212.29.154) by sourceware.org (qpsmtpd/0.31) with ESMTP; Sat, 02 Jun 2007 19:33:33 +0000 Received: from d12nrmr1607.megacenter.de.ibm.com (d12nrmr1607.megacenter.de.ibm.com [9.149.167.49]) by mtagate5.de.ibm.com (8.13.8/8.13.8) with ESMTP id l52JXUBL442088 for ; Sat, 2 Jun 2007 19:33:30 GMT Received: from d12av02.megacenter.de.ibm.com (d12av02.megacenter.de.ibm.com [9.149.165.228]) by d12nrmr1607.megacenter.de.ibm.com (8.13.8/8.13.8/NCO v8.3) with ESMTP id l52JXUfO4096206 for ; Sat, 2 Jun 2007 21:33:30 +0200 Received: from d12av02.megacenter.de.ibm.com (loopback [127.0.0.1]) by d12av02.megacenter.de.ibm.com (8.12.11.20060308/8.13.3) with ESMTP id l52JXT8B005554 for ; Sat, 2 Jun 2007 21:33:29 +0200 Received: from tuxmaker.boeblingen.de.ibm.com (tuxmaker.boeblingen.de.ibm.com [9.152.85.9]) by d12av02.megacenter.de.ibm.com (8.12.11.20060308/8.12.11) with SMTP id l52JXTJX005551; Sat, 2 Jun 2007 21:33:29 +0200 Message-Id: <200706021933.l52JXTJX005551@d12av02.megacenter.de.ibm.com> Received: by tuxmaker.boeblingen.de.ibm.com (sSMTP sendmail emulation); Sat, 2 Jun 2007 21:33:29 +0200 Subject: [rfc/rfa] [3/4] SPU enhancements: gdbserver support To: gdb-patches@sourceware.org Date: Sat, 02 Jun 2007 19:33:00 -0000 From: "Ulrich Weigand" Cc: eliz@gnu.org, drow@false.org X-Mailer: ELM [version 2.5 PL2] MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2007-06/txt/msg00019.txt.bz2 Hello, this patch, implemented by Markus Deuling, extends TARGET_OBJECT_SPU support to remote gdbserver debugging. This is done by extended the remote protocol by two new packet types, qXfer:spu:read and qXfer:spu:write. In addition, the patch contains the following changes to remote packet support: - It adds a "length" argument to qXfer::write type packets. This is to make parsing of the packet easier, and to bring it in line with the 'X' packet format. (It also provides a bit of extra redundancy to detect transmission problems.) - The remote_read_qxfer attempts to cache received end-of-object packets. However, this is a problem for some spufs objects as they can start out with no content (length zero), and acquire actual content later on. If remote_read_qxfer has already cache an end-of-object at lenght zero, future re-reads of the object will always return zero even if the object by now has actual content. To fix this we've added a CACHEABLE flag to the function and use it to disable the cache for spufs objects. Tested on spu-elf. Eli, are the doc changes OK? OK to apply? Bye, Ulrich ChangeLog: * remote.c (remote_write_qxfer): New function. (remote_xfer_partial): Add handling for TARGET_OBJECT_SPU. (remote_read_qxfer): Add cacheable flag. (_initialize_remote): Add PACKET_qXfer_spu_read and PACKET_qXfer_spu_write. doc/ChangeLog: * gdb.texinfo (General Query Packets): Add length to description of qXfer::write packet format. Document qXfer:spu:read and qXfer:spu:write packets and mention them under qSupported. gdbserver/ChangeLog: * server.c (decode_xfer_write): New function. (handle_query): Add support for qXfer:spu:read/write packets. * spu-low.c (spu_target_ops): Add spu_proc_xfer_spu. * target.h (target_ops): Add qxfer_spu. diff -urNp gdb-orig/gdb/doc/gdb.texinfo gdb-head/gdb/doc/gdb.texinfo --- gdb-orig/gdb/doc/gdb.texinfo 2007-05-31 18:54:31.000000000 +0200 +++ gdb-head/gdb/doc/gdb.texinfo 2007-06-02 19:32:26.068097686 +0200 @@ -23590,6 +23590,16 @@ These are the currently defined stub fea @tab @samp{-} @tab Yes +@item @samp{qXfer:spu:read} +@tab No +@tab @samp{-} +@tab Yes + +@item @samp{qXfer:spu:write} +@tab No +@tab @samp{-} +@tab Yes + @item @samp{QPassSignals} @tab No @tab @samp{-} @@ -23623,6 +23633,14 @@ The remote stub understands the @samp{qX The remote stub understands the @samp{qXfer:memory-map:read} packet (@pxref{qXfer memory map read}). +@item qXfer:spu:read +The remote stub understands the @samp{qXfer:spu:read} packet +(@pxref{qXfer spu read}). + +@item qXfer:spu:write +The remote stub understands the @samp{qXfer:spu:write} packet +(@pxref{qXfer spu write}). + @item QPassSignals The remote stub understands the @samp{QPassSignals} packet (@pxref{QPassSignals}). @@ -23724,6 +23742,19 @@ auxiliary vector}. Note @var{annex} mus This packet is not probed by default; the remote stub must request it, by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}). +@item qXfer:spu:read:@var{annex}:@var{offset},@var{length} +@anchor{qXfer spu read} +@cindex spufs +@cindex SPU +Read contents of an @code{spufs} file on the target system. The +annex specifies which file to read; it must be of the form +@var{id}/@var{name}, where @var{id} specifies an SPU context ID +in the target process, and @var{name} identifes the @code{spufs} file +in that context to be accessed. + +This packet is not probed by default; the remote stub must request it, +by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}). + @item qXfer:features:read:@var{annex}:@var{offset},@var{length} @anchor{qXfer target description read} Access the @dfn{target description}. @xref{Target Descriptions}. The @@ -23774,18 +23805,29 @@ An empty reply indicates the @var{object the stub, or that the object does not support reading. @end table -@item qXfer:@var{object}:write:@var{annex}:@var{offset}:@var{data}@dots{} +@item qXfer:@var{object}:write:@var{annex}:@var{offset},@var{length}:@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. +Write @var{length} bytes of uninterpreted data 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. + +@table @samp +@item qXfer:@var{spu}:write:@var{annex}:@var{offset},@var{length}:@var{data}@dots{} +@anchor{qXfer spu write} +@cindex spufs +@cindex SPU +Write @var{length} bytes of @var{data} to an @code{spufs} file on +the target system. The annex specifies which file to write; it must +be of the form @var{id}/@var{name}, where @var{id} specifies an SPU context ID +in the target process, and @var{name} identifes the @code{spufs} file +in that context to be accessed. + +This packet is not probed by default; the remote stub must request it, +by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}). +@end table Reply: @table @samp diff -urNp gdb-orig/gdb/gdbserver/server.c gdb-head/gdb/gdbserver/server.c --- gdb-orig/gdb/gdbserver/server.c 2007-05-16 17:25:22.000000000 +0200 +++ gdb-head/gdb/gdbserver/server.c 2007-06-02 19:32:10.732047243 +0200 @@ -141,13 +141,32 @@ decode_xfer_read (char *buf, char **anne return -1; *buf++ = 0; - /* After the read/write marker and annex, qXfer looks like a + /* After the read marker and annex, qXfer looks like a traditional 'm' packet. */ decode_m_packet (buf, ofs, len); return 0; } +/* Decode a qXfer write request. Return 0 if everything looks OK, + or -1 otherwise. */ +static int +decode_xfer_write (char *buf, int packet_len, char **annex, CORE_ADDR *ofs, + unsigned int *len, unsigned char *data) +{ + /* Extract and NUL-terminate the annex. */ + *annex = buf; + while (*buf && *buf != ':') + buf++; + if (*buf == '\0') + return -1; + *buf++ = 0; + + /* After the write marker and annex, qXfer looks like + a traditional 'X' packet. */ + return decode_X_packet (buf, packet_len - strlen (*annex) - 1, ofs, len, data); +} + /* 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 @@ -255,7 +274,7 @@ monitor_show_help (void) /* Handle all of the extended 'q' packets. */ void -handle_query (char *own_buf, int *new_packet_len_p) +handle_query (char *own_buf, int packet_len, int *new_packet_len_p) { static struct inferior_list_entry *thread_ptr; @@ -314,6 +333,69 @@ handle_query (char *own_buf, int *new_pa return; } + if (the_target->qxfer_spu != NULL + && strncmp ("qXfer:spu:read:", own_buf, 15) == 0) + { + char *annex; + int n; + unsigned int len; + CORE_ADDR ofs; + unsigned char *spu_buf; + + strcpy (own_buf, "E00"); + if (decode_xfer_read (own_buf + 15, &annex, &ofs, &len) < 0) + return; + if (len > PBUFSIZ - 2) + len = PBUFSIZ - 2; + spu_buf = malloc (len + 1); + if (!spu_buf) + return; + + n = (*the_target->qxfer_spu) (annex, spu_buf, NULL, ofs, len + 1); + if (n < 0) + write_enn (own_buf); + else if (n > len) + *new_packet_len_p = write_qxfer_response + (own_buf, spu_buf, len, 1); + else + *new_packet_len_p = write_qxfer_response + (own_buf, spu_buf, n, 0); + + free (spu_buf); + return; + } + + if (the_target->qxfer_spu != NULL + && strncmp ("qXfer:spu:write:", own_buf, 16) == 0) + { + char *annex; + int n; + unsigned int len; + CORE_ADDR ofs; + unsigned char *spu_buf; + + strcpy (own_buf, "E00"); + spu_buf = malloc (packet_len - 15); + if (!spu_buf) + return; + if (decode_xfer_write (own_buf + 16, packet_len - 16, &annex, + &ofs, &len, spu_buf) < 0) + { + free (spu_buf); + return; + } + + n = (*the_target->qxfer_spu) + (annex, NULL, (unsigned const char *)spu_buf, ofs, len); + if (n < 0) + write_enn (own_buf); + else + sprintf (own_buf, "%x", n); + + free (spu_buf); + return; + } + if (the_target->read_auxv != NULL && strncmp ("qXfer:auxv:read:", own_buf, 16) == 0) { @@ -403,6 +485,9 @@ handle_query (char *own_buf, int *new_pa if (the_target->read_auxv != NULL) strcat (own_buf, ";qXfer:auxv:read+"); + + if (the_target->qxfer_spu != NULL) + strcat (own_buf, ";qXfer:spu:read+;qXfer:spu:write+"); if (get_features_xml ("target.xml") != NULL) strcat (own_buf, ";qXfer:features:read+"); @@ -809,7 +894,7 @@ main (int argc, char *argv[]) switch (ch) { case 'q': - handle_query (own_buf, &new_packet_len); + handle_query (own_buf, packet_len, &new_packet_len); break; case 'Q': handle_general_set (own_buf); diff -urNp gdb-orig/gdb/gdbserver/spu-low.c gdb-head/gdb/gdbserver/spu-low.c --- gdb-orig/gdb/gdbserver/spu-low.c 2007-06-01 22:31:04.000000000 +0200 +++ gdb-head/gdb/gdbserver/spu-low.c 2007-06-02 19:32:10.738046378 +0200 @@ -574,7 +574,6 @@ spu_arch_string (void) return "spu"; } - static struct target_ops spu_target_ops = { spu_create_inferior, spu_attach, @@ -598,6 +597,7 @@ static struct target_ops spu_target_ops NULL, NULL, spu_arch_string, + spu_proc_xfer_spu, }; void diff -urNp gdb-orig/gdb/gdbserver/target.h gdb-head/gdb/gdbserver/target.h --- gdb-orig/gdb/gdbserver/target.h 2007-05-10 23:34:34.000000000 +0200 +++ gdb-head/gdb/gdbserver/target.h 2007-06-02 19:32:10.751044505 +0200 @@ -185,6 +185,10 @@ struct target_ops /* Return a string identifying the current architecture, or NULL if this operation is not supported. */ const char *(*arch_string) (void); + + /* Read/Write from/to spufs using qXfer packets. */ + int (*qxfer_spu) (const char *annex, unsigned char *readbuf, + unsigned const char *writebuf, CORE_ADDR offset, int len); }; extern struct target_ops *the_target; diff -urNp gdb-orig/gdb/remote.c gdb-head/gdb/remote.c --- gdb-orig/gdb/remote.c 2007-06-01 18:51:01.000000000 +0200 +++ gdb-head/gdb/remote.c 2007-06-02 19:32:10.810036003 +0200 @@ -907,6 +907,8 @@ enum { PACKET_qXfer_auxv, PACKET_qXfer_features, PACKET_qXfer_memory_map, + PACKET_qXfer_spu_read, + PACKET_qXfer_spu_write, PACKET_qGetTLSAddr, PACKET_qSupported, PACKET_QPassSignals, @@ -5517,18 +5519,59 @@ the loaded file\n")); printf_filtered (_("No loaded section named '%s'.\n"), args); } +/* Write LEN bytes from WRITEBUF into OBJECT_NAME/ANNEX at OFFSET + into remote target. The number of bytes written to the remote + target is returned, or -1 for error. */ + +static LONGEST +remote_write_qxfer (struct target_ops *ops, const char *object_name, + const char *annex, const gdb_byte *writebuf, + ULONGEST offset, LONGEST len, + struct packet_config *packet) +{ + int i, buf_len; + ULONGEST n; + gdb_byte *wbuf; + struct remote_state *rs = get_remote_state (); + int max_size = get_memory_write_packet_size (); + + if (packet->support == PACKET_DISABLE) + return -1; + + /* Insert header. */ + i = snprintf (rs->buf, max_size, + "qXfer:%s:write:%s:%s,%s:", + object_name, annex ? annex : "", + phex_nz (offset, sizeof offset), + phex_nz (len, sizeof len)); + max_size -= (i + 1); + + /* Escape as much data as fits into rs->buf. */ + buf_len = remote_escape_output + (writebuf, len, (rs->buf + i), &max_size, max_size); + + if (putpkt_binary (rs->buf, i + buf_len) < 0 + || getpkt_sane (&rs->buf, &rs->buf_size, 0) < 0 + || packet_ok (rs->buf, packet) != PACKET_OK) + return -1; + + unpack_varlen_hex (rs->buf, &n); + return n; +} + /* 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. */ + target supports this object. If CACHEABLE is set then the packet + is cached. */ 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 packet_config *packet, int cacheable) { static char *finished_object; static char *finished_annex; @@ -5591,7 +5634,8 @@ remote_read_qxfer (struct target_ops *op /* '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') + if (rs->buf[0] == 'l' + && cacheable) { finished_object = xstrdup (object_name); finished_annex = xstrdup (annex ? annex : ""); @@ -5630,6 +5674,19 @@ remote_xfer_partial (struct target_ops * return -1; } + /* Handle SPU memory using qxfer packets. */ + if (object == TARGET_OBJECT_SPU) + { + if (readbuf) + return remote_read_qxfer (ops, "spu", annex, readbuf, offset, len, + &remote_protocol_packets + [PACKET_qXfer_spu_read], 0); + else + return remote_write_qxfer (ops, "spu", annex, writebuf, offset, len, + &remote_protocol_packets + [PACKET_qXfer_spu_write]); + } + /* Only handle flash writes. */ if (writebuf != NULL) { @@ -5663,22 +5720,21 @@ remote_xfer_partial (struct target_ops * case TARGET_OBJECT_AUXV: gdb_assert (annex == NULL); return remote_read_qxfer (ops, "auxv", annex, readbuf, offset, len, - &remote_protocol_packets[PACKET_qXfer_auxv]); + &remote_protocol_packets[PACKET_qXfer_auxv], 1); case TARGET_OBJECT_AVAILABLE_FEATURES: return remote_read_qxfer (ops, "features", annex, readbuf, offset, len, - &remote_protocol_packets[PACKET_qXfer_features]); + &remote_protocol_packets[PACKET_qXfer_features], 1); case TARGET_OBJECT_MEMORY_MAP: gdb_assert (annex == NULL); return remote_read_qxfer (ops, "memory-map", annex, readbuf, offset, len, - &remote_protocol_packets[PACKET_qXfer_memory_map]); + &remote_protocol_packets[PACKET_qXfer_memory_map], 1); default: return -1; } - /* Note: a zero OFFSET and LEN can be used to query the minimum buffer size. */ if (offset == 0 && len == 0) @@ -6540,6 +6596,12 @@ Show the maximum size of the address (in add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_memory_map], "qXfer:memory-map:read", "memory-map", 0); + add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_spu_read], + "qXfer:spu:read", "read-spu-object", 0); + + add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_spu_write], + "qXfer:spu:write", "write-spu-object", 0); + add_packet_config_cmd (&remote_protocol_packets[PACKET_qGetTLSAddr], "qGetTLSAddr", "get-thread-local-storage-address", 0); -- Dr. Ulrich Weigand GNU Toolchain for Linux on System z and Cell BE Ulrich.Weigand@de.ibm.com