* linux-low.c (linux_store_registers): Don't re-retrieve data
authorMaciej W. Rozycki <macro@linux-mips.org>
Mon, 21 May 2012 23:50:25 +0000 (23:50 +0000)
committerMaciej W. Rozycki <macro@linux-mips.org>
Mon, 21 May 2012 23:50:25 +0000 (23:50 +0000)
with ptrace that has already been obtained from /proc.  Always
copy any data retrieved with ptrace to the buffer supplied.

gdb/gdbserver/ChangeLog
gdb/gdbserver/linux-low.c

index 59c500a..cf34bac 100644 (file)
@@ -1,3 +1,9 @@
+2012-05-21  Maciej W. Rozycki  <macro@codesourcery.com>
+
+       * 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  <yao@codesourcery.com>
            Pedro Alves  <palves@redhat.com>
 
index 143a2ed..712cc03 100644 (file)
@@ -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