From: Dmitry V. Levin Date: Fri, 18 Sep 2015 01:54:59 +0000 (+0000) Subject: Add helper functions to clear/restore syserror X-Git-Tag: v4.11~181 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3858b93ad9d2d3990f6724585e14675e663a1b5d;p=strace Add helper functions to clear/restore syserror * defs.h (temporarily_clear_syserror, restore_cleared_syserror): New prototypes. * syscall.c (saved_u_error): New variable. (temporarily_clear_syserror, restore_cleared_syserror): New functions. * aio.c (sys_io_getevents): Use temporarily_clear_syserror and restore_cleared_syserror. * mq.c (sys_mq_timedreceive): Likewise. * signal.c (sys_rt_sigtimedwait): Likewise. --- diff --git a/aio.c b/aio.c index e9d36e3c..1cbd533a 100644 --- a/aio.c +++ b/aio.c @@ -244,7 +244,14 @@ SYS_FUNC(io_getevents) tprints("], "); } + /* + * Since the timeout parameter is read by the kernel + * on entering syscall, it has to be decoded the same way + * whether the syscall has failed or not. + */ + temporarily_clear_syserror(tcp); print_timespec(tcp, tcp->u_arg[4]); + restore_cleared_syserror(tcp); } return 0; } diff --git a/defs.h b/defs.h index 1f0900b1..119f9b44 100644 --- a/defs.h +++ b/defs.h @@ -538,6 +538,9 @@ extern void get_regs(pid_t pid); extern int get_scno(struct tcb *tcp); extern const char *syscall_name(long scno); +extern void temporarily_clear_syserror(struct tcb *); +extern void restore_cleared_syserror(struct tcb *); + extern int umoven(struct tcb *, long, unsigned int, void *); #define umove(pid, addr, objp) \ umoven((pid), (addr), sizeof(*(objp)), (void *) (objp)) diff --git a/mq.c b/mq.c index ca0cfdaf..a0af2115 100644 --- a/mq.c +++ b/mq.c @@ -59,7 +59,14 @@ SYS_FUNC(mq_timedreceive) else { printstr(tcp, tcp->u_arg[1], tcp->u_arg[2]); tprintf(", %lu, %ld, ", tcp->u_arg[2], tcp->u_arg[3]); + /* + * Since the timeout parameter is read by the kernel + * on entering syscall, it has to be decoded the same way + * whether the syscall has failed or not. + */ + temporarily_clear_syserror(tcp); printtv(tcp, tcp->u_arg[4]); + restore_cleared_syserror(tcp); } return 0; } diff --git a/signal.c b/signal.c index 1df3fe5b..ec1684ef 100644 --- a/signal.c +++ b/signal.c @@ -673,7 +673,16 @@ SYS_FUNC(rt_sigtimedwait) /* syscall exit, and u_arg[1] was NULL */ return 0; } + + /* + * Since the timeout parameter is read by the kernel + * on entering syscall, it has to be decoded the same way + * whether the syscall has failed or not. + */ + temporarily_clear_syserror(tcp); print_timespec(tcp, tcp->u_arg[2]); + restore_cleared_syserror(tcp); + tprintf(", %lu", tcp->u_arg[3]); return 0; }; diff --git a/syscall.c b/syscall.c index b59388b3..aaa44ead 100644 --- a/syscall.c +++ b/syscall.c @@ -1131,6 +1131,21 @@ trace_syscall(struct tcb *tcp) trace_syscall_exiting(tcp) : trace_syscall_entering(tcp); } +static int saved_u_error; + +void +temporarily_clear_syserror(struct tcb *tcp) +{ + saved_u_error = tcp->u_error; + tcp->u_error = 0; +} + +void +restore_cleared_syserror(struct tcb *tcp) +{ + tcp->u_error = saved_u_error; +} + /* * Cannot rely on __kernel_[u]long_t being defined, * it is quite a recent feature of .