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