From: Maciej W. Rozycki Date: Mon, 21 May 2012 23:50:25 +0000 (+0000) Subject: * linux-low.c (linux_store_registers): Don't re-retrieve data X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=4934b29e91a6f9887cf0641575054279841d82f8;p=binutils-gdb.git * linux-low.c (linux_store_registers): Don't re-retrieve data with ptrace that has already been obtained from /proc. Always copy any data retrieved with ptrace to the buffer supplied. --- diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index 59c500a3f69..cf34bacd8d7 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,9 @@ +2012-05-21 Maciej W. Rozycki + + * linux-low.c (linux_store_registers): Don't re-retrieve data + with ptrace that has already been obtained from /proc. Always + copy any data retrieved with ptrace to the buffer supplied. + 2012-05-11 Yao Qi Pedro Alves diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c index 143a2ed98ce..712cc038ed2 100644 --- a/gdb/gdbserver/linux-low.c +++ b/gdb/gdbserver/linux-low.c @@ -4378,23 +4378,20 @@ linux_store_registers (struct regcache *regcache, int regno) static int linux_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len) { + int pid = lwpid_of (get_thread_lwp (current_inferior)); + register PTRACE_XFER_TYPE *buffer; + register CORE_ADDR addr; + register int count; + char filename[64]; register int i; - /* Round starting address down to longword boundary. */ - register CORE_ADDR addr = memaddr & -(CORE_ADDR) sizeof (PTRACE_XFER_TYPE); - /* Round ending address up; get number of longwords that makes. */ - register int count - = (((memaddr + len) - addr) + sizeof (PTRACE_XFER_TYPE) - 1) - / sizeof (PTRACE_XFER_TYPE); - /* Allocate buffer of that many longwords. */ - register PTRACE_XFER_TYPE *buffer - = (PTRACE_XFER_TYPE *) alloca (count * sizeof (PTRACE_XFER_TYPE)); + int ret; int fd; - char filename[64]; - int pid = lwpid_of (get_thread_lwp (current_inferior)); /* Try using /proc. Don't bother for one word. */ if (len >= 3 * sizeof (long)) { + int bytes; + /* We could keep this file open and cache it - possibly one per thread. That requires some juggling, but is even faster. */ sprintf (filename, "/proc/%d/mem", pid); @@ -4407,38 +4404,56 @@ linux_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len) 32-bit platforms (for instance, SPARC debugging a SPARC64 application). */ #ifdef HAVE_PREAD64 - if (pread64 (fd, myaddr, len, memaddr) != len) + bytes = pread64 (fd, myaddr, len, memaddr); #else - if (lseek (fd, memaddr, SEEK_SET) == -1 || read (fd, myaddr, len) != len) + bytes = -1; + if (lseek (fd, memaddr, SEEK_SET) != -1) + bytes = read (fd, myaddr, len); #endif - { - close (fd); - goto no_proc; - } close (fd); - return 0; + if (bytes == len) + return 0; + + /* Some data was read, we'll try to get the rest with ptrace. */ + if (bytes > 0) + { + memaddr += bytes; + myaddr += bytes; + len -= bytes; + } } no_proc: + /* Round starting address down to longword boundary. */ + addr = memaddr & -(CORE_ADDR) sizeof (PTRACE_XFER_TYPE); + /* Round ending address up; get number of longwords that makes. */ + count = ((((memaddr + len) - addr) + sizeof (PTRACE_XFER_TYPE) - 1) + / sizeof (PTRACE_XFER_TYPE)); + /* Allocate buffer of that many longwords. */ + buffer = (PTRACE_XFER_TYPE *) alloca (count * sizeof (PTRACE_XFER_TYPE)); + /* Read all the longwords */ + errno = 0; for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE)) { - errno = 0; /* Coerce the 3rd arg to a uintptr_t first to avoid potential gcc warning about coercing an 8 byte integer to a 4 byte pointer. */ buffer[i] = ptrace (PTRACE_PEEKTEXT, pid, (PTRACE_ARG3_TYPE) (uintptr_t) addr, 0); if (errno) - return errno; + break; } + ret = errno; /* Copy appropriate bytes out of the buffer. */ + i *= sizeof (PTRACE_XFER_TYPE); + i -= memaddr & (sizeof (PTRACE_XFER_TYPE) - 1); memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (PTRACE_XFER_TYPE) - 1)), - len); + i < len ? i : len); - return 0; + return ret; } /* Copy LEN bytes of data from debugger memory at MYADDR to inferior's