]> granicus.if.org Git - strace/blob - time.c
Add experimental code to use PTRACE_SEIZE, disabled by default
[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  *      $Id$
30  */
31
32 #include "defs.h"
33
34 #ifdef LINUX
35 #include <linux/version.h>
36 #include <sys/timex.h>
37 #include <linux/ioctl.h>
38 #include <linux/rtc.h>
39
40 #ifndef UTIME_NOW
41 #define UTIME_NOW ((1l << 30) - 1l)
42 #endif
43 #ifndef UTIME_OMIT
44 #define UTIME_OMIT ((1l << 30) - 2l)
45 #endif
46 #endif /* LINUX */
47
48 struct timeval32
49 {
50         u_int32_t tv_sec, tv_usec;
51 };
52
53 static void
54 tprint_timeval32(struct tcb *tcp, const struct timeval32 *tv)
55 {
56         tprintf("{%u, %u}", tv->tv_sec, tv->tv_usec);
57 }
58
59 static void
60 tprint_timeval(struct tcb *tcp, const struct timeval *tv)
61 {
62         tprintf("{%lu, %lu}",
63                 (unsigned long) tv->tv_sec, (unsigned long) tv->tv_usec);
64 }
65
66 void
67 printtv_bitness(struct tcb *tcp, long addr, enum bitness_t bitness, int special)
68 {
69         char buf[TIMEVAL_TEXT_BUFSIZE];
70         sprinttv(buf, tcp, addr, bitness, special);
71         tprints(buf);
72 }
73
74 char *
75 sprinttv(char *buf, struct tcb *tcp, long addr, enum bitness_t bitness, int special)
76 {
77         int rc;
78
79         if (addr == 0)
80                 return stpcpy(buf, "NULL");
81
82         if (!verbose(tcp))
83                 return buf + sprintf(buf, "%#lx", addr);
84
85         if (bitness == BITNESS_32
86 #if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
87             || personality_wordsize[current_personality] == 4
88 #endif
89                 )
90         {
91                 struct timeval32 tv;
92
93                 rc = umove(tcp, addr, &tv);
94                 if (rc >= 0) {
95                         if (special && tv.tv_sec == 0) {
96                                 if (tv.tv_usec == UTIME_NOW)
97                                         return stpcpy(buf, "UTIME_NOW");
98                                 if (tv.tv_usec == UTIME_OMIT)
99                                         return stpcpy(buf, "UTIME_OMIT");
100                         }
101                         return buf + sprintf(buf, "{%u, %u}",
102                                 tv.tv_sec, tv.tv_usec);
103                 }
104         } else {
105                 struct timeval tv;
106
107                 rc = umove(tcp, addr, &tv);
108                 if (rc >= 0) {
109                         if (special && tv.tv_sec == 0) {
110                                 if (tv.tv_usec == UTIME_NOW)
111                                         return stpcpy(buf, "UTIME_NOW");
112                                 if (tv.tv_usec == UTIME_OMIT)
113                                         return stpcpy(buf, "UTIME_OMIT");
114                         }
115                         return buf + sprintf(buf, "{%lu, %lu}",
116                                 (unsigned long) tv.tv_sec,
117                                 (unsigned long) tv.tv_usec);
118                 }
119         }
120
121         return stpcpy(buf, "{...}");
122 }
123
124 void
125 print_timespec(struct tcb *tcp, long addr)
126 {
127         char buf[TIMESPEC_TEXT_BUFSIZE];
128         sprint_timespec(buf, tcp, addr);
129         tprints(buf);
130 }
131
132 void
133 sprint_timespec(char *buf, struct tcb *tcp, long addr)
134 {
135         if (addr == 0)
136                 strcpy(buf, "NULL");
137         else if (!verbose(tcp))
138                 sprintf(buf, "%#lx", addr);
139         else {
140                 int rc;
141
142 #if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
143                 if (personality_wordsize[current_personality] == 4) {
144                         struct timeval32 tv;
145
146                         rc = umove(tcp, addr, &tv);
147                         if (rc >= 0)
148                                 sprintf(buf, "{%u, %u}",
149                                         tv.tv_sec, tv.tv_usec);
150                 } else
151 #endif
152                 {
153                         struct timespec ts;
154
155                         rc = umove(tcp, addr, &ts);
156                         if (rc >= 0)
157                                 sprintf(buf, "{%lu, %lu}",
158                                         (unsigned long) ts.tv_sec,
159                                         (unsigned long) ts.tv_nsec);
160                 }
161                 if (rc < 0)
162                         strcpy(buf, "{...}");
163         }
164 }
165
166 int
167 sys_time(struct tcb *tcp)
168 {
169         if (exiting(tcp)) {
170 #ifndef SVR4
171                 printnum(tcp, tcp->u_arg[0], "%ld");
172 #endif /* SVR4 */
173         }
174         return 0;
175 }
176
177 int
178 sys_stime(struct tcb *tcp)
179 {
180         if (exiting(tcp)) {
181                 printnum(tcp, tcp->u_arg[0], "%ld");
182         }
183         return 0;
184 }
185
186 int
187 sys_gettimeofday(struct tcb *tcp)
188 {
189         if (exiting(tcp)) {
190                 if (syserror(tcp)) {
191                         tprintf("%#lx, %#lx",
192                                 tcp->u_arg[0], tcp->u_arg[1]);
193                         return 0;
194                 }
195                 printtv(tcp, tcp->u_arg[0]);
196 #ifndef SVR4
197                 tprints(", ");
198                 printtv(tcp, tcp->u_arg[1]);
199 #endif /* !SVR4 */
200         }
201         return 0;
202 }
203
204
205 #ifdef ALPHA
206 int
207 sys_osf_gettimeofday(struct tcb *tcp)
208 {
209         if (exiting(tcp)) {
210                 if (syserror(tcp)) {
211                         tprintf("%#lx, %#lx", tcp->u_arg[0], tcp->u_arg[1]);
212                         return 0;
213                 }
214                 printtv_bitness(tcp, tcp->u_arg[0], BITNESS_32, 0);
215 #ifndef SVR4
216                 tprints(", ");
217                 printtv_bitness(tcp, tcp->u_arg[1], BITNESS_32, 0);
218 #endif /* !SVR4 */
219         }
220         return 0;
221 }
222 #endif
223
224 int
225 sys_settimeofday(struct tcb *tcp)
226 {
227         if (entering(tcp)) {
228                 printtv(tcp, tcp->u_arg[0]);
229 #ifndef SVR4
230                 tprints(", ");
231                 printtv(tcp, tcp->u_arg[1]);
232 #endif /* !SVR4 */
233         }
234         return 0;
235 }
236
237 #ifdef ALPHA
238 int
239 sys_osf_settimeofday(struct tcb *tcp)
240 {
241         if (entering(tcp)) {
242                 printtv_bitness(tcp, tcp->u_arg[0], BITNESS_32, 0);
243 #ifndef SVR4
244                 tprints(", ");
245                 printtv_bitness(tcp, tcp->u_arg[1], BITNESS_32, 0);
246 #endif /* !SVR4 */
247         }
248         return 0;
249 }
250 #endif
251
252 int
253 sys_adjtime(struct tcb *tcp)
254 {
255         if (entering(tcp)) {
256                 printtv(tcp, tcp->u_arg[0]);
257                 tprints(", ");
258         } else {
259                 if (syserror(tcp))
260                         tprintf("%#lx", tcp->u_arg[1]);
261                 else
262                         printtv(tcp, tcp->u_arg[1]);
263         }
264         return 0;
265 }
266
267 int
268 sys_nanosleep(struct tcb *tcp)
269 {
270         if (entering(tcp)) {
271                 print_timespec(tcp, tcp->u_arg[0]);
272                 tprints(", ");
273         } else {
274                 /* Second (returned) timespec is only significant
275                  * if syscall was interrupted. We print only its address
276                  * on _success_, since kernel doesn't modify its value.
277                  */
278                 if (is_restart_error(tcp) || !tcp->u_arg[1])
279                         /* Interrupted (or NULL) */
280                         print_timespec(tcp, tcp->u_arg[1]);
281                 else
282                         /* Success */
283                         tprintf("%#lx", tcp->u_arg[1]);
284         }
285         return 0;
286 }
287
288 static const struct xlat which[] = {
289         { ITIMER_REAL,  "ITIMER_REAL"   },
290         { ITIMER_VIRTUAL,"ITIMER_VIRTUAL"},
291         { ITIMER_PROF,  "ITIMER_PROF"   },
292         { 0,            NULL            },
293 };
294
295 static void
296 printitv_bitness(struct tcb *tcp, long addr, enum bitness_t bitness)
297 {
298         if (addr == 0)
299                 tprints("NULL");
300         else if (!verbose(tcp))
301                 tprintf("%#lx", addr);
302         else {
303                 int rc;
304
305                 if (bitness == BITNESS_32
306 #if defined(LINUX) && SUPPORTED_PERSONALITIES > 1
307                     || personality_wordsize[current_personality] == 4
308 #endif
309                         )
310                 {
311                         struct {
312                                 struct timeval32 it_interval, it_value;
313                         } itv;
314
315                         rc = umove(tcp, addr, &itv);
316                         if (rc >= 0) {
317                                 tprints("{it_interval=");
318                                 tprint_timeval32(tcp, &itv.it_interval);
319                                 tprints(", it_value=");
320                                 tprint_timeval32(tcp, &itv.it_value);
321                                 tprints("}");
322                         }
323                 } else {
324                         struct itimerval itv;
325
326                         rc = umove(tcp, addr, &itv);
327                         if (rc >= 0) {
328                                 tprints("{it_interval=");
329                                 tprint_timeval(tcp, &itv.it_interval);
330                                 tprints(", it_value=");
331                                 tprint_timeval(tcp, &itv.it_value);
332                                 tprints("}");
333                         }
334                 }
335                 if (rc < 0)
336                         tprints("{...}");
337         }
338 }
339
340 #define printitv(tcp, addr)     \
341         printitv_bitness((tcp), (addr), BITNESS_CURRENT)
342
343 int
344 sys_getitimer(struct tcb *tcp)
345 {
346         if (entering(tcp)) {
347                 printxval(which, tcp->u_arg[0], "ITIMER_???");
348                 tprints(", ");
349         } else {
350                 if (syserror(tcp))
351                         tprintf("%#lx", tcp->u_arg[1]);
352                 else
353                         printitv(tcp, tcp->u_arg[1]);
354         }
355         return 0;
356 }
357
358
359 #ifdef ALPHA
360 int
361 sys_osf_getitimer(struct tcb *tcp)
362 {
363         if (entering(tcp)) {
364                 printxval(which, tcp->u_arg[0], "ITIMER_???");
365                 tprints(", ");
366         } else {
367                 if (syserror(tcp))
368                         tprintf("%#lx", tcp->u_arg[1]);
369                 else
370                         printitv_bitness(tcp, tcp->u_arg[1], BITNESS_32);
371         }
372         return 0;
373 }
374 #endif
375
376 int
377 sys_setitimer(struct tcb *tcp)
378 {
379         if (entering(tcp)) {
380                 printxval(which, tcp->u_arg[0], "ITIMER_???");
381                 tprints(", ");
382                 printitv(tcp, tcp->u_arg[1]);
383                 tprints(", ");
384         } else {
385                 if (syserror(tcp))
386                         tprintf("%#lx", tcp->u_arg[2]);
387                 else
388                         printitv(tcp, tcp->u_arg[2]);
389         }
390         return 0;
391 }
392
393 #ifdef ALPHA
394 int
395 sys_osf_setitimer(struct tcb *tcp)
396 {
397         if (entering(tcp)) {
398                 printxval(which, tcp->u_arg[0], "ITIMER_???");
399                 tprints(", ");
400                 printitv_bitness(tcp, tcp->u_arg[1], BITNESS_32);
401                 tprints(", ");
402         } else {
403                 if (syserror(tcp))
404                         tprintf("%#lx", tcp->u_arg[2]);
405                 else
406                         printitv_bitness(tcp, tcp->u_arg[2], BITNESS_32);
407         }
408         return 0;
409 }
410 #endif
411
412 #ifdef LINUX
413
414 static const struct xlat adjtimex_modes[] = {
415   { 0, "0" },
416 #ifdef ADJ_OFFSET
417   { ADJ_OFFSET, "ADJ_OFFSET" },
418 #endif
419 #ifdef ADJ_FREQUENCY
420   { ADJ_FREQUENCY, "ADJ_FREQUENCY" },
421 #endif
422 #ifdef ADJ_MAXERROR
423   { ADJ_MAXERROR, "ADJ_MAXERROR" },
424 #endif
425 #ifdef ADJ_ESTERROR
426   { ADJ_ESTERROR, "ADJ_ESTERROR" },
427 #endif
428 #ifdef ADJ_STATUS
429   { ADJ_STATUS, "ADJ_STATUS" },
430 #endif
431 #ifdef ADJ_TIMECONST
432   { ADJ_TIMECONST, "ADJ_TIMECONST" },
433 #endif
434 #ifdef ADJ_TICK
435   { ADJ_TICK, "ADJ_TICK" },
436 #endif
437 #ifdef ADJ_OFFSET_SINGLESHOT
438   { ADJ_OFFSET_SINGLESHOT, "ADJ_OFFSET_SINGLESHOT" },
439 #endif
440   { 0,             NULL }
441 };
442
443 static const struct xlat adjtimex_status[] = {
444 #ifdef STA_PLL
445   { STA_PLL, "STA_PLL" },
446 #endif
447 #ifdef STA_PPSFREQ
448   { STA_PPSFREQ, "STA_PPSFREQ" },
449 #endif
450 #ifdef STA_PPSTIME
451   { STA_PPSTIME, "STA_PPSTIME" },
452 #endif
453 #ifdef STA_FLL
454   { STA_FLL, "STA_FLL" },
455 #endif
456 #ifdef STA_INS
457   { STA_INS, "STA_INS" },
458 #endif
459 #ifdef STA_DEL
460   { STA_DEL, "STA_DEL" },
461 #endif
462 #ifdef STA_UNSYNC
463   { STA_UNSYNC, "STA_UNSYNC" },
464 #endif
465 #ifdef STA_FREQHOLD
466   { STA_FREQHOLD, "STA_FREQHOLD" },
467 #endif
468 #ifdef STA_PPSSIGNAL
469   { STA_PPSSIGNAL, "STA_PPSSIGNAL" },
470 #endif
471 #ifdef STA_PPSJITTER
472   { STA_PPSJITTER, "STA_PPSJITTER" },
473 #endif
474 #ifdef STA_PPSWANDER
475   { STA_PPSWANDER, "STA_PPSWANDER" },
476 #endif
477 #ifdef STA_PPSERROR
478   { STA_PPSERROR, "STA_PPSERROR" },
479 #endif
480 #ifdef STA_CLOCKERR
481   { STA_CLOCKERR, "STA_CLOCKERR" },
482 #endif
483   { 0,             NULL }
484 };
485
486 static const struct xlat adjtimex_state[] = {
487 #ifdef TIME_OK
488   { TIME_OK, "TIME_OK" },
489 #endif
490 #ifdef TIME_INS
491   { TIME_INS, "TIME_INS" },
492 #endif
493 #ifdef TIME_DEL
494   { TIME_DEL, "TIME_DEL" },
495 #endif
496 #ifdef TIME_OOP
497   { TIME_OOP, "TIME_OOP" },
498 #endif
499 #ifdef TIME_WAIT
500   { TIME_WAIT, "TIME_WAIT" },
501 #endif
502 #ifdef TIME_ERROR
503   { TIME_ERROR, "TIME_ERROR" },
504 #endif
505   { 0,             NULL }
506 };
507
508 #if SUPPORTED_PERSONALITIES > 1
509 static int
510 tprint_timex32(struct tcb *tcp, long addr)
511 {
512         struct {
513                 unsigned int modes;
514                 int     offset;
515                 int     freq;
516                 int     maxerror;
517                 int     esterror;
518                 int     status;
519                 int     constant;
520                 int     precision;
521                 int     tolerance;
522                 struct timeval32 time;
523                 int     tick;
524                 int     ppsfreq;
525                 int     jitter;
526                 int     shift;
527                 int     stabil;
528                 int     jitcnt;
529                 int     calcnt;
530                 int     errcnt;
531                 int     stbcnt;
532         } tx;
533
534         if (umove(tcp, addr, &tx) < 0)
535                 return -1;
536
537         tprints("{modes=");
538         printflags(adjtimex_modes, tx.modes, "ADJ_???");
539         tprintf(", offset=%d, freq=%d, maxerror=%d, ",
540                 tx.offset, tx.freq, tx.maxerror);
541         tprintf("esterror=%u, status=", tx.esterror);
542         printflags(adjtimex_status, tx.status, "STA_???");
543         tprintf(", constant=%d, precision=%u, ",
544                 tx.constant, tx.precision);
545         tprintf("tolerance=%d, time=", tx.tolerance);
546         tprint_timeval32(tcp, &tx.time);
547         tprintf(", tick=%d, ppsfreq=%d, jitter=%d",
548                 tx.tick, tx.ppsfreq, tx.jitter);
549         tprintf(", shift=%d, stabil=%d, jitcnt=%d",
550                 tx.shift, tx.stabil, tx.jitcnt);
551         tprintf(", calcnt=%d, errcnt=%d, stbcnt=%d",
552                 tx.calcnt, tx.errcnt, tx.stbcnt);
553         tprints("}");
554         return 0;
555 }
556 #endif /* SUPPORTED_PERSONALITIES > 1 */
557
558 static int
559 tprint_timex(struct tcb *tcp, long addr)
560 {
561         struct timex tx;
562
563 #if SUPPORTED_PERSONALITIES > 1
564         if (personality_wordsize[current_personality] == 4)
565                 return tprint_timex32(tcp, addr);
566 #endif
567         if (umove(tcp, addr, &tx) < 0)
568                 return -1;
569
570 #if LINUX_VERSION_CODE < 66332
571         tprintf("{mode=%d, offset=%ld, frequency=%ld, ",
572                 tx.mode, tx.offset, tx.frequency);
573         tprintf("maxerror=%ld, esterror=%lu, status=%u, ",
574                 tx.maxerror, tx.esterror, tx.status);
575         tprintf("time_constant=%ld, precision=%lu, ",
576                 tx.time_constant, tx.precision);
577         tprintf("tolerance=%ld, time=", tx.tolerance);
578         tprint_timeval(tcp, &tx.time);
579 #else
580         tprints("{modes=");
581         printflags(adjtimex_modes, tx.modes, "ADJ_???");
582         tprintf(", offset=%ld, freq=%ld, maxerror=%ld, ",
583                 tx.offset, tx.freq, tx.maxerror);
584         tprintf("esterror=%lu, status=", tx.esterror);
585         printflags(adjtimex_status, tx.status, "STA_???");
586         tprintf(", constant=%ld, precision=%lu, ",
587                 tx.constant, tx.precision);
588         tprintf("tolerance=%ld, time=", tx.tolerance);
589         tprint_timeval(tcp, &tx.time);
590         tprintf(", tick=%ld, ppsfreq=%ld, jitter=%ld",
591                 tx.tick, tx.ppsfreq, tx.jitter);
592         tprintf(", shift=%d, stabil=%ld, jitcnt=%ld",
593                 tx.shift, tx.stabil, tx.jitcnt);
594         tprintf(", calcnt=%ld, errcnt=%ld, stbcnt=%ld",
595                 tx.calcnt, tx.errcnt, tx.stbcnt);
596 #endif
597         tprints("}");
598         return 0;
599 }
600
601 int
602 sys_adjtimex(struct tcb *tcp)
603 {
604         if (exiting(tcp)) {
605                 if (tcp->u_arg[0] == 0)
606                         tprints("NULL");
607                 else if (syserror(tcp) || !verbose(tcp))
608                         tprintf("%#lx", tcp->u_arg[0]);
609                 else if (tprint_timex(tcp, tcp->u_arg[0]) < 0)
610                         tprints("{...}");
611                 if (syserror(tcp))
612                         return 0;
613                 tcp->auxstr = xlookup(adjtimex_state, tcp->u_rval);
614                 if (tcp->auxstr)
615                         return RVAL_STR;
616         }
617         return 0;
618 }
619
620 static const struct xlat clockflags[] = {
621   { TIMER_ABSTIME, "TIMER_ABSTIME" },
622   { 0,             NULL }
623 };
624
625 static const struct xlat clocknames[] = {
626 #ifdef CLOCK_REALTIME
627   { CLOCK_REALTIME, "CLOCK_REALTIME" },
628 #endif
629 #ifdef CLOCK_MONOTONIC
630   { CLOCK_MONOTONIC, "CLOCK_MONOTONIC" },
631 #endif
632 #ifdef CLOCK_PROCESS_CPUTIME_ID
633   { CLOCK_PROCESS_CPUTIME_ID, "CLOCK_PROCESS_CPUTIME_ID" },
634 #endif
635 #ifdef CLOCK_THREAD_CPUTIME_ID
636   { CLOCK_THREAD_CPUTIME_ID, "CLOCK_THREAD_CPUTIME_ID" },
637 #endif
638 #ifdef CLOCK_MONOTONIC_RAW
639   { CLOCK_MONOTONIC_RAW, "CLOCK_MONOTONIC_RAW" },
640 #endif
641 #ifdef CLOCK_REALTIME_COARSE
642   { CLOCK_REALTIME_COARSE, "CLOCK_REALTIME_COARSE" },
643 #endif
644 #ifdef CLOCK_MONOTONIC_COARSE
645   { CLOCK_MONOTONIC_COARSE, "CLOCK_MONOTONIC_COARSE" },
646 #endif
647   { 0, NULL }
648 };
649
650 int
651 sys_clock_settime(struct tcb *tcp)
652 {
653         if (entering(tcp)) {
654                 printxval(clocknames, tcp->u_arg[0], "CLOCK_???");
655                 tprints(", ");
656                 printtv(tcp, tcp->u_arg[1]);
657         }
658         return 0;
659 }
660
661 int
662 sys_clock_gettime(struct tcb *tcp)
663 {
664         if (entering(tcp)) {
665                 printxval(clocknames, tcp->u_arg[0], "CLOCK_???");
666                 tprints(", ");
667         } else {
668                 if (syserror(tcp))
669                         tprintf("%#lx", tcp->u_arg[1]);
670                 else
671                         printtv(tcp, tcp->u_arg[1]);
672         }
673         return 0;
674 }
675
676 int
677 sys_clock_nanosleep(struct tcb *tcp)
678 {
679         if (entering(tcp)) {
680                 printxval(clocknames, tcp->u_arg[0], "CLOCK_???");
681                 tprints(", ");
682                 printflags(clockflags, tcp->u_arg[1], "TIMER_???");
683                 tprints(", ");
684                 printtv(tcp, tcp->u_arg[2]);
685                 tprints(", ");
686         } else {
687                 if (syserror(tcp))
688                         tprintf("%#lx", tcp->u_arg[3]);
689                 else
690                         printtv(tcp, tcp->u_arg[3]);
691         }
692         return 0;
693 }
694
695 #ifndef SIGEV_THREAD_ID
696 # define SIGEV_THREAD_ID 4
697 #endif
698 static const struct xlat sigev_value[] = {
699         { SIGEV_SIGNAL+1, "SIGEV_SIGNAL" },
700         { SIGEV_NONE+1, "SIGEV_NONE" },
701         { SIGEV_THREAD+1, "SIGEV_THREAD" },
702         { SIGEV_THREAD_ID+1, "SIGEV_THREAD_ID" },
703         { 0, NULL }
704 };
705
706 #if SUPPORTED_PERSONALITIES > 1
707 static void
708 printsigevent32(struct tcb *tcp, long arg)
709 {
710         struct {
711                 int     sigev_value;
712                 int     sigev_signo;
713                 int     sigev_notify;
714
715                 union {
716                         int     tid;
717                         struct {
718                                 int     function, attribute;
719                         } thread;
720                 } un;
721         } sev;
722
723         if (umove(tcp, arg, &sev) < 0)
724                 tprints("{...}");
725         else {
726                 tprintf("{%#x, ", sev.sigev_value);
727                 if (sev.sigev_notify == SIGEV_SIGNAL)
728                         tprintf("%s, ", signame(sev.sigev_signo));
729                 else
730                         tprintf("%u, ", sev.sigev_signo);
731                 printxval(sigev_value, sev.sigev_notify + 1, "SIGEV_???");
732                 tprints(", ");
733                 if (sev.sigev_notify == SIGEV_THREAD_ID)
734                         tprintf("{%d}", sev.un.tid);
735                 else if (sev.sigev_notify == SIGEV_THREAD)
736                         tprintf("{%#x, %#x}",
737                                 sev.un.thread.function,
738                                 sev.un.thread.attribute);
739                 else
740                         tprints("{...}");
741                 tprints("}");
742         }
743 }
744 #endif
745
746 void
747 printsigevent(struct tcb *tcp, long arg)
748 {
749         struct sigevent sev;
750
751 #if SUPPORTED_PERSONALITIES > 1
752         if (personality_wordsize[current_personality] == 4) {
753                 printsigevent32(tcp, arg);
754                 return;
755         }
756 #endif
757         if (umove(tcp, arg, &sev) < 0)
758                 tprints("{...}");
759         else {
760                 tprintf("{%p, ", sev.sigev_value.sival_ptr);
761                 if (sev.sigev_notify == SIGEV_SIGNAL)
762                         tprintf("%s, ", signame(sev.sigev_signo));
763                 else
764                         tprintf("%u, ", sev.sigev_signo);
765                 printxval(sigev_value, sev.sigev_notify+1, "SIGEV_???");
766                 tprints(", ");
767                 if (sev.sigev_notify == SIGEV_THREAD_ID)
768                         /* _pad[0] is the _tid field which might not be
769                            present in the userlevel definition of the
770                            struct.  */
771                         tprintf("{%d}", sev._sigev_un._pad[0]);
772                 else if (sev.sigev_notify == SIGEV_THREAD)
773                         tprintf("{%p, %p}", sev.sigev_notify_function,
774                                 sev.sigev_notify_attributes);
775                 else
776                         tprints("{...}");
777                 tprints("}");
778         }
779 }
780
781 int
782 sys_timer_create(struct tcb *tcp)
783 {
784         if (entering(tcp)) {
785                 printxval(clocknames, tcp->u_arg[0], "CLOCK_???");
786                 tprints(", ");
787                 printsigevent(tcp, tcp->u_arg[1]);
788                 tprints(", ");
789         } else {
790                 int timer_id;
791
792                 if (syserror(tcp) || umove(tcp, tcp->u_arg[2], &timer_id) < 0)
793                         tprintf("%#lx", tcp->u_arg[2]);
794                 else
795                         tprintf("{%d}", timer_id);
796         }
797         return 0;
798 }
799
800 int
801 sys_timer_settime(struct tcb *tcp)
802 {
803         if (entering(tcp)) {
804                 tprintf("%#lx, ", tcp->u_arg[0]);
805                 printflags(clockflags, tcp->u_arg[1], "TIMER_???");
806                 tprints(", ");
807                 printitv(tcp, tcp->u_arg[2]);
808                 tprints(", ");
809         } else {
810                 if (syserror(tcp))
811                         tprintf("%#lx", tcp->u_arg[3]);
812                 else
813                         printitv(tcp, tcp->u_arg[3]);
814         }
815         return 0;
816 }
817
818 int
819 sys_timer_gettime(struct tcb *tcp)
820 {
821         if (entering(tcp)) {
822                 tprintf("%#lx, ", tcp->u_arg[0]);
823         } else {
824                 if (syserror(tcp))
825                         tprintf("%#lx", tcp->u_arg[1]);
826                 else
827                         printitv(tcp, tcp->u_arg[1]);
828         }
829         return 0;
830 }
831
832 static void
833 print_rtc(struct tcb *tcp, const struct rtc_time *rt)
834 {
835         tprintf("{tm_sec=%d, tm_min=%d, tm_hour=%d, "
836                 "tm_mday=%d, tm_mon=%d, tm_year=%d, ",
837                 rt->tm_sec, rt->tm_min, rt->tm_hour,
838                 rt->tm_mday, rt->tm_mon, rt->tm_year);
839         if (!abbrev(tcp))
840                 tprintf("tm_wday=%d, tm_yday=%d, tm_isdst=%d}",
841                         rt->tm_wday, rt->tm_yday, rt->tm_isdst);
842         else
843                 tprints("...}");
844 }
845
846 int
847 rtc_ioctl(struct tcb *tcp, long code, long arg)
848 {
849         switch (code) {
850         case RTC_ALM_SET:
851         case RTC_SET_TIME:
852                 if (entering(tcp)) {
853                         struct rtc_time rt;
854                         if (umove(tcp, arg, &rt) < 0)
855                                 tprintf(", %#lx", arg);
856                         else {
857                                 tprints(", ");
858                                 print_rtc(tcp, &rt);
859                         }
860                 }
861                 break;
862         case RTC_ALM_READ:
863         case RTC_RD_TIME:
864                 if (exiting(tcp)) {
865                         struct rtc_time rt;
866                         if (syserror(tcp) || umove(tcp, arg, &rt) < 0)
867                                 tprintf(", %#lx", arg);
868                         else {
869                                 tprints(", ");
870                                 print_rtc(tcp, &rt);
871                         }
872                 }
873                 break;
874         case RTC_IRQP_SET:
875         case RTC_EPOCH_SET:
876                 if (entering(tcp))
877                         tprintf(", %lu", arg);
878                 break;
879         case RTC_IRQP_READ:
880         case RTC_EPOCH_READ:
881                 if (exiting(tcp))
882                         tprintf(", %lu", arg);
883                 break;
884         case RTC_WKALM_SET:
885                 if (entering(tcp)) {
886                         struct rtc_wkalrm wk;
887                         if (umove(tcp, arg, &wk) < 0)
888                                 tprintf(", %#lx", arg);
889                         else {
890                                 tprintf(", {enabled=%d, pending=%d, ",
891                                         wk.enabled, wk.pending);
892                                 print_rtc(tcp, &wk.time);
893                                 tprints("}");
894                         }
895                 }
896                 break;
897         case RTC_WKALM_RD:
898                 if (exiting(tcp)) {
899                         struct rtc_wkalrm wk;
900                         if (syserror(tcp) || umove(tcp, arg, &wk) < 0)
901                                 tprintf(", %#lx", arg);
902                         else {
903                                 tprintf(", {enabled=%d, pending=%d, ",
904                                         wk.enabled, wk.pending);
905                                 print_rtc(tcp, &wk.time);
906                                 tprints("}");
907                         }
908                 }
909                 break;
910         default:
911                 if (entering(tcp))
912                         tprintf(", %#lx", arg);
913                 break;
914         }
915         return 1;
916 }
917
918 #ifndef TFD_TIMER_ABSTIME
919 #define TFD_TIMER_ABSTIME (1 << 0)
920 #endif
921
922 static const struct xlat timerfdflags[] = {
923         { TFD_TIMER_ABSTIME,    "TFD_TIMER_ABSTIME"     },
924         { 0,                    NULL                    }
925 };
926
927 int
928 sys_timerfd(struct tcb *tcp)
929 {
930         if (entering(tcp)) {
931                 /* It does not matter that the kernel uses itimerspec.  */
932                 tprintf("%ld, ", tcp->u_arg[0]);
933                 printxval(clocknames, tcp->u_arg[1], "CLOCK_???");
934                 tprints(", ");
935                 printflags(timerfdflags, tcp->u_arg[2], "TFD_???");
936                 tprints(", ");
937                 printitv(tcp, tcp->u_arg[3]);
938         }
939         return 0;
940 }
941
942 int
943 sys_timerfd_create(struct tcb *tcp)
944 {
945         if (entering(tcp)) {
946                 printxval(clocknames, tcp->u_arg[0], "CLOCK_???");
947                 tprints(", ");
948                 printflags(timerfdflags, tcp->u_arg[1], "TFD_???");
949         }
950         return 0;
951 }
952
953 int
954 sys_timerfd_settime(struct tcb *tcp)
955 {
956         if (entering(tcp)) {
957                 printfd(tcp, tcp->u_arg[0]);
958                 tprints(", ");
959                 printflags(timerfdflags, tcp->u_arg[1], "TFD_???");
960                 tprints(", ");
961                 printitv(tcp, tcp->u_arg[2]);
962                 tprints(", ");
963                 printitv(tcp, tcp->u_arg[3]);
964         }
965         return 0;
966 }
967
968 int
969 sys_timerfd_gettime(struct tcb *tcp)
970 {
971         if (entering(tcp)) {
972                 printfd(tcp, tcp->u_arg[0]);
973                 tprints(", ");
974                 printitv(tcp, tcp->u_arg[1]);
975         }
976         return 0;
977 }
978
979 #endif /* LINUX */