From b5d25ec2f9820953f489cd10a9330e28341f451b Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Sat, 6 Dec 2014 03:53:16 +0000 Subject: [PATCH] file.c: move lseek and llseek parsers to a separate file * lseek.c: New file. * Makefile.am (strace_SOURCES): Add it. * file.c: Move sys_lseek, sys_llseek, and related code to lseek.c. --- Makefile.am | 1 + file.c | 87 ---------------------------------------------------- lseek.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+), 87 deletions(-) create mode 100644 lseek.c diff --git a/Makefile.am b/Makefile.am index 0c03252a..47b90a20 100644 --- a/Makefile.am +++ b/Makefile.am @@ -43,6 +43,7 @@ strace_SOURCES = \ ldt.c \ link.c \ loop.c \ + lseek.c \ mem.c \ mknod.c \ mount.c \ diff --git a/file.c b/file.c index 5d6932bb..23c0e15c 100644 --- a/file.c +++ b/file.c @@ -365,93 +365,6 @@ sys_umask(struct tcb *tcp) return RVAL_OCTAL; } -#include "xlat/whence_codes.h" - -/* Linux kernel has exactly one version of lseek: - * fs/read_write.c::SYSCALL_DEFINE3(lseek, unsigned, fd, off_t, offset, unsigned, origin) - * In kernel, off_t is always the same as (kernel's) long - * (see include/uapi/asm-generic/posix_types.h), - * which means that on x32 we need to use tcp->ext_arg[N] to get offset argument. - * Use test/x32_lseek.c to test lseek decoding. - */ -#if defined(LINUX_MIPSN32) || defined(X32) -int -sys_lseek(struct tcb *tcp) -{ - long long offset; - int whence; - - if (entering(tcp)) { - printfd(tcp, tcp->u_arg[0]); - offset = tcp->ext_arg[1]; - whence = tcp->u_arg[2]; - if (whence == SEEK_SET) - tprintf(", %llu, ", offset); - else - tprintf(", %lld, ", offset); - printxval(whence_codes, whence, "SEEK_???"); - } - return RVAL_LUDECIMAL; -} -#else -int -sys_lseek(struct tcb *tcp) -{ - long offset; - int whence; - - if (entering(tcp)) { - printfd(tcp, tcp->u_arg[0]); - offset = tcp->u_arg[1]; - whence = tcp->u_arg[2]; - if (whence == SEEK_SET) - tprintf(", %lu, ", offset); - else - tprintf(", %ld, ", offset); - printxval(whence_codes, whence, "SEEK_???"); - } - return RVAL_UDECIMAL; -} -#endif - -/* llseek syscall takes explicitly two ulong arguments hi, lo, - * rather than one 64-bit argument for which LONG_LONG works - * appropriate for the native byte order. - * - * See kernel's fs/read_write.c::SYSCALL_DEFINE5(llseek, ...) - * - * hi,lo are "unsigned longs" and combined exactly this way in kernel: - * ((loff_t) hi << 32) | lo - * Note that for architectures with kernel's long wider than userspace long - * (such as x32), combining code will use *kernel's*, i.e. *wide* longs - * for hi and lo. We would need to use tcp->ext_arg[N] on x32... - * ...however, x32 (and x86_64) does not _have_ llseek syscall as such. - */ -int -sys_llseek(struct tcb *tcp) -{ - if (entering(tcp)) { - printfd(tcp, tcp->u_arg[0]); - if (tcp->u_arg[4] == SEEK_SET) - tprintf(", %llu, ", - ((long long) tcp->u_arg[1]) << 32 | - (unsigned long long) (unsigned) tcp->u_arg[2]); - else - tprintf(", %lld, ", - ((long long) tcp->u_arg[1]) << 32 | - (unsigned long long) (unsigned) tcp->u_arg[2]); - } - else { - long long off; - if (syserror(tcp) || umove(tcp, tcp->u_arg[3], &off) < 0) - tprintf("%#lx, ", tcp->u_arg[3]); - else - tprintf("[%llu], ", off); - printxval(whence_codes, tcp->u_arg[4], "SEEK_???"); - } - return 0; -} - /* several stats */ #if defined(SPARC) || defined(SPARC64) diff --git a/lseek.c b/lseek.c new file mode 100644 index 00000000..7a0a501e --- /dev/null +++ b/lseek.c @@ -0,0 +1,88 @@ +#include "defs.h" + +#include "xlat/whence_codes.h" + +/* Linux kernel has exactly one version of lseek: + * fs/read_write.c::SYSCALL_DEFINE3(lseek, unsigned, fd, off_t, offset, unsigned, origin) + * In kernel, off_t is always the same as (kernel's) long + * (see include/uapi/asm-generic/posix_types.h), + * which means that on x32 we need to use tcp->ext_arg[N] to get offset argument. + * Use test/x32_lseek.c to test lseek decoding. + */ +#if defined(LINUX_MIPSN32) || defined(X32) +int +sys_lseek(struct tcb *tcp) +{ + long long offset; + int whence; + + if (entering(tcp)) { + printfd(tcp, tcp->u_arg[0]); + offset = tcp->ext_arg[1]; + whence = tcp->u_arg[2]; + if (whence == SEEK_SET) + tprintf(", %llu, ", offset); + else + tprintf(", %lld, ", offset); + printxval(whence_codes, whence, "SEEK_???"); + } + return RVAL_LUDECIMAL; +} +#else +int +sys_lseek(struct tcb *tcp) +{ + long offset; + int whence; + + if (entering(tcp)) { + printfd(tcp, tcp->u_arg[0]); + offset = tcp->u_arg[1]; + whence = tcp->u_arg[2]; + if (whence == SEEK_SET) + tprintf(", %lu, ", offset); + else + tprintf(", %ld, ", offset); + printxval(whence_codes, whence, "SEEK_???"); + } + return RVAL_UDECIMAL; +} +#endif + +/* llseek syscall takes explicitly two ulong arguments hi, lo, + * rather than one 64-bit argument for which LONG_LONG works + * appropriate for the native byte order. + * + * See kernel's fs/read_write.c::SYSCALL_DEFINE5(llseek, ...) + * + * hi,lo are "unsigned longs" and combined exactly this way in kernel: + * ((loff_t) hi << 32) | lo + * Note that for architectures with kernel's long wider than userspace long + * (such as x32), combining code will use *kernel's*, i.e. *wide* longs + * for hi and lo. We would need to use tcp->ext_arg[N] on x32... + * ...however, x32 (and x86_64) does not _have_ llseek syscall as such. + */ +int +sys_llseek(struct tcb *tcp) +{ + if (entering(tcp)) { + printfd(tcp, tcp->u_arg[0]); + if (tcp->u_arg[4] == SEEK_SET) + tprintf(", %llu, ", + ((long long) tcp->u_arg[1]) << 32 | + (unsigned long long) (unsigned) tcp->u_arg[2]); + else + tprintf(", %lld, ", + ((long long) tcp->u_arg[1]) << 32 | + (unsigned long long) (unsigned) tcp->u_arg[2]); + } + else { + long long off; + if (syserror(tcp) || umove(tcp, tcp->u_arg[3], &off) < 0) + tprintf("%#lx, ", tcp->u_arg[3]); + else + tprintf("[%llu], ", off); + printxval(whence_codes, tcp->u_arg[4], "SEEK_???"); + } + return 0; +} -- 2.40.0