From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 26594 invoked by alias); 24 May 2013 07:46:22 -0000 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 Received: (qmail 26555 invoked by uid 89); 24 May 2013 07:46:19 -0000 X-Spam-SWARE-Status: No, score=-2.1 required=5.0 tests=AWL,BAYES_00,KHOP_THREADED,TW_CP,TW_XS autolearn=ham version=3.3.1 Received: from gbenson.demon.co.uk (HELO blade.nx) (80.177.220.214) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Fri, 24 May 2013 07:46:17 +0000 Received: by blade.nx (Postfix, from userid 500) id 7E4B426424D; Fri, 24 May 2013 08:46:13 +0100 (BST) Date: Fri, 24 May 2013 07:46:00 -0000 From: Gary Benson To: Tom Tromey Cc: gdb-patches@sourceware.org Subject: [RFA 3/7 take 2] New gdbserver functionality Message-ID: <20130524074613.GA4602@blade.nx> Mail-Followup-To: Tom Tromey , gdb-patches@sourceware.org MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="uQr8t48UFsdbeI+V" Content-Disposition: inline In-Reply-To: <877giyzt2p.fsf@fleche.redhat.com> X-Virus-Found: No X-SW-Source: 2013-05/txt/msg00910.txt.bz2 --uQr8t48UFsdbeI+V Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-length: 1133 Tom Tromey wrote: > >>>>> "Gary" == Gary Benson writes: > > Gary> This patch updates gdbserver to allow arguments to be passed > Gary> in the annex of qXfer:libraries-svr4:read to allow that > Gary> function to transfer partial lists of libraries. The ability > Gary> of gdbserver to support these arguments is indicated by a > Gary> qSupported response containing > Gary> "augmented-libraries-svr4-read+". > > This needs a documentation patch to reflect the new addition to the > remote protocol. The attached patch adds this documentation. I have also attached an updated code patch with more robust argument handling--specifically, if START is unset or set to zero, the stub will read the start of the library list from r_debug in the usual way. In the original patch, specifying *any* arguments would bypass that code, and the code to read the list would see START set to zero. This didn't affect anything now, as there was no reason to use the augmented form of qXfer:libraries-svr4:read without setting START, but it would have caused problems in future if further arguments were added. Thanks, Gary --uQr8t48UFsdbeI+V Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="rtld-probes-8-docs.patch" Content-length: 3453 2013-05-23 Gary Benson * gdb.texinfo (General Query Packets/qSupported): Added "qXfer:libraries-svr4:read" and "augmented-libraries-svr4-read". to the table of currently defined stub features. Added a more detailed entry for "augmented-libraries-svr4-read". (General Query Packets/qXfer:libraries-svr4:read): Documented the augmented form of this packet. diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index b68d2f8..dfe42c9 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -38542,6 +38542,16 @@ These are the currently defined stub features and their properties: @tab @samp{-} @tab Yes +@item @samp{qXfer:libraries-svr4:read} +@tab No +@tab @samp{-} +@tab Yes + +@item @samp{augmented-libraries-svr4-read} +@tab No +@tab @samp{-} +@tab No + @item @samp{qXfer:memory-map:read} @tab No @tab @samp{-} @@ -38718,6 +38728,11 @@ The remote stub understands the @samp{qXfer:libraries:read} packet The remote stub understands the @samp{qXfer:libraries-svr4:read} packet (@pxref{qXfer svr4 library list read}). +@item augmented-libraries-svr4-read +The remote stub understands the augmented form of the +@samp{qXfer:libraries-svr4:read} packet +(@pxref{qXfer svr4 library list read}). + @item qXfer:memory-map:read The remote stub understands the @samp{qXfer:memory-map:read} packet (@pxref{qXfer memory map read}). @@ -39013,7 +39028,10 @@ by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}). @anchor{qXfer svr4 library list read} Access the target's list of loaded libraries when the target is an SVR4 platform. @xref{Library List Format for SVR4 Targets}. The annex part -of the generic @samp{qXfer} packet must be empty (@pxref{qXfer read}). +of the generic @samp{qXfer} packet must be empty unless the remote +stub indicated it supports the augmented form of this packet +by supplying an appropriate @samp{qSupported} response +(@pxref{qXfer read}, @ref{qSupported}). This packet is optional for better performance on SVR4 targets. @value{GDBN} uses memory read packets to read the SVR4 library list otherwise. @@ -39021,6 +39039,30 @@ This packet is optional for better performance on SVR4 targets. This packet is not probed by default; the remote stub must request it, by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}). +If the remote stub indicates it supports the augmented form of this +packet then the annex part of the generic @samp{qXfer} packet may +contain a semicolon-separated list of @samp{@var{name}=@var{value}} +arguments. The currently supported arguments are: + +@table @code +@item start=@var{address} +A hexidecimal number specifying the address of the @samp{struct +link_map} to start reading the library list from. If unset or zero +then the first @samp{struct link_map} in the library list will be +chosen as the starting point. + +@item prev=@var{address} +A hexidecimal number specifying the address of the @samp{struct +link_map} immediately preceding the @samp{struct link_map} +specified by the @samp{start} argument. If unset or zero then +the remote stub will expect that no @samp{struct link_map} +exists prior to the starting point. + +@end table + +Arguments that are not understood by the remote stub will be silently +ignored. + @item qXfer:memory-map:read::@var{offset},@var{length} @anchor{qXfer memory map read} Access the target's @dfn{memory-map}. @xref{Memory Map Format}. The --uQr8t48UFsdbeI+V Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="rtld-probes-3-gdbserver.patch" Content-length: 9134 2013-05-23 Gary Benson * server.c (handle_query): Add "augmented-libraries-svr4-read+" to qSupported response when appropriate. (handle_qxfer_libraries_svr4): Allow qXfer:libraries-svr4:read with nonzero-length annex. * linux-low.c (linux_qxfer_libraries_svr4): Parse and handle arguments supplied in annex. diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c index 6bb36d8..0a8f68b 100644 --- a/gdb/gdbserver/server.c +++ b/gdb/gdbserver/server.c @@ -1115,8 +1115,7 @@ handle_qxfer_libraries_svr4 (const char *annex, if (writebuf != NULL) return -2; - if (annex[0] != '\0' || !target_running () - || the_target->qxfer_libraries_svr4 == NULL) + if (!target_running () || the_target->qxfer_libraries_svr4 == NULL) return -1; return the_target->qxfer_libraries_svr4 (annex, readbuf, writebuf, offset, len); @@ -1743,7 +1742,8 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p) PBUFSIZ - 1); if (the_target->qxfer_libraries_svr4 != NULL) - strcat (own_buf, ";qXfer:libraries-svr4:read+"); + strcat (own_buf, ";qXfer:libraries-svr4:read+" + ";augmented-libraries-svr4-read+"); else { /* We do not have any hook to indicate whether the non-SVR4 target diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c index b01b37c..a7c4b07 100644 --- a/gdb/gdbserver/linux-low.c +++ b/gdb/gdbserver/linux-low.c @@ -5688,6 +5688,12 @@ linux_qxfer_libraries_svr4 (const char *annex, unsigned char *readbuf, }; const struct link_map_offsets *lmo; unsigned int machine; + int ptr_size; + CORE_ADDR lm_addr = 0, lm_prev = 0; + int allocated = 1024; + char *p; + CORE_ADDR l_name, l_addr, l_ld, l_next, l_prev; + int header_done = 0; if (writebuf != NULL) return -2; @@ -5698,128 +5704,144 @@ linux_qxfer_libraries_svr4 (const char *annex, unsigned char *readbuf, xsnprintf (filename, sizeof filename, "/proc/%d/exe", pid); is_elf64 = elf_64_file_p (filename, &machine); lmo = is_elf64 ? &lmo_64bit_offsets : &lmo_32bit_offsets; + ptr_size = is_elf64 ? 8 : 4; - if (priv->r_debug == 0) - priv->r_debug = get_r_debug (pid, is_elf64); + while (annex[0] != '\0') + { + const char *sep; + CORE_ADDR *addrp; + int len; - /* We failed to find DT_DEBUG. Such situation will not change for this - inferior - do not retry it. Report it to GDB as E01, see for the reasons - at the GDB solib-svr4.c side. */ - if (priv->r_debug == (CORE_ADDR) -1) - return -1; + sep = strchr (annex, '='); + if (!sep) + break; - if (priv->r_debug == 0) - { - document = xstrdup ("\n"); + len = sep - annex; + if (len == 5 && !strncmp (annex, "start", 5)) + addrp = &lm_addr; + else if (len == 4 && !strncmp (annex, "prev", 4)) + addrp = &lm_prev; + else + { + annex = strchr (sep, ';'); + if (!annex) + break; + annex++; + continue; + } + + annex = decode_address_to_semicolon (addrp, sep + 1); } - else + + if (lm_addr == 0) { - int allocated = 1024; - char *p; - const int ptr_size = is_elf64 ? 8 : 4; - CORE_ADDR lm_addr, lm_prev, l_name, l_addr, l_ld, l_next, l_prev; - int r_version, header_done = 0; - - document = xmalloc (allocated); - strcpy (document, "r_debug + lmo->r_version_offset, - (unsigned char *) &r_version, - sizeof (r_version)) != 0 - || r_version != 1) + int r_version = 0; + + if (priv->r_debug == 0) + priv->r_debug = get_r_debug (pid, is_elf64); + + /* We failed to find DT_DEBUG. Such situation will not change + for this inferior - do not retry it. Report it to GDB as + E01, see for the reasons at the GDB solib-svr4.c side. */ + if (priv->r_debug == (CORE_ADDR) -1) + return -1; + + if (priv->r_debug != 0) { - warning ("unexpected r_debug version %d", r_version); - goto done; + if (linux_read_memory (priv->r_debug + lmo->r_version_offset, + (unsigned char *) &r_version, + sizeof (r_version)) != 0 + || r_version != 1) + { + warning ("unexpected r_debug version %d", r_version); + } + else if (read_one_ptr (priv->r_debug + lmo->r_map_offset, + &lm_addr, ptr_size) != 0) + { + warning ("unable to read r_map from 0x%lx", + (long) priv->r_debug + lmo->r_map_offset); + } } + } - if (read_one_ptr (priv->r_debug + lmo->r_map_offset, - &lm_addr, ptr_size) != 0) + document = xmalloc (allocated); + strcpy (document, "l_name_offset, + &l_name, ptr_size) == 0 + && read_one_ptr (lm_addr + lmo->l_addr_offset, + &l_addr, ptr_size) == 0 + && read_one_ptr (lm_addr + lmo->l_ld_offset, + &l_ld, ptr_size) == 0 + && read_one_ptr (lm_addr + lmo->l_prev_offset, + &l_prev, ptr_size) == 0 + && read_one_ptr (lm_addr + lmo->l_next_offset, + &l_next, ptr_size) == 0) + { + unsigned char libname[PATH_MAX]; + + if (lm_prev != l_prev) { - warning ("unable to read r_map from 0x%lx", - (long) priv->r_debug + lmo->r_map_offset); - goto done; + warning ("Corrupted shared library list: 0x%lx != 0x%lx", + (long) lm_prev, (long) l_prev); + break; } - lm_prev = 0; - while (read_one_ptr (lm_addr + lmo->l_name_offset, - &l_name, ptr_size) == 0 - && read_one_ptr (lm_addr + lmo->l_addr_offset, - &l_addr, ptr_size) == 0 - && read_one_ptr (lm_addr + lmo->l_ld_offset, - &l_ld, ptr_size) == 0 - && read_one_ptr (lm_addr + lmo->l_prev_offset, - &l_prev, ptr_size) == 0 - && read_one_ptr (lm_addr + lmo->l_next_offset, - &l_next, ptr_size) == 0) + /* Not checking for error because reading may stop before + we've got PATH_MAX worth of characters. */ + libname[0] = '\0'; + linux_read_memory (l_name, libname, sizeof (libname) - 1); + libname[sizeof (libname) - 1] = '\0'; + if (libname[0] != '\0') { - unsigned char libname[PATH_MAX]; + /* 6x the size for xml_escape_text below. */ + size_t len = 6 * strlen ((char *) libname); + char *name; - if (lm_prev != l_prev) + if (!header_done) { - warning ("Corrupted shared library list: 0x%lx != 0x%lx", - (long) lm_prev, (long) l_prev); - break; + /* Terminate `", - name, (unsigned long) lm_addr, - (unsigned long) l_addr, (unsigned long) l_ld); - free (name); - } - else if (lm_prev == 0) - { - sprintf (p, " main-lm=\"0x%lx\"", (unsigned long) lm_addr); - p = p + strlen (p); + document = xrealloc (document, 2 * allocated); + allocated *= 2; + p = document + document_len; } - if (l_next == 0) - break; - - lm_prev = lm_addr; - lm_addr = l_next; + name = xml_escape_text ((char *) libname); + p += sprintf (p, "", + name, (unsigned long) lm_addr, + (unsigned long) l_addr, (unsigned long) l_ld); + free (name); } - done: - if (!header_done) + else if (lm_prev == 0) { - /* Empty list; terminate `"); + sprintf (p, " main-lm=\"0x%lx\"", (unsigned long) lm_addr); + p = p + strlen (p); } - else - strcpy (p, ""); + + lm_prev = lm_addr; + lm_addr = l_next; } + if (!header_done) + { + /* Empty list; terminate `"); + } + else + strcpy (p, ""); + document_len = strlen (document); if (offset < document_len) document_len -= offset; --uQr8t48UFsdbeI+V--