diff options
author | Andreas Arnez <arnez@linux.vnet.ibm.com> | 2017-03-14 11:14:49 +0100 |
---|---|---|
committer | Andreas Arnez <arnez@linux.vnet.ibm.com> | 2017-03-14 11:14:49 +0100 |
commit | a379284af268ed768674e7f452ca78dad2aaaf55 (patch) | |
tree | c3d998b0fb90042f7f4b2617b99985555c62a392 | |
parent | 8a6200ba863f207d93467312431d107f50f0e2ab (diff) | |
download | gdb-a379284af268ed768674e7f452ca78dad2aaaf55.zip gdb-a379284af268ed768674e7f452ca78dad2aaaf55.tar.gz gdb-a379284af268ed768674e7f452ca78dad2aaaf55.tar.bz2 |
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.
-rw-r--r-- | gdb/ChangeLog | 5 | ||||
-rw-r--r-- | 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 { |