Home | History | Annotate | Download | only in strace
      1 /*
      2  * Copyright (c) 1991, 1992 Paul Kranenburg <pk (at) cs.few.eur.nl>
      3  * Copyright (c) 1993 Branko Lankester <branko (at) hacktic.nl>
      4  * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs (at) 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
     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
     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
     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 *
     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
    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_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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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