X-Git-Url: https://granicus.if.org/sourcecode?a=blobdiff_plain;f=time.c;h=1f44dca714e0693f25509a59635b73fee7b31ca3;hb=90eee029a92746dc6d9d1cb1ee34ee9e268aecc9;hp=cbfa5568fa5a200ae3df455a98820d33b5be6ee8;hpb=a7945a3d4e144674a8dd1d885e7086bc274e391b;p=strace diff --git a/time.c b/time.c index cbfa5568..1f44dca7 100644 --- a/time.c +++ b/time.c @@ -2,6 +2,7 @@ * Copyright (c) 1991, 1992 Paul Kranenburg * Copyright (c) 1993 Branko Lankester * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey + * Copyright (c) 1996-2018 The strace developers. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,624 +26,320 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $Id$ */ #include "defs.h" - -#ifdef LINUX -#include +#include +#include #include -#include -#include -#endif /* LINUX */ -struct timeval32 +static void +print_timezone(struct tcb *const tcp, const kernel_ulong_t addr) { - u_int32_t tv_sec, tv_usec; -}; + struct timezone tz; -void -printtv_bitness(struct tcb *tcp, long addr, enum bitness_t bitness) -{ - if (addr == 0) - tprintf("NULL"); - else if (!verbose(tcp)) - tprintf("%#lx", addr); - else - { - int rc; - - if (bitness == BITNESS_32 -#if defined(LINUX) && SUPPORTED_PERSONALITIES > 1 - || personality_wordsize[current_personality] == 4 -#endif - ) - { - struct timeval32 tv; - - if ((rc = umove(tcp, addr, &tv)) >= 0) - tprintf("{%u, %u}", - tv.tv_sec, tv.tv_usec); - } else - { - struct timeval tv; - - if ((rc = umove(tcp, addr, &tv)) >= 0) - tprintf("{%lu, %lu}", - (unsigned long) tv.tv_sec, - (unsigned long) tv.tv_usec); - } + if (umove_or_printaddr(tcp, addr, &tz)) + return; - if (rc < 0) - tprintf("{...}"); - } + tprintf("{tz_minuteswest=%d, tz_dsttime=%d}", + tz.tz_minuteswest, tz.tz_dsttime); } -void -sprinttv(struct tcb *tcp, long addr, enum bitness_t bitness, char *buf) -{ - if (addr == 0) - strcpy(buf, "NULL"); - else if (!verbose(tcp)) - sprintf(buf, "%#lx", addr); - else - { - int rc; - - if (bitness == BITNESS_32 -#if defined(LINUX) && SUPPORTED_PERSONALITIES > 1 - || personality_wordsize[current_personality] == 4 -#endif - ) - { - struct timeval32 tv; - - if ((rc = umove(tcp, addr, &tv)) >= 0) - sprintf(buf, "{%u, %u}", - tv.tv_sec, tv.tv_usec); - } else - { - struct timeval tv; - - if ((rc = umove(tcp, addr, &tv)) >= 0) - sprintf(buf, "{%lu, %lu}", - (unsigned long) tv.tv_sec, - (unsigned long) tv.tv_usec); - } - - if (rc < 0) - strcpy(buf, "{...}"); - } -} - -int -sys_time(tcp) -struct tcb *tcp; +SYS_FUNC(gettimeofday) { if (exiting(tcp)) { -#ifndef SVR4 - printnum(tcp, tcp->u_arg[0], "%ld"); -#endif /* SVR4 */ + print_timeval(tcp, tcp->u_arg[0]); + tprints(", "); + print_timezone(tcp, tcp->u_arg[1]); } return 0; } -int -sys_stime(tcp) -struct tcb *tcp; +#ifdef ALPHA +SYS_FUNC(osf_gettimeofday) { if (exiting(tcp)) { - printnum(tcp, tcp->u_arg[0], "%ld"); + print_timeval32(tcp, tcp->u_arg[0]); + tprints(", "); + print_timezone(tcp, tcp->u_arg[1]); } return 0; } +#endif -int -sys_gettimeofday(tcp) -struct tcb *tcp; +SYS_FUNC(settimeofday) { - if (exiting(tcp)) { - if (syserror(tcp)) { - tprintf("%#lx, %#lx", - tcp->u_arg[0], tcp->u_arg[1]); - return 0; - } - printtv(tcp, tcp->u_arg[0]); -#ifndef SVR4 - tprintf(", "); - printtv(tcp, tcp->u_arg[1]); -#endif /* !SVR4 */ - } - return 0; -} + print_timeval(tcp, tcp->u_arg[0]); + tprints(", "); + print_timezone(tcp, tcp->u_arg[1]); + return RVAL_DECODED; +} #ifdef ALPHA -int -sys_osf_gettimeofday(tcp) -struct tcb *tcp; +SYS_FUNC(osf_settimeofday) { - if (exiting(tcp)) { - if (syserror(tcp)) { - tprintf("%#lx, %#lx", - tcp->u_arg[0], tcp->u_arg[1]); - return 0; - } - printtv_bitness(tcp, tcp->u_arg[0], BITNESS_32); -#ifndef SVR4 - tprintf(", "); - printtv_bitness(tcp, tcp->u_arg[1], BITNESS_32); -#endif /* !SVR4 */ - } - return 0; + print_timeval32(tcp, tcp->u_arg[0]); + tprints(", "); + print_timezone(tcp, tcp->u_arg[1]); + + return RVAL_DECODED; } #endif -int -sys_settimeofday(tcp) -struct tcb *tcp; +SYS_FUNC(nanosleep) { if (entering(tcp)) { - printtv(tcp, tcp->u_arg[0]); -#ifndef SVR4 - tprintf(", "); - printtv(tcp, tcp->u_arg[1]); -#endif /* !SVR4 */ + print_timespec(tcp, tcp->u_arg[0]); + tprints(", "); + } else { + + /* + * Second (returned) timespec is only significant if syscall + * was interrupted. On success and in case of other errors we + * print only its address, since kernel doesn't modify it, + * and printing the value may show uninitialized data. + */ + if (is_erestart(tcp)) { + temporarily_clear_syserror(tcp); + print_timespec(tcp, tcp->u_arg[1]); + restore_cleared_syserror(tcp); + } else { + printaddr(tcp->u_arg[1]); + } } return 0; } -#ifdef ALPHA -int -sys_osf_settimeofday(tcp) -struct tcb *tcp; -{ - if (entering(tcp)) { - printtv_bitness(tcp, tcp->u_arg[0], BITNESS_32); -#ifndef SVR4 - tprintf(", "); - printtv_bitness(tcp, tcp->u_arg[1], BITNESS_32); -#endif /* !SVR4 */ - } - return 0; -} -#endif +#include "xlat/itimer_which.h" -int -sys_adjtime(tcp) -struct tcb *tcp; +SYS_FUNC(getitimer) { if (entering(tcp)) { - printtv(tcp, tcp->u_arg[0]); - tprintf(", "); + printxval_index(itimer_which, (unsigned int) tcp->u_arg[0], + "ITIMER_???"); + tprints(", "); } else { - if (syserror(tcp)) - tprintf("%#lx", tcp->u_arg[1]); - else - printtv(tcp, tcp->u_arg[1]); + print_itimerval(tcp, tcp->u_arg[1]); } return 0; } -static const struct xlat which[] = { - { ITIMER_REAL, "ITIMER_REAL" }, - { ITIMER_VIRTUAL,"ITIMER_VIRTUAL"}, - { ITIMER_PROF, "ITIMER_PROF" }, - { 0, NULL }, -}; - -static void -printitv(tcp, addr) -struct tcb *tcp; -long addr; -{ - struct itimerval itv; - - if (addr == 0) - tprintf("NULL"); - else if (!verbose(tcp)) - tprintf("%#lx", addr); - else if (umove(tcp, addr, &itv) < 0) - tprintf("{...}"); - else { - tprintf("{it_interval={%lu, %lu}, it_value={%lu, %lu}}", - (long) itv.it_interval.tv_sec, (long) itv.it_interval.tv_usec, - (long) itv.it_value.tv_sec, (long) itv.it_value.tv_usec); - } -} - - #ifdef ALPHA -static void -printitv32(tcp, addr) -struct tcb *tcp; -long addr; -{ - struct itimerval32 - { - struct timeval32 it_interval; - struct timeval32 it_value; - } itv; - - if (addr == 0) - tprintf("NULL"); - else if (!verbose(tcp)) - tprintf("%#lx", addr); - else if (umove(tcp, addr, &itv) < 0) - tprintf("{...}"); - else { - tprintf("{it_interval={%u, %u}, it_value={%u, %u}}", - itv.it_interval.tv_sec, itv.it_interval.tv_usec, - itv.it_value.tv_sec, itv.it_value.tv_usec); - } -} -#endif - -int -sys_getitimer(tcp) -struct tcb *tcp; +SYS_FUNC(osf_getitimer) { if (entering(tcp)) { - printxval(which, tcp->u_arg[0], "ITIMER_???"); - tprintf(", "); + printxval_index(itimer_which, (unsigned int) tcp->u_arg[0], + "ITIMER_???"); + tprints(", "); } else { - if (syserror(tcp)) - tprintf("%#lx", tcp->u_arg[1]); - else - printitv(tcp, tcp->u_arg[1]); + print_itimerval32(tcp, tcp->u_arg[1]); } return 0; } - - -#ifdef ALPHA -int -sys_osf_getitimer(tcp) -struct tcb *tcp; -{ - if (entering(tcp)) { - printxval(which, tcp->u_arg[0], "ITIMER_???"); - tprintf(", "); - } else { - if (syserror(tcp)) - tprintf("%#lx", tcp->u_arg[1]); - else - printitv32(tcp, tcp->u_arg[1]); - } - return 0; -} #endif -int -sys_setitimer(tcp) -struct tcb *tcp; +SYS_FUNC(setitimer) { if (entering(tcp)) { - printxval(which, tcp->u_arg[0], "ITIMER_???"); - tprintf(", "); - printitv(tcp, tcp->u_arg[1]); - tprintf(", "); + printxval_index(itimer_which, (unsigned int) tcp->u_arg[0], + "ITIMER_???"); + tprints(", "); + print_itimerval(tcp, tcp->u_arg[1]); + tprints(", "); } else { - if (syserror(tcp)) - tprintf("%#lx", tcp->u_arg[2]); - else - printitv(tcp, tcp->u_arg[2]); + print_itimerval(tcp, tcp->u_arg[2]); } return 0; } #ifdef ALPHA -int -sys_osf_setitimer(tcp) -struct tcb *tcp; +SYS_FUNC(osf_setitimer) { - if (entering(tcp)) { - printxval(which, tcp->u_arg[0], "ITIMER_???"); - tprintf(", "); - printitv32(tcp, tcp->u_arg[1]); - tprintf(", "); - } else { - if (syserror(tcp)) - tprintf("%#lx", tcp->u_arg[2]); - else - printitv32(tcp, tcp->u_arg[2]); - } - return 0; + if (entering(tcp)) { + printxval_index(itimer_which, (unsigned int) tcp->u_arg[0], + "ITIMER_???"); + tprints(", "); + print_itimerval32(tcp, tcp->u_arg[1]); + tprints(", "); + } else { + print_itimerval32(tcp, tcp->u_arg[2]); + } + return 0; } #endif -#ifdef LINUX +#include "xlat/adjtimex_state.h" -int -sys_adjtimex(tcp) -struct tcb *tcp; +static int +do_adjtimex(struct tcb *const tcp, const kernel_ulong_t addr) { - struct timex txc; + if (print_timex(tcp, addr)) + return 0; + tcp->auxstr = xlat_idx(adjtimex_state, ARRAY_SIZE(adjtimex_state) - 1, + (kernel_ulong_t) tcp->u_rval); + return RVAL_STR; +} - if (exiting(tcp)) { - if (tcp->u_arg[0] == 0) - tprintf("NULL"); - else if (syserror(tcp) || !verbose(tcp)) - tprintf("%#lx", tcp->u_arg[0]); - else if (umove(tcp, tcp->u_arg[0], &txc) < 0) - tprintf("{...}"); - else { -#if LINUX_VERSION_CODE < 66332 - tprintf("{mode=%d, offset=%ld, frequency=%ld, ", - txc.mode, txc.offset, txc.frequency); - tprintf("maxerror=%ld, esterror=%lu, status=%u, ", - txc.maxerror, txc.esterror, txc.status); - tprintf("time_constant=%ld, precision=%lu, ", - txc.time_constant, txc.precision); - tprintf("tolerance=%ld, time={%lu, %lu}}", - txc.tolerance, (long) txc.time.tv_sec, - (long) txc.time.tv_usec); -#else - tprintf("{modes=%d, offset=%ld, freq=%ld, ", - txc.modes, txc.offset, txc.freq); - tprintf("maxerror=%ld, esterror=%lu, status=%u, ", - txc.maxerror, txc.esterror, txc.status); - tprintf("constant=%ld, precision=%lu, ", - txc.constant, txc.precision); - tprintf("tolerance=%ld, time={%lu, %lu}}", - txc.tolerance, (long) txc.time.tv_sec, - (long) txc.time.tv_usec); - /* there's a bunch of other stuff, but it's not - * worth the time or the trouble to include */ -#endif - } - } +SYS_FUNC(adjtimex) +{ + if (exiting(tcp)) + return do_adjtimex(tcp, tcp->u_arg[0]); return 0; } -static const struct xlat clockflags[] = { - { TIMER_ABSTIME, "TIMER_ABSTIME" }, - { 0, NULL } -}; +#include "xlat/clockflags.h" +#include "xlat/clocknames.h" -static const struct xlat clocknames[] = { -#ifdef CLOCK_REALTIME - { CLOCK_REALTIME, "CLOCK_REALTIME" }, -#endif -#ifdef CLOCK_MONOTONIC - { CLOCK_MONOTONIC, "CLOCK_MONOTONIC" }, +static void +printclockname(int clockid) +{ +#ifdef CLOCKID_TO_FD +# include "xlat/cpuclocknames.h" + + if (clockid < 0) { + if ((clockid & CLOCKFD_MASK) == CLOCKFD) + tprintf("FD_TO_CLOCKID(%d)", CLOCKID_TO_FD(clockid)); + else { + tprintf("%s(%d,", + CPUCLOCK_PERTHREAD(clockid) ? + "MAKE_THREAD_CPUCLOCK" : + "MAKE_PROCESS_CPUCLOCK", + CPUCLOCK_PID(clockid)); + printxval_index(cpuclocknames, + (unsigned int) clockid & CLOCKFD_MASK, + "CPUCLOCK_???"); + tprints(")"); + } + } else #endif - { 0, NULL } -}; + printxval_index(clocknames, clockid, "CLOCK_???"); +} -int -sys_clock_settime(tcp) -struct tcb *tcp; +SYS_FUNC(clock_settime) { - if (entering(tcp)) { - printxval(clocknames, tcp->u_arg[0], "CLOCK_???"); - tprintf(", "); - printtv(tcp, tcp->u_arg[1]); - } - return 0; + printclockname(tcp->u_arg[0]); + tprints(", "); + print_timespec(tcp, tcp->u_arg[1]); + + return RVAL_DECODED; } -int -sys_clock_gettime(tcp) -struct tcb *tcp; +SYS_FUNC(clock_gettime) { if (entering(tcp)) { - printxval(clocknames, tcp->u_arg[0], "CLOCK_???"); - tprintf(", "); + printclockname(tcp->u_arg[0]); + tprints(", "); } else { - if (syserror(tcp)) - tprintf("%#lx", tcp->u_arg[1]); - else - printtv(tcp, tcp->u_arg[1]); + print_timespec(tcp, tcp->u_arg[1]); } return 0; } -int -sys_clock_nanosleep(tcp) -struct tcb *tcp; +SYS_FUNC(clock_nanosleep) { if (entering(tcp)) { - printxval(clocknames, tcp->u_arg[0], "CLOCK_???"); - tprintf(", "); + printclockname(tcp->u_arg[0]); + tprints(", "); printflags(clockflags, tcp->u_arg[1], "TIMER_???"); - tprintf(", "); - printtv(tcp, tcp->u_arg[2]); - tprintf(", "); + tprints(", "); + print_timespec(tcp, tcp->u_arg[2]); + tprints(", "); } else { - if (syserror(tcp)) - tprintf("%#lx", tcp->u_arg[3]); - else - printtv(tcp, tcp->u_arg[3]); + /* + * Second (returned) timespec is only significant + * if syscall was interrupted and flags is not TIMER_ABSTIME. + */ + if (!tcp->u_arg[1] && is_erestart(tcp)) { + temporarily_clear_syserror(tcp); + print_timespec(tcp, tcp->u_arg[3]); + restore_cleared_syserror(tcp); + } else { + printaddr(tcp->u_arg[3]); + } } return 0; } -#ifndef SIGEV_THREAD_ID -# define SIGEV_THREAD_ID 4 -#endif -static const struct xlat sigev_value[] = { - { SIGEV_SIGNAL+1, "SIGEV_SIGNAL" }, - { SIGEV_NONE+1, "SIGEV_NONE" }, - { SIGEV_THREAD+1, "SIGEV_THREAD" }, - { SIGEV_THREAD_ID+1, "SIGEV_THREAD_ID" }, - { 0, NULL } -}; - -void -printsigevent(tcp, arg) -struct tcb *tcp; -long arg; +SYS_FUNC(clock_adjtime) { - struct sigevent sev; - if (umove (tcp, arg, &sev) < 0) - tprintf("{...}"); - else { - tprintf("{%p, ", sev.sigev_value.sival_ptr); - if (sev.sigev_notify == SIGEV_SIGNAL) - tprintf("%s, ", signame(sev.sigev_signo)); - else - tprintf("%u, ", sev.sigev_signo); - printxval(sigev_value, sev.sigev_notify+1, "SIGEV_???"); - tprintf(", "); - if (sev.sigev_notify == SIGEV_THREAD_ID) - /* _pad[0] is the _tid field which might not be - present in the userlevel definition of the - struct. */ - tprintf("{%d}", sev._sigev_un._pad[0]); - else if (sev.sigev_notify == SIGEV_THREAD) - tprintf("{%p, %p}", sev.sigev_notify_function, - sev.sigev_notify_attributes); - else - tprintf("{...}"); - tprintf("}"); - } + if (exiting(tcp)) + return do_adjtimex(tcp, tcp->u_arg[1]); + printclockname(tcp->u_arg[0]); + tprints(", "); + return 0; } -int -sys_timer_create(tcp) -struct tcb *tcp; +SYS_FUNC(timer_create) { if (entering(tcp)) { - printxval(clocknames, tcp->u_arg[0], "CLOCK_???"); - tprintf(", "); - printsigevent(tcp, tcp->u_arg[1]); - tprintf(", "); + printclockname(tcp->u_arg[0]); + tprints(", "); + print_sigevent(tcp, tcp->u_arg[1]); + tprints(", "); } else { - void *p; - - if (syserror(tcp) || umove(tcp, tcp->u_arg[2], &p) < 0) - tprintf("%#lx", tcp->u_arg[2]); - else - tprintf("{%p}", p); + printnum_int(tcp, tcp->u_arg[2], "%d"); } return 0; } -int -sys_timer_settime(tcp) -struct tcb *tcp; +SYS_FUNC(timer_settime) { if (entering(tcp)) { - tprintf("%#lx, ", tcp->u_arg[0]); + tprintf("%d, ", (int) tcp->u_arg[0]); printflags(clockflags, tcp->u_arg[1], "TIMER_???"); - tprintf(", "); - printitv(tcp, tcp->u_arg[2]); - tprintf(", "); + tprints(", "); + print_itimerspec(tcp, tcp->u_arg[2]); + tprints(", "); } else { - if (syserror(tcp)) - tprintf("%#lx", tcp->u_arg[3]); - else - printitv(tcp, tcp->u_arg[3]); + print_itimerspec(tcp, tcp->u_arg[3]); } return 0; } -int -sys_timer_gettime(tcp) -struct tcb *tcp; +SYS_FUNC(timer_gettime) { if (entering(tcp)) { - tprintf("%#lx, ", tcp->u_arg[0]); + tprintf("%d, ", (int) tcp->u_arg[0]); } else { - if (syserror(tcp)) - tprintf("%#lx", tcp->u_arg[1]); - else - printitv(tcp, tcp->u_arg[1]); + print_itimerspec(tcp, tcp->u_arg[1]); } return 0; } -static void -print_rtc(tcp, rt) -struct tcb *tcp; -const struct rtc_time *rt; +#include "xlat/timerfdflags.h" + +SYS_FUNC(timerfd_create) { - tprintf("{tm_sec=%d, tm_min=%d, tm_hour=%d, " - "tm_mday=%d, tm_mon=%d, tm_year=%d, ", - rt->tm_sec, rt->tm_min, rt->tm_hour, - rt->tm_mday, rt->tm_mon, rt->tm_year); - if (!abbrev(tcp)) - tprintf("tm_wday=%d, tm_yday=%d, tm_isdst=%d}", - rt->tm_wday, rt->tm_yday, rt->tm_isdst); - else - tprintf("...}"); + printclockname(tcp->u_arg[0]); + tprints(", "); + printflags(timerfdflags, tcp->u_arg[1], "TFD_???"); + + return RVAL_DECODED | RVAL_FD; } -int -rtc_ioctl(tcp, code, arg) -struct tcb *tcp; -long code; -long arg; +SYS_FUNC(timerfd_settime) { - switch (code) { - case RTC_ALM_SET: - case RTC_SET_TIME: - if (entering(tcp)) { - struct rtc_time rt; - if (umove(tcp, arg, &rt) < 0) - tprintf(", %#lx", arg); - else { - tprintf(", "); - print_rtc(tcp, &rt); - } - } - break; - case RTC_ALM_READ: - case RTC_RD_TIME: - if (exiting(tcp)) { - struct rtc_time rt; - if (syserror(tcp) || umove(tcp, arg, &rt) < 0) - tprintf(", %#lx", arg); - else { - tprintf(", "); - print_rtc(tcp, &rt); - } - } - break; - case RTC_IRQP_SET: - case RTC_EPOCH_SET: - if (entering(tcp)) - tprintf(", %lu", arg); - break; - case RTC_IRQP_READ: - case RTC_EPOCH_READ: - if (exiting(tcp)) - tprintf(", %lu", arg); - break; - case RTC_WKALM_SET: - if (entering(tcp)) { - struct rtc_wkalrm wk; - if (umove(tcp, arg, &wk) < 0) - tprintf(", %#lx", arg); - else { - tprintf(", {enabled=%d, pending=%d, ", - wk.enabled, wk.pending); - print_rtc(tcp, &wk.time); - tprintf("}"); - } - } - break; - case RTC_WKALM_RD: - if (exiting(tcp)) { - struct rtc_wkalrm wk; - if (syserror(tcp) || umove(tcp, arg, &wk) < 0) - tprintf(", %#lx", arg); - else { - tprintf(", {enabled=%d, pending=%d, ", - wk.enabled, wk.pending); - print_rtc(tcp, &wk.time); - tprintf("}"); - } - } - break; - default: - if (entering(tcp)) - tprintf(", %#lx", arg); - break; + if (entering(tcp)) { + printfd(tcp, tcp->u_arg[0]); + tprints(", "); + printflags(timerfdflags, tcp->u_arg[1], "TFD_???"); + tprints(", "); + print_itimerspec(tcp, tcp->u_arg[2]); + tprints(", "); + } else { + print_itimerspec(tcp, tcp->u_arg[3]); } - return 1; + return 0; +} + +SYS_FUNC(timerfd_gettime) +{ + if (entering(tcp)) { + printfd(tcp, tcp->u_arg[0]); + tprints(", "); + } else { + print_itimerspec(tcp, tcp->u_arg[1]); + } + return 0; } -#endif /* LINUX */