This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[commit] Speed up gdbserver memory reads
- From: Daniel Jacobowitz <drow at false dot org>
- To: gdb-patches at sourceware dot org
- Date: Wed, 19 Sep 2007 10:45:00 -0400
- Subject: [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))
{