Dima Kogan <[email protected]> writes:
> Dima Kogan <[email protected]> writes:
>
>> Does anybody know what's going on? I can imagine anything from the
>> kernel being inconsistent with itself to glibc producing an incorrect
>> kernel interface.
>
> So I just checked to see what data the kernel returns in response to the
> pread() and preadv() calls in the example. The kernel sees the correct
> addresses in both of those calls, so libc is doing the right thing, and
> this is an strace bug/kernel weirdness.
I'll just keep replying to myself :)
I looked into this, and I know what's happening, and a patch is
attached.
preadv/pwritev have a 64-bit 'offset' argument in userspace. The system call,
however, has two separate 32-bit arguments. This is different from syscalls like
pread where the syscall has a 64-bit argument.
In the latter case, alignment requirements apply. In the former (preadv) case,
however, NO alignment requirements apply, since as far as the kernel is
concerned, there are no 64 bit arguments.
To be absolutely clear, here are the syscall definitions of preadv and pread
(I'm looking at fs/read_write.c in Linux 3.14):
SYSCALL_DEFINE4(pread64, unsigned int, fd, char __user *, buf,
size_t, count, loff_t, pos)
SYSCALL_DEFINE5(preadv, unsigned long, fd, const struct iovec __user *, vec,
unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h)
Note that pread64 has a single loff_t pos while preadv has a split pos.
This patch removes the alignment requirements from preadv and pwritev, so the
pos argument is reported correctly
dima
>From d0d4ade5a06648d456a1b1cb02a4a5f8528029bb Mon Sep 17 00:00:00 2001
From: Dima Kogan <[email protected]>
Date: Wed, 16 Apr 2014 02:23:00 -0700
Subject: [PATCH] fixed preadv/pwritev offset reporting
preadv/pwritev have a 64-bit 'offset' argument in userspace. The system call,
however, has two separate 32-bit arguments. This is different from syscalls like
pread where the syscall has a 64-bit argument.
In the latter case, alignment requirements apply. In the former (preadv) case,
however, NO alignment requirements apply, since as far as the kernel is
concerned, there are no 64 bit arguments.
To be absolutely clear, here are the syscall definitions of preadv and pread
(I'm looking at =fs/read_write.c= in Linux 3.14):
SYSCALL_DEFINE4(pread64, unsigned int, fd, char __user *, buf,
size_t, count, loff_t, pos)
SYSCALL_DEFINE5(preadv, unsigned long, fd, const struct iovec __user *, vec,
unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h)
Note thhat pread64 has a single loff_t pos while preadv has a split pos.
This patch removes the alignment requirements from preadv and pwritev, so the
pos argument is reported correctly
---
io.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/io.c b/io.c
index fac5615..4b8569c 100644
--- a/io.c
+++ b/io.c
@@ -230,8 +230,7 @@ sys_preadv(struct tcb *tcp)
return 0;
}
tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], 1);
- tprintf(", %lu, ", tcp->u_arg[2]);
- printllval(tcp, "%llu", PREAD_OFFSET_ARG);
+ tprintf(", %lu, %llu", tcp->u_arg[2], LONG_LONG(tcp->u_arg[3], tcp->u_arg[4]));
}
return 0;
}
@@ -244,7 +243,7 @@ sys_pwritev(struct tcb *tcp)
tprints(", ");
tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1], 1);
tprintf(", %lu, ", tcp->u_arg[2]);
- printllval(tcp, "%llu", PREAD_OFFSET_ARG);
+ tprintf(", %lu, %llu", tcp->u_arg[2], LONG_LONG(tcp->u_arg[3], tcp->u_arg[4]));
}
return 0;
}
--
1.9.2
------------------------------------------------------------------------------
Learn Graph Databases - Download FREE O'Reilly Book
"Graph Databases" is the definitive new guide to graph databases and their
applications. Written by three acclaimed leaders in the field,
this first edition is now available. Download your free book today!
http://p.sf.net/sfu/NeoTech
_______________________________________________
Strace-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/strace-devel