This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[commit] Speed up gdbserver memory reads


This patch copies a useful optimization I made for GDB into gdbserver.
It's much faster to read a large block of memory by using pread64 on
/proc/PID/mem than by using ptrace, since the former takes one syscall
and the latter takes one per word.

Tested on mips-linux and checked in.

It happens to also improve reliability of gdbserver on MIPS qemu
system emulation.  Without this patch huge.exp reliably crashes the
emulator and with it it passes.  That's a qemu bug, but the result
was useful since I couldn't figure out the qemu bug :-)

-- 
Daniel Jacobowitz
CodeSourcery

2007-09-19  Daniel Jacobowitz  <dan@codesourcery.com>

	* linux-low.c (O_LARGEFILE): Define.
	(linux_read_memory): Use /proc/PID/mem.
	* configure.ac: Use AC_GNU_SOURCE.  Check for pread64.
	* configure, config.in: Regenerated.

Index: gdbserver/configure.ac
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/configure.ac,v
retrieving revision 1.16
diff -u -p -r1.16 configure.ac
--- gdbserver/configure.ac	23 Aug 2007 17:58:44 -0000	1.16
+++ gdbserver/configure.ac	19 Sep 2007 14:40:27 -0000
@@ -25,6 +25,7 @@ AC_INIT(server.c)
 AC_CONFIG_HEADER(config.h:config.in)
 
 AC_PROG_CC
+AC_GNU_SOURCE
 
 AC_CANONICAL_SYSTEM
 
@@ -40,6 +41,7 @@ AC_CHECK_HEADERS(sgtty.h termio.h termio
  		 errno.h fcntl.h signal.h sys/file.h malloc.h dnl
 		 sys/ioctl.h netinet/in.h sys/socket.h netdb.h dnl
 		 netinet/tcp.h arpa/inet.h sys/wait.h)
+AC_CHECK_FUNCS(pread64)
 
 have_errno=no
 AC_MSG_CHECKING(for errno)
Index: gdbserver/linux-low.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/linux-low.c,v
retrieving revision 1.61
diff -u -p -r1.61 linux-low.c
--- gdbserver/linux-low.c	4 Sep 2007 21:30:23 -0000	1.61
+++ gdbserver/linux-low.c	19 Sep 2007 14:40:27 -0000
@@ -40,6 +40,10 @@
 # define PTRACE_SETSIGINFO 0x4203
 #endif
 
+#ifndef O_LARGEFILE
+#define O_LARGEFILE 0
+#endif
+
 #ifdef __UCLIBC__
 #if !(defined(__UCLIBC_HAS_MMU__) || defined(__ARCH_HAS_MMU__))
 #define HAS_NOMMU
@@ -1488,7 +1492,38 @@ linux_read_memory (CORE_ADDR memaddr, un
   /* Allocate buffer of that many longwords.  */
   register PTRACE_XFER_TYPE *buffer
     = (PTRACE_XFER_TYPE *) alloca (count * sizeof (PTRACE_XFER_TYPE));
+  int fd;
+  char filename[64];
+
+  /* Try using /proc.  Don't bother for one word.  */
+  if (len >= 3 * sizeof (long))
+    {
+      /* We could keep this file open and cache it - possibly one per
+	 thread.  That requires some juggling, but is even faster.  */
+      sprintf (filename, "/proc/%ld/mem", inferior_pid);
+      fd = open (filename, O_RDONLY | O_LARGEFILE);
+      if (fd == -1)
+	goto no_proc;
+
+      /* If pread64 is available, use it.  It's faster if the kernel
+	 supports it (only one syscall), and it's 64-bit safe even on
+	 32-bit platforms (for instance, SPARC debugging a SPARC64
+	 application).  */
+#ifdef HAVE_PREAD64
+      if (pread64 (fd, myaddr, len, memaddr) != len)
+#else
+      if (lseek (fd, memaddr, SEEK_SET) == -1 || read (fd, memaddr, len) != len)
+#endif
+	{
+	  close (fd);
+	  goto no_proc;
+	}
+
+      close (fd);
+      return 0;
+    }
 
+ no_proc:
   /* Read all the longwords */
   for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
     {


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]