From: Jose E. Marchesi Date: Fri, 9 Oct 2015 10:35:27 +0000 (+0200) Subject: Use seek+read instead of pread to read from /dev/$$/mem files. X-Git-Tag: elfutils-0.164~13 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f17d101232d6d40e192e61441aa02a12ee8cf9b8;p=thirdparty%2Felfutils.git 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 --- diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog index ee41405e8..211f9ecd1 100644 --- a/libdwfl/ChangeLog +++ b/libdwfl/ChangeLog @@ -1,3 +1,8 @@ +2015-10-09 Jose E. Marchesi + + * 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 * dwfl_module_getdwarf.c (MAX): Removed. diff --git a/libdwfl/linux-proc-maps.c b/libdwfl/linux-proc-maps.c index d08583420..2a65db2ec 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;