]> granicus.if.org Git - strace/blob - time.c
arm: fix v4.10-25-g8497b62 fallout
[strace] / time.c
1 /*
2  * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3  * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4  * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include "defs.h"
31 #include <fcntl.h>
32 #include <linux/version.h>
33 #include <sys/timex.h>
34 #include <linux/ioctl.h>
35 #include <linux/rtc.h>
36
37 #ifndef UTIME_NOW
38 #define UTIME_NOW ((1l << 30) - 1l)
39 #endif
40 #ifndef UTIME_OMIT
41 #define UTIME_OMIT ((1l << 30) - 2l)
42 #endif
43
44 #if SUPPORTED_PERSONALITIES > 1
45 # if defined X86_64 || defined X32
46 #  define current_time_t_is_compat (current_personality == 1)
47 # else
48 #  define current_time_t_is_compat (current_wordsize == 4)
49 # endif
50 #else
51 # define current_time_t_is_compat 0
52 #endif
53
54 struct timeval32
55 {
56         u_int32_t tv_sec, tv_usec;
57 };
58
59 static void
60 tprint_timeval32(struct tcb *tcp, const struct timeval32 *tv)
61 {
62         tprintf("{%u, %u}", tv->tv_sec, tv->tv_usec);
63 }
64
65 static void
66 tprint_timeval(struct tcb *tcp, const struct timeval *tv)
67 {
68         tprintf("{%ju, %ju}", (uintmax_t) tv->tv_sec, (uintmax_t) tv->tv_usec);
69 }
70
71 void
72 printtv_bitness(struct tcb *tcp, long addr, enum bitness_t bitness, int special)
73 {
74         char buf[TIMEVAL_TEXT_BUFSIZE];
75         sprinttv(buf, tcp, addr, bitness, special);
76         tprints(buf);
77 }
78
79 static char *
80 do_sprinttv(char *buf, const uintmax_t sec, const uintmax_t usec,
81             const int special)
82 {
83         if (special) {
84                 switch (usec) {
85                         case UTIME_NOW:
86                                 return stpcpy(buf, "UTIME_NOW");
87                         case UTIME_OMIT:
88                                 return stpcpy(buf, "UTIME_OMIT");
89                 }
90         }
91         return buf + sprintf(buf, "{%ju, %ju}", sec, usec);
92 }
93
94 char *
95 sprinttv(char *buf, struct tcb *tcp, long addr, enum bitness_t bitness, int special)
96 {
97         if (addr == 0)
98                 return stpcpy(buf, "NULL");
99
100         if (!verbose(tcp))
101                 return buf + sprintf(buf, "%#lx", addr);
102
103         if (bitness == BITNESS_32 || current_time_t_is_compat)
104         {
105                 struct timeval32 tv;
106
107                 if (umove(tcp, addr, &tv) >= 0)
108                         return do_sprinttv(buf, tv.tv_sec, tv.tv_usec, special);
109         } else {
110                 struct timeval tv;
111
112                 if (umove(tcp, addr, &tv) >= 0)
113                         return do_sprinttv(buf, tv.tv_sec, tv.tv_usec, special);
114         }
115
116         return stpcpy(buf, "{...}");
117 }
118
119 void
120 print_timespec(struct tcb *tcp, long addr)
121 {
122         char buf[TIMESPEC_TEXT_BUFSIZE];
123         sprint_timespec(buf, tcp, addr);
124         tprints(buf);
125 }
126
127 void
128 sprint_timespec(char *buf, struct tcb *tcp, long addr)
129 {
130         if (addr == 0)
131                 strcpy(buf, "NULL");
132         else if (!verbose(tcp))
133                 sprintf(buf, "%#lx", addr);
134         else {
135                 int rc;
136
137 #if SUPPORTED_PERSONALITIES > 1
138                 if (current_time_t_is_compat) {
139                         struct timeval32 tv;
140
141                         rc = umove(tcp, addr, &tv);
142                         if (rc >= 0)
143                                 sprintf(buf, "{%u, %u}",
144                                         tv.tv_sec, tv.tv_usec);
145                 } else
146 #endif
147                 {
148                         struct timespec ts;
149
150                         rc = umove(tcp, addr, &ts);
151                         if (rc >= 0)
152                                 sprintf(buf, "{%ju, %ju}",
153                                         (uintmax_t) ts.tv_sec,
154                                         (uintmax_t) ts.tv_nsec);
155                 }
156                 if (rc < 0)
157                         strcpy(buf, "{...}");
158         }
159 }
160
161 int
162 sys_time(struct tcb *tcp)
163 {
164         if (exiting(tcp)) {
165                 printnum_long(tcp, tcp->u_arg[0], "%ld");
166         }
167         return 0;
168 }
169
170 int
171 sys_gettimeofday(struct tcb *tcp)
172 {
173         if (exiting(tcp)) {
174                 if (syserror(tcp)) {
175                         tprintf("%#lx, %#lx", tcp->u_arg[0], tcp->u_arg[1]);
176                         return 0;
177                 }
178                 printtv(tcp, tcp->u_arg[0]);
179                 tprints(", ");
180                 printtv(tcp, tcp->u_arg[1]);
181         }
182         return 0;
183 }
184
185 #ifdef ALPHA
186 int
187 sys_osf_gettimeofday(struct tcb *tcp)
188 {
189         if (exiting(tcp)) {
190                 if (syserror(tcp)) {
191                         tprintf("%#lx, %#lx", tcp->u_arg[0], tcp->u_arg[1]);
192                         return 0;
193                 }
194                 printtv_bitness(tcp, tcp->u_arg[0], BITNESS_32, 0);
195                 tprints(", ");
196                 printtv_bitness(tcp, tcp->u_arg[1], BITNESS_32, 0);
197         }
198         return 0;
199 }
200 #endif
201
202 int
203 sys_settimeofday(struct tcb *tcp)
204 {
205         if (entering(tcp)) {
206                 printtv(tcp, tcp->u_arg[0]);
207                 tprints(", ");
208                 printtv(tcp, tcp->u_arg[1]);
209         }
210         return 0;
211 }
212
213 #ifdef ALPHA
214 int
215 sys_osf_settimeofday(struct tcb *tcp)
216 {
217         if (entering(tcp)) {
218                 printtv_bitness(tcp, tcp->u_arg[0], BITNESS_32, 0);
219                 tprints(", ");
220                 printtv_bitness(tcp, tcp->u_arg[1], BITNESS_32, 0);
221         }
222         return 0;
223 }
224 #endif
225
226 int
227 sys_adjtime(struct tcb *tcp)
228 {
229         if (entering(tcp)) {
230                 printtv(tcp, tcp->u_arg[0]);
231                 tprints(", ");
232         } else {
233                 if (syserror(tcp))
234                         tprintf("%#lx", tcp->u_arg[1]);
235                 else
236                         printtv(tcp, tcp->u_arg[1]);
237         }
238         return 0;
239 }
240
241 int
242 sys_nanosleep(struct tcb *tcp)
243 {
244         if (entering(tcp)) {
245                 print_timespec(tcp, tcp->u_arg[0]);
246                 tprints(", ");
247         } else {
248                 /* Second (returned) timespec is only significant
249                  * if syscall was interrupted. On success, we print
250                  * only its address, since kernel doesn't modify it,
251                  * and printing the value may show uninitialized data.
252                  */
253                 switch (tcp->u_error) {
254                 default:
255                         /* Not interrupted (slept entire interval) */
256                         if (tcp->u_arg[1]) {
257                                 tprintf("%#lx", tcp->u_arg[1]);
258                                 break;
259                         }
260                         /* Fall through: print_timespec(NULL) prints "NULL" */
261                 case ERESTARTSYS:
262                 case ERESTARTNOINTR:
263                 case ERESTARTNOHAND:
264                 case ERESTART_RESTARTBLOCK:
265                         /* Interrupted */
266                         print_timespec(tcp, tcp->u_arg[1]);
267                 }
268         }
269         return 0;
270 }
271
272 #include "xlat/itimer_which.h"
273
274 static void
275 printitv_bitness(struct tcb *tcp, long addr, enum bitness_t bitness)
276 {
277         if (addr == 0)
278                 tprints("NULL");
279         else if (!verbose(tcp))
280                 tprintf("%#lx", addr);
281         else {
282                 int rc;
283
284                 if (bitness == BITNESS_32 || current_time_t_is_compat) {
285                         struct {
286                                 struct timeval32 it_interval, it_value;
287                         } itv;
288
289                         rc = umove(tcp, addr, &itv);
290                         if (rc >= 0) {
291                                 tprints("{it_interval=");
292                                 tprint_timeval32(tcp, &itv.it_interval);
293                                 tprints(", it_value=");
294                                 tprint_timeval32(tcp, &itv.it_value);
295                                 tprints("}");
296                         }
297                 } else {
298                         struct itimerval itv;
299
300                         rc = umove(tcp, addr, &itv);
301                         if (rc >= 0) {
302                                 tprints("{it_interval=");
303                                 tprint_timeval(tcp, &itv.it_interval);
304                                 tprints(", it_value=");
305                                 tprint_timeval(tcp, &itv.it_value);
306                                 tprints("}");
307                         }
308                 }
309                 if (rc < 0)
310                         tprints("{...}");
311         }
312 }
313
314 #define printitv(tcp, addr)     \
315         printitv_bitness((tcp), (addr), BITNESS_CURRENT)
316
317 int
318 sys_getitimer(struct tcb *tcp)
319 {
320         if (entering(tcp)) {
321                 printxval(itimer_which, tcp->u_arg[0], "ITIMER_???");
322                 tprints(", ");
323         } else {
324                 if (syserror(tcp))
325                         tprintf("%#lx", tcp->u_arg[1]);
326                 else
327                         printitv(tcp, tcp->u_arg[1]);
328         }
329         return 0;
330 }
331
332 #ifdef ALPHA
333 int
334 sys_osf_getitimer(struct tcb *tcp)
335 {
336         if (entering(tcp)) {
337                 printxval(itimer_which, tcp->u_arg[0], "ITIMER_???");
338                 tprints(", ");
339         } else {
340                 if (syserror(tcp))
341                         tprintf("%#lx", tcp->u_arg[1]);
342                 else
343                         printitv_bitness(tcp, tcp->u_arg[1], BITNESS_32);
344         }
345         return 0;
346 }
347 #endif
348
349 int
350 sys_setitimer(struct tcb *tcp)
351 {
352         if (entering(tcp)) {
353                 printxval(itimer_which, tcp->u_arg[0], "ITIMER_???");
354                 tprints(", ");
355                 printitv(tcp, tcp->u_arg[1]);
356                 tprints(", ");
357         } else {
358                 if (syserror(tcp))
359                         tprintf("%#lx", tcp->u_arg[2]);
360                 else
361                         printitv(tcp, tcp->u_arg[2]);
362         }
363         return 0;
364 }
365
366 #ifdef ALPHA
367 int
368 sys_osf_setitimer(struct tcb *tcp)
369 {
370         if (entering(tcp)) {
371                 printxval(itimer_which, tcp->u_arg[0], "ITIMER_???");
372                 tprints(", ");
373                 printitv_bitness(tcp, tcp->u_arg[1], BITNESS_32);
374                 tprints(", ");
375         } else {
376                 if (syserror(tcp))
377                         tprintf("%#lx", tcp->u_arg[2]);
378                 else
379                         printitv_bitness(tcp, tcp->u_arg[2], BITNESS_32);
380         }
381         return 0;
382 }
383 #endif
384
385 #include "xlat/adjtimex_modes.h"
386 #include "xlat/adjtimex_status.h"
387 #include "xlat/adjtimex_state.h"
388
389 #if SUPPORTED_PERSONALITIES > 1
390 static int
391 tprint_timex32(struct tcb *tcp, long addr)
392 {
393         struct {
394                 unsigned int modes;
395                 int     offset;
396                 int     freq;
397                 int     maxerror;
398                 int     esterror;
399                 int     status;
400                 int     constant;
401                 int     precision;
402                 int     tolerance;
403                 struct timeval32 time;
404                 int     tick;
405                 int     ppsfreq;
406                 int     jitter;
407                 int     shift;
408                 int     stabil;
409                 int     jitcnt;
410                 int     calcnt;
411                 int     errcnt;
412                 int     stbcnt;
413         } tx;
414
415         if (umove(tcp, addr, &tx) < 0)
416                 return -1;
417
418         tprints("{modes=");
419         printflags(adjtimex_modes, tx.modes, "ADJ_???");
420         tprintf(", offset=%d, freq=%d, maxerror=%d, ",
421                 tx.offset, tx.freq, tx.maxerror);
422         tprintf("esterror=%u, status=", tx.esterror);
423         printflags(adjtimex_status, tx.status, "STA_???");
424         tprintf(", constant=%d, precision=%u, ",
425                 tx.constant, tx.precision);
426         tprintf("tolerance=%d, time=", tx.tolerance);
427         tprint_timeval32(tcp, &tx.time);
428         tprintf(", tick=%d, ppsfreq=%d, jitter=%d",
429                 tx.tick, tx.ppsfreq, tx.jitter);
430         tprintf(", shift=%d, stabil=%d, jitcnt=%d",
431                 tx.shift, tx.stabil, tx.jitcnt);
432         tprintf(", calcnt=%d, errcnt=%d, stbcnt=%d",
433                 tx.calcnt, tx.errcnt, tx.stbcnt);
434         tprints("}");
435         return 0;
436 }
437 #endif /* SUPPORTED_PERSONALITIES > 1 */
438
439 static int
440 tprint_timex(struct tcb *tcp, long addr)
441 {
442         struct timex tx;
443
444 #if SUPPORTED_PERSONALITIES > 1
445         if (current_time_t_is_compat)
446                 return tprint_timex32(tcp, addr);
447 #endif
448         if (umove(tcp, addr, &tx) < 0)
449                 return -1;
450
451 #if LINUX_VERSION_CODE < 66332
452         tprintf("{mode=%d, offset=%ld, frequency=%ld, ",
453                 tx.mode, tx.offset, tx.frequency);
454         tprintf("maxerror=%ld, esterror=%lu, status=%u, ",
455                 tx.maxerror, tx.esterror, tx.status);
456         tprintf("time_constant=%ld, precision=%lu, ",
457                 tx.time_constant, tx.precision);
458         tprintf("tolerance=%ld, time=", tx.tolerance);
459         tprint_timeval(tcp, &tx.time);
460 #else
461         tprints("{modes=");
462         printflags(adjtimex_modes, tx.modes, "ADJ_???");
463         tprintf(", offset=%jd, freq=%jd, maxerror=%ju, esterror=%ju, status=",
464                 (intmax_t) tx.offset, (intmax_t) tx.freq,
465                 (uintmax_t) tx.maxerror, (uintmax_t) tx.esterror);
466         printflags(adjtimex_status, tx.status, "STA_???");
467         tprintf(", constant=%jd, precision=%ju, tolerance=%jd, time=",
468                 (intmax_t) tx.constant, (uintmax_t) tx.precision,
469                 (intmax_t) tx.tolerance);
470         tprint_timeval(tcp, &tx.time);
471         tprintf(", tick=%jd, ppsfreq=%jd, jitter=%jd",
472                 (intmax_t) tx.tick, (intmax_t) tx.ppsfreq, (intmax_t) tx.jitter);
473         tprintf(", shift=%d, stabil=%jd, jitcnt=%jd",
474                 tx.shift, (intmax_t) tx.stabil, (intmax_t) tx.jitcnt);
475         tprintf(", calcnt=%jd, errcnt=%jd, stbcnt=%jd",
476                 (intmax_t) tx.calcnt, (intmax_t) tx.errcnt, (intmax_t) tx.stbcnt);
477 #endif
478         tprints("}");
479         return 0;
480 }
481
482 static int
483 do_adjtimex(struct tcb *tcp, long addr)
484 {
485         if (addr == 0)
486                 tprints("NULL");
487         else if (syserror(tcp) || !verbose(tcp))
488                 tprintf("%#lx", addr);
489         else if (tprint_timex(tcp, addr) < 0)
490                 tprints("{...}");
491         if (syserror(tcp))
492                 return 0;
493         tcp->auxstr = xlookup(adjtimex_state, tcp->u_rval);
494         if (tcp->auxstr)
495                 return RVAL_STR;
496         return 0;
497 }
498
499 int
500 sys_adjtimex(struct tcb *tcp)
501 {
502         if (exiting(tcp))
503                 return do_adjtimex(tcp, tcp->u_arg[0]);
504         return 0;
505 }
506
507 #include "xlat/clockflags.h"
508 #include "xlat/clocknames.h"
509
510 static void
511 printclockname(int clockid)
512 {
513 #ifdef CLOCKID_TO_FD
514 # include "xlat/cpuclocknames.h"
515
516         if (clockid < 0) {
517                 if ((clockid & CLOCKFD_MASK) == CLOCKFD)
518                         tprintf("FD_TO_CLOCKID(%d)", CLOCKID_TO_FD(clockid));
519                 else {
520                         if(CPUCLOCK_PERTHREAD(clockid))
521                                 tprintf("MAKE_THREAD_CPUCLOCK(%d,", CPUCLOCK_PID(clockid));
522                         else
523                                 tprintf("MAKE_PROCESS_CPUCLOCK(%d,", CPUCLOCK_PID(clockid));
524                         printxval(cpuclocknames, clockid & CLOCKFD_MASK, "CPUCLOCK_???");
525                         tprints(")");
526                 }
527         }
528         else
529 #endif
530                 printxval(clocknames, clockid, "CLOCK_???");
531 }
532
533 int
534 sys_clock_settime(struct tcb *tcp)
535 {
536         if (entering(tcp)) {
537                 printclockname(tcp->u_arg[0]);
538                 tprints(", ");
539                 printtv(tcp, tcp->u_arg[1]);
540         }
541         return 0;
542 }
543
544 int
545 sys_clock_gettime(struct tcb *tcp)
546 {
547         if (entering(tcp)) {
548                 printclockname(tcp->u_arg[0]);
549                 tprints(", ");
550         } else {
551                 if (syserror(tcp))
552                         tprintf("%#lx", tcp->u_arg[1]);
553                 else
554                         printtv(tcp, tcp->u_arg[1]);
555         }
556         return 0;
557 }
558
559 int
560 sys_clock_nanosleep(struct tcb *tcp)
561 {
562         if (entering(tcp)) {
563                 printclockname(tcp->u_arg[0]);
564                 tprints(", ");
565                 printflags(clockflags, tcp->u_arg[1], "TIMER_???");
566                 tprints(", ");
567                 printtv(tcp, tcp->u_arg[2]);
568                 tprints(", ");
569         } else {
570                 if (syserror(tcp))
571                         tprintf("%#lx", tcp->u_arg[3]);
572                 else
573                         printtv(tcp, tcp->u_arg[3]);
574         }
575         return 0;
576 }
577
578 int
579 sys_clock_adjtime(struct tcb *tcp)
580 {
581         if (exiting(tcp))
582                 return do_adjtimex(tcp, tcp->u_arg[1]);
583         printclockname(tcp->u_arg[0]);
584         tprints(", ");
585         return 0;
586 }
587
588 #ifndef SIGEV_THREAD_ID
589 # define SIGEV_THREAD_ID 4
590 #endif
591 #include "xlat/sigev_value.h"
592
593 #if SUPPORTED_PERSONALITIES > 1
594 static void
595 printsigevent32(struct tcb *tcp, long arg)
596 {
597         struct {
598                 int     sigev_value;
599                 int     sigev_signo;
600                 int     sigev_notify;
601
602                 union {
603                         int     tid;
604                         struct {
605                                 int     function, attribute;
606                         } thread;
607                 } un;
608         } sev;
609
610         if (umove(tcp, arg, &sev) < 0)
611                 tprints("{...}");
612         else {
613                 tprintf("{%#x, ", sev.sigev_value);
614                 if (sev.sigev_notify == SIGEV_SIGNAL)
615                         tprintf("%s, ", signame(sev.sigev_signo));
616                 else
617                         tprintf("%u, ", sev.sigev_signo);
618                 printxval(sigev_value, sev.sigev_notify, "SIGEV_???");
619                 tprints(", ");
620                 if (sev.sigev_notify == SIGEV_THREAD_ID)
621                         tprintf("{%d}", sev.un.tid);
622                 else if (sev.sigev_notify == SIGEV_THREAD)
623                         tprintf("{%#x, %#x}",
624                                 sev.un.thread.function,
625                                 sev.un.thread.attribute);
626                 else
627                         tprints("{...}");
628                 tprints("}");
629         }
630 }
631 #endif
632
633 void
634 printsigevent(struct tcb *tcp, long arg)
635 {
636         struct sigevent sev;
637
638 #if SUPPORTED_PERSONALITIES > 1
639         if (current_wordsize == 4) {
640                 printsigevent32(tcp, arg);
641                 return;
642         }
643 #endif
644         if (umove(tcp, arg, &sev) < 0)
645                 tprints("{...}");
646         else {
647                 tprintf("{%p, ", sev.sigev_value.sival_ptr);
648                 if (sev.sigev_notify == SIGEV_SIGNAL)
649                         tprintf("%s, ", signame(sev.sigev_signo));
650                 else
651                         tprintf("%u, ", sev.sigev_signo);
652                 printxval(sigev_value, sev.sigev_notify, "SIGEV_???");
653                 tprints(", ");
654                 if (sev.sigev_notify == SIGEV_THREAD_ID)
655 #if defined(HAVE_STRUCT_SIGEVENT__SIGEV_UN__PAD)
656                         /* _pad[0] is the _tid field which might not be
657                            present in the userlevel definition of the
658                            struct.  */
659                         tprintf("{%d}", sev._sigev_un._pad[0]);
660 #elif defined(HAVE_STRUCT_SIGEVENT___PAD)
661                         tprintf("{%d}", sev.__pad[0]);
662 #else
663 # warning unfamiliar struct sigevent => incomplete SIGEV_THREAD_ID decoding
664                         tprints("{...}");
665 #endif
666                 else if (sev.sigev_notify == SIGEV_THREAD)
667                         tprintf("{%p, %p}", sev.sigev_notify_function,
668                                 sev.sigev_notify_attributes);
669                 else
670                         tprints("{...}");
671                 tprints("}");
672         }
673 }
674
675 int
676 sys_timer_create(struct tcb *tcp)
677 {
678         if (entering(tcp)) {
679                 printclockname(tcp->u_arg[0]);
680                 tprints(", ");
681                 printsigevent(tcp, tcp->u_arg[1]);
682                 tprints(", ");
683         } else {
684                 int timer_id;
685
686                 if (syserror(tcp) || umove(tcp, tcp->u_arg[2], &timer_id) < 0)
687                         tprintf("%#lx", tcp->u_arg[2]);
688                 else
689                         tprintf("{%d}", timer_id);
690         }
691         return 0;
692 }
693
694 int
695 sys_timer_settime(struct tcb *tcp)
696 {
697         if (entering(tcp)) {
698                 tprintf("%#lx, ", tcp->u_arg[0]);
699                 printflags(clockflags, tcp->u_arg[1], "TIMER_???");
700                 tprints(", ");
701                 printitv(tcp, tcp->u_arg[2]);
702                 tprints(", ");
703         } else {
704                 if (syserror(tcp))
705                         tprintf("%#lx", tcp->u_arg[3]);
706                 else
707                         printitv(tcp, tcp->u_arg[3]);
708         }
709         return 0;
710 }
711
712 int
713 sys_timer_gettime(struct tcb *tcp)
714 {
715         if (entering(tcp)) {
716                 tprintf("%#lx, ", tcp->u_arg[0]);
717         } else {
718                 if (syserror(tcp))
719                         tprintf("%#lx", tcp->u_arg[1]);
720                 else
721                         printitv(tcp, tcp->u_arg[1]);
722         }
723         return 0;
724 }
725
726 static void
727 print_rtc(struct tcb *tcp, const struct rtc_time *rt)
728 {
729         tprintf("{tm_sec=%d, tm_min=%d, tm_hour=%d, "
730                 "tm_mday=%d, tm_mon=%d, tm_year=%d, ",
731                 rt->tm_sec, rt->tm_min, rt->tm_hour,
732                 rt->tm_mday, rt->tm_mon, rt->tm_year);
733         if (!abbrev(tcp))
734                 tprintf("tm_wday=%d, tm_yday=%d, tm_isdst=%d}",
735                         rt->tm_wday, rt->tm_yday, rt->tm_isdst);
736         else
737                 tprints("...}");
738 }
739
740 int
741 rtc_ioctl(struct tcb *tcp, const unsigned int code, long arg)
742 {
743         switch (code) {
744         case RTC_ALM_SET:
745         case RTC_SET_TIME:
746                 if (entering(tcp)) {
747                         struct rtc_time rt;
748                         if (umove(tcp, arg, &rt) < 0)
749                                 tprintf(", %#lx", arg);
750                         else {
751                                 tprints(", ");
752                                 print_rtc(tcp, &rt);
753                         }
754                 }
755                 break;
756         case RTC_ALM_READ:
757         case RTC_RD_TIME:
758                 if (exiting(tcp)) {
759                         struct rtc_time rt;
760                         if (syserror(tcp) || umove(tcp, arg, &rt) < 0)
761                                 tprintf(", %#lx", arg);
762                         else {
763                                 tprints(", ");
764                                 print_rtc(tcp, &rt);
765                         }
766                 }
767                 break;
768         case RTC_IRQP_SET:
769         case RTC_EPOCH_SET:
770                 if (entering(tcp))
771                         tprintf(", %lu", arg);
772                 break;
773         case RTC_IRQP_READ:
774         case RTC_EPOCH_READ:
775                 if (exiting(tcp))
776                         tprintf(", %lu", arg);
777                 break;
778         case RTC_WKALM_SET:
779                 if (entering(tcp)) {
780                         struct rtc_wkalrm wk;
781                         if (umove(tcp, arg, &wk) < 0)
782                                 tprintf(", %#lx", arg);
783                         else {
784                                 tprintf(", {enabled=%d, pending=%d, ",
785                                         wk.enabled, wk.pending);
786                                 print_rtc(tcp, &wk.time);
787                                 tprints("}");
788                         }
789                 }
790                 break;
791         case RTC_WKALM_RD:
792                 if (exiting(tcp)) {
793                         struct rtc_wkalrm wk;
794                         if (syserror(tcp) || umove(tcp, arg, &wk) < 0)
795                                 tprintf(", %#lx", arg);
796                         else {
797                                 tprintf(", {enabled=%d, pending=%d, ",
798                                         wk.enabled, wk.pending);
799                                 print_rtc(tcp, &wk.time);
800                                 tprints("}");
801                         }
802                 }
803                 break;
804         default:
805                 if (entering(tcp))
806                         tprintf(", %#lx", arg);
807                 break;
808         }
809         return 1;
810 }
811
812 #include "xlat/timerfdflags.h"
813
814 int
815 sys_timerfd(struct tcb *tcp)
816 {
817         if (entering(tcp)) {
818                 /* It does not matter that the kernel uses itimerspec.  */
819                 tprintf("%ld, ", tcp->u_arg[0]);
820                 printclockname(tcp->u_arg[0]);
821                 tprints(", ");
822                 printflags(timerfdflags, tcp->u_arg[2], "TFD_???");
823                 tprints(", ");
824                 printitv(tcp, tcp->u_arg[3]);
825         }
826         return 0;
827 }
828
829 int
830 sys_timerfd_create(struct tcb *tcp)
831 {
832         if (entering(tcp)) {
833                 printclockname(tcp->u_arg[0]);
834                 tprints(", ");
835                 printflags(timerfdflags, tcp->u_arg[1], "TFD_???");
836         }
837         return 0;
838 }
839
840 int
841 sys_timerfd_settime(struct tcb *tcp)
842 {
843         if (entering(tcp)) {
844                 printfd(tcp, tcp->u_arg[0]);
845                 tprints(", ");
846                 printflags(timerfdflags, tcp->u_arg[1], "TFD_???");
847                 tprints(", ");
848                 printitv(tcp, tcp->u_arg[2]);
849                 tprints(", ");
850                 printitv(tcp, tcp->u_arg[3]);
851         }
852         return 0;
853 }
854
855 int
856 sys_timerfd_gettime(struct tcb *tcp)
857 {
858         if (entering(tcp)) {
859                 printfd(tcp, tcp->u_arg[0]);
860                 tprints(", ");
861                 printitv(tcp, tcp->u_arg[1]);
862         }
863         return 0;
864 }