]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
Use seek+read instead of pread to read from /dev/$$/mem files.
authorJose E. Marchesi <jose.marchesi@oracle.com>
Fri, 9 Oct 2015 10:35:27 +0000 (12:35 +0200)
committerMark Wielaard <mjw@redhat.com>
Fri, 9 Oct 2015 13:42:34 +0000 (15:42 +0200)
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
libdwfl/linux-proc-maps.c

index ee41405e8a9cb4da1644db7147e5a0e69e8f7424..211f9ecd19ec5cf17914f5ae462eda882b5f0ae5 100644 (file)
@@ -1,3 +1,8 @@
+2015-10-09  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-10-07  Mark Wielaard  <mjw@redhat.com>
 
        * dwfl_module_getdwarf.c (MAX): Removed.
index d0858342014e1173d8db395908c834b2334fc74b..2a65db2ecee53dc6829500754c11058da28410ff 100644 (file)
@@ -315,10 +315,17 @@ 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);
-  /* Some kernels don't actually let us do this read, ignore those errors.  */
-  if (nread < 0 && (errno == EINVAL || errno == EPERM))
-    return 0;
+
+  /* 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 -1;
+
+  ssize_t nread = read (fd, data, maxread);
+
   if (nread > 0 && (size_t) nread < minread)
     nread = 0;
   return nread;