This is the mail archive of the
elfutils-devel@sourceware.org
mailing list for the elfutils project.
Re: [PATCH 5/5] Use seek+read instead of pread to read from /dev/$$/mem files.
- From: Jose E. Marchesi <jose dot marchesi at oracle dot com>
- To: elfutils-devel at lists dot fedorahosted dot org
- Date: Fri, 09 Oct 2015 12:35:27 +0200
- Subject: Re: [PATCH 5/5] Use seek+read instead of pread to read from /dev/$$/mem files.
This subtly changes the code to always ignore errors and turns them into
"short reads" instead. Looking at how this code is used I think it is
actually better to instead change the code to report an error with errno.
So return -1 from lseek and just fall through to returning -1 after the
read. It doesn't matter too much, but seems more consistent and might
provide slightly nicer error messages if something fails (actually currently
the error message is swallowed later in the code, but if we are changing
this anyway, then changing it to report a real errno always seems better).
Here you go.
commit 43f68c295e60ca716bc5d1a3876c62f949d4f889
Author: Jose E. Marchesi <jose.marchesi@oracle.com>
Date: Fri Oct 9 06:38:39 2015 -0400
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>
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index ee41405..211f9ec 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -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.
diff --git a/libdwfl/linux-proc-maps.c b/libdwfl/linux-proc-maps.c
index d085834..2a65db2 100644
--- a/libdwfl/linux-proc-maps.c
+++ b/libdwfl/linux-proc-maps.c
@@ -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;