Implement 'qXfer:exec-file:read' packet in Valgrind gdbserver.

Thanks to this packet, with recent GDB (>= 7.9.50.20150514-cvs), the
command 'target remote' will automatically load the executable file of
the process running under Valgrind. This means you do not need to
specify the executable file yourself, GDB will discover it itself.
See GDB documentation about 'qXfer:exec-file:read' packet for more
info.



git-svn-id: svn://svn.valgrind.org/valgrind/trunk@15230 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/NEWS b/NEWS
index b702d0a..40cf7ce 100644
--- a/NEWS
+++ b/NEWS
@@ -48,6 +48,14 @@
 * Valgrind can be built with Intel's ICC compiler. The required
   compiler version is 14.0 or later.
 
+* New and modified GDB server monitor features:
+
+  - With recent GDB (>= 7.9.50.20150514-cvs), the command 'target remote'
+    will automatically load the executable file of the process running
+    under Valgrind. This means you do not need to specify the executable
+    file yourself, GDB will discover it itself.
+    See GDB documentation about 'qXfer:exec-file:read' packet for more info.
+
 * ==================== FIXED BUGS ====================
 
 The following bugs have been fixed or resolved.  Note that "n-i-bz"
diff --git a/coregrind/m_gdbserver/server.c b/coregrind/m_gdbserver/server.c
index deedddf..6fb507d 100644
--- a/coregrind/m_gdbserver/server.c
+++ b/coregrind/m_gdbserver/server.c
@@ -916,6 +916,63 @@
       return;
    }
 
+   if (strncmp ("qXfer:exec-file:read:", arg_own_buf, 21) == 0) {
+      unsigned char *data;
+      int n;
+      CORE_ADDR ofs;
+      unsigned int len;
+      const char *annex;
+      unsigned long pid;
+      const HChar *name;
+
+      /* Reject any annex; grab the offset and length.  */
+      if (decode_xfer_read (arg_own_buf + 21, &annex, &ofs, &len) < 0) {
+         strcpy (arg_own_buf, "E00");
+         return;
+      }
+      
+      if (strlen(annex) > 0)
+         pid = strtoul (annex, NULL, 16);
+      else
+         pid = 0;
+      if ((int)pid != VG_(getpid)() && pid != 0) {
+         VG_(sprintf) (arg_own_buf, 
+                       "E.Valgrind gdbserver pid is %d."
+                       " Cannot give info for pid %d",
+                       VG_(getpid)(), (int) pid);
+         return;
+      }
+
+      if (len > PBUFSIZ - 2)
+         len = PBUFSIZ - 2;
+      data = malloc (len);
+
+      if (!VG_(resolve_filename)(VG_(cl_exec_fd), &name)) {
+         VG_(sprintf) (arg_own_buf, 
+                       "E.Valgrind gdbserver could not"
+                       " resolve pid %d exec filename.",
+                       VG_(getpid)());
+         return;
+      }
+
+      if (ofs >= strlen(name))
+         n = -1;
+      else {
+         n = strlen(name) - ofs;
+         VG_(memcpy) (data, name, n);
+      }
+
+      if (n < 0)
+         write_enn (arg_own_buf);
+      else if (n > len)
+         *new_packet_len_p = write_qxfer_response (arg_own_buf, data, len, 1);
+      else
+         *new_packet_len_p = write_qxfer_response (arg_own_buf, data, n, 0);
+      
+      free (data);
+      
+      return;
+   }
 
    /* Protocol features query.  */
    if (strncmp ("qSupported", arg_own_buf, 10) == 0
@@ -923,7 +980,7 @@
       VG_(sprintf) (arg_own_buf, "PacketSize=%x", PBUFSIZ - 1);
       /* Note: max packet size including frame and checksum, but without
          trailing null byte, which is not sent/received. */
-      
+
       strcat (arg_own_buf, ";QStartNoAckMode+");
       strcat (arg_own_buf, ";QPassSignals+");
       if (VG_(client_auxv))
@@ -942,6 +999,7 @@
             not properly connect. */
          initialize_shadow_low(False);
       }
+      strcat (arg_own_buf, ";qXfer:exec-file:read+");
       return;
    }