This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 5/5] Use seek+read instead of pread to read from /dev/$$/mem files.


pread[64] always returns EINVAL when negative offsets are used.
read+seek allows us to read in-memory vdso objects mapped high in the
address space.

Signed-off-by: Jose E. Marchesi <jose.marchesi@oracle.com>
---
 libdwfl/ChangeLog         |  5 +++++
 libdwfl/linux-proc-maps.c | 14 ++++++++++++--
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index ed1156e..355c750 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,8 @@
+2015-10-05  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* linux-proc-maps.c (read_proc_memory): Use seek+read instead of
+	pread, as the later doesn't accept negative offsets.
+
 2015-09-18  Chih-Hung Hsieh  <chh@google.com>
 
 	* relocate.c (relocate_section): Move nested function "relocate"
diff --git a/libdwfl/linux-proc-maps.c b/libdwfl/linux-proc-maps.c
index d085834..83b90db 100644
--- a/libdwfl/linux-proc-maps.c
+++ b/libdwfl/linux-proc-maps.c
@@ -315,9 +315,19 @@ read_proc_memory (void *arg, void *data, GElf_Addr address,
 		  size_t minread, size_t maxread)
 {
   const int fd = *(const int *) arg;
-  ssize_t nread = pread64 (fd, data, maxread, (off64_t) address);
+
+  /* This code relies on the fact the Linux kernel accepts negative
+     offsets when seeking /dev/$$/mem files, as a special case. In
+     particular pread[64] cannot be used here, because it will always
+     return EINVAL when passed a negative offset.  */
+
+  if (lseek (fd, (off64_t) address, SEEK_SET) == -1)
+    return 0;
+
+  ssize_t nread = read (fd, data, maxread);
+
   /* Some kernels don't actually let us do this read, ignore those errors.  */
-  if (nread < 0 && (errno == EINVAL || errno == EPERM))
+  if (nread < 0)
     return 0;
   if (nread > 0 && (size_t) nread < minread)
     nread = 0;
-- 
2.3.4


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]