[binutils-gdb] linux-nat: Exploit /proc/<pid>/mem for writing

Andreas Arnez arnez@sourceware.org
Tue Mar 14 11:22:00 GMT 2017


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=a379284af268ed768674e7f452ca78dad2aaaf55

commit a379284af268ed768674e7f452ca78dad2aaaf55
Author: Andreas Arnez <arnez@linux.vnet.ibm.com>
Date:   Tue Mar 14 11:14:49 2017 +0100

    linux-nat: Exploit /proc/<pid>/mem for writing
    
    So far linux_proc_xfer_partial refused to handle write requests.  This is
    still based on the assumption that the Linux kernel does not support
    writes to /proc/<pid>/mem.  That used to be true, but has changed with
    Linux 2.6.39 released in May 2011.
    
    This patch lifts this restriction and now exploits /proc/<pid>/mem for
    writing to inferior memory as well, if possible.
    
    gdb/ChangeLog:
    
    	* linux-nat.c (linux_proc_xfer_partial): Handle write operations
    	as well.

Diff:
---
 gdb/ChangeLog   |  5 +++++
 gdb/linux-nat.c | 32 ++++++++++++++++----------------
 2 files changed, 21 insertions(+), 16 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 608501b..e90fbc0 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,8 @@
+2017-03-14  Andreas Arnez  <arnez@linux.vnet.ibm.com>
+
+	* linux-nat.c (linux_proc_xfer_partial): Handle write operations
+	as well.
+
 2017-03-14  Pedro Alves  <palves@redhat.com>
 
 	* cp-name-parser.y (cp_demangled_name_to_comp): Update comment.
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
index c58ed83..73ef2d4 100644
--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -3978,10 +3978,9 @@ linux_child_pid_to_exec_file (struct target_ops *self, int pid)
   return linux_proc_pid_to_exec_file (pid);
 }
 
-/* Implement the to_xfer_partial interface for memory reads using the /proc
-   filesystem.  Because we can use a single read() call for /proc, this
-   can be much more efficient than banging away at PTRACE_PEEKTEXT,
-   but it doesn't support writes.  */
+/* Implement the to_xfer_partial target method using /proc/<pid>/mem.
+   Because we can use a single read/write call, this can be much more
+   efficient than banging away at PTRACE_PEEKTEXT.  */
 
 static enum target_xfer_status
 linux_proc_xfer_partial (struct target_ops *ops, enum target_object object,
@@ -3993,7 +3992,7 @@ linux_proc_xfer_partial (struct target_ops *ops, enum target_object object,
   int fd;
   char filename[64];
 
-  if (object != TARGET_OBJECT_MEMORY || !readbuf)
+  if (object != TARGET_OBJECT_MEMORY)
     return TARGET_XFER_EOF;
 
   /* Don't bother for one word.  */
@@ -4004,26 +4003,27 @@ linux_proc_xfer_partial (struct target_ops *ops, enum target_object object,
      thread.  That requires some juggling, but is even faster.  */
   xsnprintf (filename, sizeof filename, "/proc/%d/mem",
 	     ptid_get_pid (inferior_ptid));
-  fd = gdb_open_cloexec (filename, O_RDONLY | O_LARGEFILE, 0);
+  fd = gdb_open_cloexec (filename, ((readbuf ? O_RDONLY : O_WRONLY)
+				    | O_LARGEFILE), 0);
   if (fd == -1)
     return TARGET_XFER_EOF;
 
-  /* 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).  */
+  /* Use pread64/pwrite64 if available, since they save a syscall and can
+     handle 64-bit offsets even on 32-bit platforms (for instance, SPARC
+     debugging a SPARC64 application).  */
 #ifdef HAVE_PREAD64
-  if (pread64 (fd, readbuf, len, offset) != len)
+  ret = (readbuf ? pread64 (fd, readbuf, len, offset)
+	 : pwrite64 (fd, writebuf, len, offset));
 #else
-  if (lseek (fd, offset, SEEK_SET) == -1 || read (fd, readbuf, len) != len)
+  ret = lseek (fd, offset, SEEK_SET);
+  if (ret != -1)
+    ret = (readbuf ? read (fd, readbuf, len)
+	   : write (fd, writebuf, len));
 #endif
-    ret = 0;
-  else
-    ret = len;
 
   close (fd);
 
-  if (ret == 0)
+  if (ret == -1 || ret == 0)
     return TARGET_XFER_EOF;
   else
     {



More information about the Gdb-cvs mailing list