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  * Copyright (c) 1996-1999 Wichert Akkerman <wichert (at) cistron.nl>
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  * 3. The name of the author may not be used to endorse or promote products
     17  *    derived from this software without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  *
     30  *	$Id$
     31  */
     32 
     33 #include "defs.h"
     34 
     35 #include <fcntl.h>
     36 #include <sys/file.h>
     37 #ifdef LINUX
     38 #include <inttypes.h>
     39 #endif
     40 #ifdef HAVE_SYS_EPOLL_H
     41 #include <sys/epoll.h>
     42 #endif
     43 #ifdef HAVE_LIBAIO_H
     44 #include <libaio.h>
     45 #endif
     46 
     47 #if HAVE_LONG_LONG_OFF_T
     48 /*
     49  * Hacks for systems that have a long long off_t
     50  */
     51 #define flock64	flock		/* Horrid hack */
     52 #define printflock printflock64	/* Horrider hack */
     53 #endif
     54 
     55 
     56 static const struct xlat fcntlcmds[] = {
     57 	{ F_DUPFD,	"F_DUPFD"	},
     58 	{ F_GETFD,	"F_GETFD"	},
     59 	{ F_SETFD,	"F_SETFD"	},
     60 	{ F_GETFL,	"F_GETFL"	},
     61 	{ F_SETFL,	"F_SETFL"	},
     62 	{ F_GETLK,	"F_GETLK"	},
     63 	{ F_SETLK,	"F_SETLK"	},
     64 	{ F_SETLKW,	"F_SETLKW"	},
     65 	{ F_GETOWN,	"F_GETOWN"	},
     66 	{ F_SETOWN,	"F_SETOWN"	},
     67 #ifdef F_RSETLK
     68 	{ F_RSETLK,	"F_RSETLK"	},
     69 #endif
     70 #ifdef F_RSETLKW
     71 	{ F_RSETLKW,	"F_RSETLKW"	},
     72 #endif
     73 #ifdef F_RGETLK
     74 	{ F_RGETLK,	"F_RGETLK"	},
     75 #endif
     76 #ifdef F_CNVT
     77 	{ F_CNVT,	"F_CNVT"	},
     78 #endif
     79 #ifdef F_SETSIG
     80 	{ F_SETSIG,	"F_SETSIG"	},
     81 #endif
     82 #ifdef F_GETSIG
     83 	{ F_GETSIG,	"F_GETSIG"	},
     84 #endif
     85 #ifdef F_CHKFL
     86 	{ F_CHKFL,	"F_CHKFL"	},
     87 #endif
     88 #ifdef F_DUP2FD
     89 	{ F_DUP2FD,	"F_DUP2FD"	},
     90 #endif
     91 #ifdef F_ALLOCSP
     92 	{ F_ALLOCSP,	"F_ALLOCSP"	},
     93 #endif
     94 #ifdef F_ISSTREAM
     95 	{ F_ISSTREAM,	"F_ISSTREAM"	},
     96 #endif
     97 #ifdef F_PRIV
     98 	{ F_PRIV,	"F_PRIV"	},
     99 #endif
    100 #ifdef F_NPRIV
    101 	{ F_NPRIV,	"F_NPRIV"	},
    102 #endif
    103 #ifdef F_QUOTACL
    104 	{ F_QUOTACL,	"F_QUOTACL"	},
    105 #endif
    106 #ifdef F_BLOCKS
    107 	{ F_BLOCKS,	"F_BLOCKS"	},
    108 #endif
    109 #ifdef F_BLKSIZE
    110 	{ F_BLKSIZE,	"F_BLKSIZE"	},
    111 #endif
    112 #ifdef F_GETOWN
    113 	{ F_GETOWN,	"F_GETOWN"	},
    114 #endif
    115 #ifdef F_SETOWN
    116 	{ F_SETOWN,	"F_SETOWN"	},
    117 #endif
    118 #ifdef F_REVOKE
    119 	{ F_REVOKE,	"F_REVOKE"	},
    120 #endif
    121 #ifdef F_SETLK
    122 	{ F_SETLK,	"F_SETLK"	},
    123 #endif
    124 #ifdef F_SETLKW
    125 	{ F_SETLKW,	"F_SETLKW"	},
    126 #endif
    127 #ifdef F_FREESP
    128 	{ F_FREESP,	"F_FREESP"	},
    129 #endif
    130 #ifdef F_GETLK
    131 	{ F_GETLK,	"F_GETLK"	},
    132 #endif
    133 #ifdef F_SETLK64
    134 	{ F_SETLK64,	"F_SETLK64"	},
    135 #endif
    136 #ifdef F_SETLKW64
    137 	{ F_SETLKW64,	"F_SETLKW64"	},
    138 #endif
    139 #ifdef F_FREESP64
    140 	{ F_FREESP64,	"F_FREESP64"	},
    141 #endif
    142 #ifdef F_GETLK64
    143 	{ F_GETLK64,	"F_GETLK64"	},
    144 #endif
    145 #ifdef F_SHARE
    146 	{ F_SHARE,	"F_SHARE"	},
    147 #endif
    148 #ifdef F_UNSHARE
    149 	{ F_UNSHARE,	"F_UNSHARE"	},
    150 #endif
    151 #ifdef F_SETLEASE
    152 	{ F_SETLEASE,	"F_SETLEASE"	},
    153 #endif
    154 #ifdef F_GETLEASE
    155 	{ F_GETLEASE,	"F_GETLEASE"	},
    156 #endif
    157 #ifdef F_NOTIFY
    158 	{ F_NOTIFY,	"F_NOTIFY"	},
    159 #endif
    160 #ifdef F_DUPFD_CLOEXEC
    161 	{ F_DUPFD_CLOEXEC,"F_DUPFD_CLOEXEC"},
    162 #endif
    163 	{ 0,		NULL		},
    164 };
    165 
    166 static const struct xlat fdflags[] = {
    167 #ifdef FD_CLOEXEC
    168 	{ FD_CLOEXEC,	"FD_CLOEXEC"	},
    169 #endif
    170 	{ 0,		NULL		},
    171 };
    172 
    173 #ifdef LOCK_SH
    174 
    175 static const struct xlat flockcmds[] = {
    176 	{ LOCK_SH,	"LOCK_SH"	},
    177 	{ LOCK_EX,	"LOCK_EX"	},
    178 	{ LOCK_NB,	"LOCK_NB"	},
    179 	{ LOCK_UN,	"LOCK_UN"	},
    180 	{ 0,		NULL		},
    181 };
    182 
    183 #endif /* LOCK_SH */
    184 
    185 static const struct xlat lockfcmds[] = {
    186 	{ F_RDLCK,	"F_RDLCK"	},
    187 	{ F_WRLCK,	"F_WRLCK"	},
    188 	{ F_UNLCK,	"F_UNLCK"	},
    189 #ifdef F_EXLCK
    190 	{ F_EXLCK,	"F_EXLCK"	},
    191 #endif
    192 #ifdef F_SHLCK
    193 	{ F_SHLCK,	"F_SHLCK"	},
    194 #endif
    195 	{ 0,		NULL		},
    196 };
    197 
    198 #ifdef F_NOTIFY
    199 static const struct xlat notifyflags[] = {
    200 #ifdef DN_ACCESS
    201 	{ DN_ACCESS,	"DN_ACCESS"	},
    202 #endif
    203 #ifdef DN_MODIFY
    204 	{ DN_MODIFY,	"DN_MODIFY"	},
    205 #endif
    206 #ifdef DN_CREATE
    207 	{ DN_CREATE,	"DN_CREATE"	},
    208 #endif
    209 #ifdef DN_DELETE
    210 	{ DN_DELETE,	"DN_DELETE"	},
    211 #endif
    212 #ifdef DN_RENAME
    213 	{ DN_RENAME,	"DN_RENAME"	},
    214 #endif
    215 #ifdef DN_ATTRIB
    216 	{ DN_ATTRIB,	"DN_ATTRIB"	},
    217 #endif
    218 #ifdef DN_MULTISHOT
    219 	{ DN_MULTISHOT,	"DN_MULTISHOT"	},
    220 #endif
    221 	{ 0,		NULL		},
    222 };
    223 #endif
    224 
    225 static const struct xlat whence[] = {
    226 	{ SEEK_SET,	"SEEK_SET"	},
    227 	{ SEEK_CUR,	"SEEK_CUR"	},
    228 	{ SEEK_END,	"SEEK_END"	},
    229 	{ 0,		NULL		},
    230 };
    231 
    232 #ifndef HAVE_LONG_LONG_OFF_T
    233 /* fcntl/lockf */
    234 static void
    235 printflock(struct tcb *tcp, long addr, int getlk)
    236 {
    237 	struct flock fl;
    238 
    239 #if SUPPORTED_PERSONALITIES > 1
    240 	if (personality_wordsize[current_personality] != sizeof(fl.l_start)) {
    241 		if (personality_wordsize[current_personality] == 4) {
    242 			/* 32-bit x86 app on x86_64 and similar cases */
    243 			struct {
    244 				short int l_type;
    245 				short int l_whence;
    246 				int32_t l_start; /* off_t */
    247 				int32_t l_len; /* off_t */
    248 				int32_t l_pid; /* pid_t */
    249 			} fl32;
    250 			if (umove(tcp, addr, &fl32) < 0) {
    251 				tprintf("{...}");
    252 				return;
    253 			}
    254 			fl.l_type = fl32.l_type;
    255 			fl.l_whence = fl32.l_whence;
    256 			fl.l_start = fl32.l_start;
    257 			fl.l_len = fl32.l_len;
    258 			fl.l_pid = fl32.l_pid;
    259 		} else {
    260 			/* let people know we have a problem here */
    261 			tprintf("{ <decode error: unsupported wordsize %d> }",
    262 				personality_wordsize[current_personality]);
    263 			return;
    264 		}
    265 	} else
    266 #endif
    267 	{
    268 		if (umove(tcp, addr, &fl) < 0) {
    269 			tprintf("{...}");
    270 			return;
    271 		}
    272 	}
    273 	tprintf("{type=");
    274 	printxval(lockfcmds, fl.l_type, "F_???");
    275 	tprintf(", whence=");
    276 	printxval(whence, fl.l_whence, "SEEK_???");
    277 	tprintf(", start=%ld, len=%ld", fl.l_start, fl.l_len);
    278 	if (getlk)
    279 		tprintf(", pid=%lu}", (unsigned long) fl.l_pid);
    280 	else
    281 		tprintf("}");
    282 }
    283 #endif
    284 
    285 #if _LFS64_LARGEFILE || HAVE_LONG_LONG_OFF_T
    286 /* fcntl/lockf */
    287 static void
    288 printflock64(struct tcb *tcp, long addr, int getlk)
    289 {
    290 	struct flock64 fl;
    291 
    292 	if (umove(tcp, addr, &fl) < 0) {
    293 		tprintf("{...}");
    294 		return;
    295 	}
    296 	tprintf("{type=");
    297 	printxval(lockfcmds, fl.l_type, "F_???");
    298 	tprintf(", whence=");
    299 	printxval(whence, fl.l_whence, "SEEK_???");
    300 	tprintf(", start=%lld, len=%lld", (long long) fl.l_start, (long long) fl.l_len);
    301 	if (getlk)
    302 		tprintf(", pid=%lu}", (unsigned long) fl.l_pid);
    303 	else
    304 		tprintf("}");
    305 }
    306 #endif
    307 
    308 int
    309 sys_fcntl(struct tcb *tcp)
    310 {
    311 	if (entering(tcp)) {
    312 		printfd(tcp, tcp->u_arg[0]);
    313 		tprintf(", ");
    314 		printxval(fcntlcmds, tcp->u_arg[1], "F_???");
    315 		switch (tcp->u_arg[1]) {
    316 		case F_SETFD:
    317 			tprintf(", ");
    318 			printflags(fdflags, tcp->u_arg[2], "FD_???");
    319 			break;
    320 		case F_SETOWN: case F_DUPFD:
    321 #ifdef F_DUPFD_CLOEXEC
    322 		case F_DUPFD_CLOEXEC:
    323 #endif
    324 			tprintf(", %ld", tcp->u_arg[2]);
    325 			break;
    326 		case F_SETFL:
    327 			tprintf(", ");
    328 			tprint_open_modes(tcp->u_arg[2]);
    329 			break;
    330 		case F_SETLK: case F_SETLKW:
    331 #ifdef F_FREESP
    332 		case F_FREESP:
    333 #endif
    334 			tprintf(", ");
    335 			printflock(tcp, tcp->u_arg[2], 0);
    336 			break;
    337 #if _LFS64_LARGEFILE
    338 #ifdef F_FREESP64
    339 		case F_FREESP64:
    340 #endif
    341 		/* Linux glibc defines SETLK64 as SETLK,
    342 		   even though the kernel has different values - as does Solaris. */
    343 #if defined(F_SETLK64) && F_SETLK64 + 0 != F_SETLK
    344 		case F_SETLK64:
    345 #endif
    346 #if defined(F_SETLKW64) && F_SETLKW64 + 0 != F_SETLKW
    347 		case F_SETLKW64:
    348 #endif
    349 			tprintf(", ");
    350 			printflock64(tcp, tcp->u_arg[2], 0);
    351 			break;
    352 #endif
    353 #ifdef F_NOTIFY
    354 		case F_NOTIFY:
    355 			tprintf(", ");
    356 			printflags(notifyflags, tcp->u_arg[2], "DN_???");
    357 			break;
    358 #endif
    359 #ifdef F_SETLEASE
    360 		case F_SETLEASE:
    361 			tprintf(", ");
    362 			printxval(lockfcmds, tcp->u_arg[2], "F_???");
    363 			break;
    364 #endif
    365 		}
    366 	}
    367 	else {
    368 		switch (tcp->u_arg[1]) {
    369 		case F_DUPFD:
    370 #ifdef F_DUPFD_CLOEXEC
    371 		case F_DUPFD_CLOEXEC:
    372 #endif
    373 		case F_SETFD: case F_SETFL:
    374 		case F_SETLK: case F_SETLKW:
    375 		case F_SETOWN: case F_GETOWN:
    376 #ifdef F_NOTIFY
    377 		case F_NOTIFY:
    378 #endif
    379 #ifdef F_SETLEASE
    380 		case F_SETLEASE:
    381 #endif
    382 			break;
    383 		case F_GETFD:
    384 			if (syserror(tcp) || tcp->u_rval == 0)
    385 				return 0;
    386 			tcp->auxstr = sprintflags("flags ", fdflags, tcp->u_rval);
    387 			return RVAL_HEX|RVAL_STR;
    388 		case F_GETFL:
    389 			if (syserror(tcp))
    390 				return 0;
    391 			tcp->auxstr = sprint_open_modes(tcp->u_rval);
    392 			return RVAL_HEX|RVAL_STR;
    393 		case F_GETLK:
    394 			tprintf(", ");
    395 			printflock(tcp, tcp->u_arg[2], 1);
    396 			break;
    397 #if _LFS64_LARGEFILE
    398 #if defined(F_GETLK64) && F_GETLK64+0!=F_GETLK
    399 		case F_GETLK64:
    400 #endif
    401 			tprintf(", ");
    402 			printflock64(tcp, tcp->u_arg[2], 1);
    403 			break;
    404 #endif
    405 #ifdef F_GETLEASE
    406 		case F_GETLEASE:
    407 			if (syserror(tcp))
    408 				return 0;
    409 			tcp->auxstr = xlookup(lockfcmds, tcp->u_rval);
    410 			return RVAL_HEX|RVAL_STR;
    411 #endif
    412 		default:
    413 			tprintf(", %#lx", tcp->u_arg[2]);
    414 			break;
    415 		}
    416 	}
    417 	return 0;
    418 }
    419 
    420 #ifdef LOCK_SH
    421 
    422 int
    423 sys_flock(struct tcb *tcp)
    424 {
    425 	if (entering(tcp)) {
    426 		printfd(tcp, tcp->u_arg[0]);
    427 		tprintf(", ");
    428 		printflags(flockcmds, tcp->u_arg[1], "LOCK_???");
    429 	}
    430 	return 0;
    431 }
    432 #endif /* LOCK_SH */
    433 
    434 int
    435 sys_close(struct tcb *tcp)
    436 {
    437 	if (entering(tcp)) {
    438 		printfd(tcp, tcp->u_arg[0]);
    439 	}
    440 	return 0;
    441 }
    442 
    443 int
    444 sys_dup(struct tcb *tcp)
    445 {
    446 	if (entering(tcp)) {
    447 		printfd(tcp, tcp->u_arg[0]);
    448 	}
    449 	return 0;
    450 }
    451 
    452 static int
    453 do_dup2(struct tcb *tcp, int flags_arg)
    454 {
    455 	if (entering(tcp)) {
    456 		printfd(tcp, tcp->u_arg[0]);
    457 		tprintf(", ");
    458 		printfd(tcp, tcp->u_arg[1]);
    459 		if (flags_arg >= 0) {
    460 			tprintf(", ");
    461 			printflags(open_mode_flags, tcp->u_arg[flags_arg], "O_???");
    462 		}
    463 	}
    464 	return 0;
    465 }
    466 
    467 int
    468 sys_dup2(struct tcb *tcp)
    469 {
    470 	return do_dup2(tcp, -1);
    471 }
    472 
    473 #ifdef LINUX
    474 int
    475 sys_dup3(struct tcb *tcp)
    476 {
    477 	return do_dup2(tcp, 2);
    478 }
    479 #endif
    480 
    481 #if defined(ALPHA) || defined(FREEBSD) || defined(SUNOS4)
    482 int
    483 sys_getdtablesize(struct tcb *tcp)
    484 {
    485 	return 0;
    486 }
    487 #endif /* ALPHA || FREEBSD || SUNOS4 */
    488 
    489 static int
    490 decode_select(struct tcb *tcp, long *args, enum bitness_t bitness)
    491 {
    492 	int i, j, nfds;
    493 	unsigned int fdsize = ((((args[0] + 7) / 8) + sizeof(long) - 1)
    494 			       & -sizeof(long));
    495 	fd_set *fds;
    496 	static char outstr[1024];
    497 	const char *sep;
    498 	long arg;
    499 
    500 	if (entering(tcp)) {
    501 		fds = (fd_set *) malloc(fdsize);
    502 		if (fds == NULL)
    503 			fprintf(stderr, "out of memory\n");
    504 		nfds = args[0];
    505 		tprintf("%d", nfds);
    506 		for (i = 0; i < 3; i++) {
    507 			arg = args[i+1];
    508 			if (arg == 0) {
    509 				tprintf(", NULL");
    510 				continue;
    511 			}
    512 			if (fds == NULL || !verbose(tcp)) {
    513 				tprintf(", %#lx", arg);
    514 				continue;
    515 			}
    516 			if (umoven(tcp, arg, fdsize, (char *) fds) < 0) {
    517 				tprintf(", [?]");
    518 				continue;
    519 			}
    520 			tprintf(", [");
    521 			for (j = 0, sep = ""; j < nfds; j++) {
    522 				if (FD_ISSET(j, fds)) {
    523 					tprintf("%s", sep);
    524 					printfd(tcp, j);
    525 					sep = " ";
    526 				}
    527 			}
    528 			tprintf("]");
    529 		}
    530 		free(fds);
    531 		tprintf(", ");
    532 		printtv_bitness(tcp, args[4], bitness, 0);
    533 	}
    534 	else
    535 	{
    536 		unsigned int cumlen = 0;
    537 		const char *sep = "";
    538 
    539 		if (syserror(tcp))
    540 			return 0;
    541 
    542 		if ((nfds = tcp->u_rval) == 0) {
    543 			tcp->auxstr = "Timeout";
    544 			return RVAL_STR;
    545 		}
    546 
    547 		fds = (fd_set *) malloc(fdsize);
    548 		if (fds == NULL)
    549 			fprintf(stderr, "out of memory\n");
    550 
    551 		outstr[0] = '\0';
    552 		for (i = 0; i < 3; i++) {
    553 			int first = 1;
    554 
    555 			tcp->auxstr = outstr;
    556 			arg = args[i+1];
    557 			if (fds == NULL || !arg ||
    558 			    umoven(tcp, arg, fdsize, (char *) fds) < 0)
    559 				continue;
    560 			for (j = 0; j < args[0]; j++) {
    561 				if (FD_ISSET(j, fds)) {
    562 					char str[11 + 3 * sizeof(int)];
    563 
    564 					if (first) {
    565 						sprintf(str, "%s%s [%u", sep,
    566 							i == 0 ? "in" :
    567 							i == 1 ? "out" :
    568 							"except", j);
    569 						first = 0;
    570 						sep = ", ";
    571 					}
    572 					else
    573 						sprintf(str, " %u", j);
    574 					cumlen += strlen(str);
    575 					if (cumlen < sizeof(outstr))
    576 						strcat(outstr, str);
    577 					nfds--;
    578 				}
    579 			}
    580 			if (cumlen)
    581 				strcat(outstr, "]");
    582 			if (nfds == 0)
    583 				break;
    584 		}
    585 		free(fds);
    586 #ifdef LINUX
    587 		/* This contains no useful information on SunOS.  */
    588 		if (args[4]) {
    589 			char str[128];
    590 
    591 			sprintf(str, "%sleft ", sep);
    592 			sprinttv(tcp, args[4], bitness, str + strlen(str));
    593 			if ((cumlen += strlen(str)) < sizeof(outstr))
    594 				strcat(outstr, str);
    595 		}
    596 #endif /* LINUX */
    597 		return RVAL_STR;
    598 	}
    599 	return 0;
    600 }
    601 
    602 #ifdef LINUX
    603 
    604 int
    605 sys_oldselect(struct tcb *tcp)
    606 {
    607 	long args[5];
    608 
    609 	if (umoven(tcp, tcp->u_arg[0], sizeof args, (char *) args) < 0) {
    610 		tprintf("[...]");
    611 		return 0;
    612 	}
    613 	return decode_select(tcp, args, BITNESS_CURRENT);
    614 }
    615 
    616 #ifdef ALPHA
    617 int
    618 sys_osf_select(struct tcb *tcp)
    619 {
    620 	long *args = tcp->u_arg;
    621 	return decode_select(tcp, args, BITNESS_32);
    622 }
    623 #endif
    624 
    625 static const struct xlat epollctls[] = {
    626 #ifdef EPOLL_CTL_ADD
    627 	{ EPOLL_CTL_ADD,	"EPOLL_CTL_ADD"	},
    628 #endif
    629 #ifdef EPOLL_CTL_MOD
    630 	{ EPOLL_CTL_MOD,	"EPOLL_CTL_MOD"	},
    631 #endif
    632 #ifdef EPOLL_CTL_DEL
    633 	{ EPOLL_CTL_DEL,	"EPOLL_CTL_DEL"	},
    634 #endif
    635 	{ 0,			NULL		}
    636 };
    637 
    638 static const struct xlat epollevents[] = {
    639 #ifdef EPOLLIN
    640 	{ EPOLLIN,	"EPOLLIN"	},
    641 #endif
    642 #ifdef EPOLLPRI
    643 	{ EPOLLPRI,	"EPOLLPRI"	},
    644 #endif
    645 #ifdef EPOLLOUT
    646 	{ EPOLLOUT,	"EPOLLOUT"	},
    647 #endif
    648 #ifdef EPOLLRDNORM
    649 	{ EPOLLRDNORM,	"EPOLLRDNORM"	},
    650 #endif
    651 #ifdef EPOLLRDBAND
    652 	{ EPOLLRDBAND,	"EPOLLRDBAND"	},
    653 #endif
    654 #ifdef EPOLLWRNORM
    655 	{ EPOLLWRNORM,	"EPOLLWRNORM"	},
    656 #endif
    657 #ifdef EPOLLWRBAND
    658 	{ EPOLLWRBAND,	"EPOLLWRBAND"	},
    659 #endif
    660 #ifdef EPOLLMSG
    661 	{ EPOLLMSG,	"EPOLLMSG"	},
    662 #endif
    663 #ifdef EPOLLERR
    664 	{ EPOLLERR,	"EPOLLERR"	},
    665 #endif
    666 #ifdef EPOLLHUP
    667 	{ EPOLLHUP,	"EPOLLHUP"	},
    668 #endif
    669 #ifdef EPOLLONESHOT
    670 	{ EPOLLONESHOT,	"EPOLLONESHOT"	},
    671 #endif
    672 #ifdef EPOLLET
    673 	{ EPOLLET,	"EPOLLET"	},
    674 #endif
    675 	{ 0,		NULL		}
    676 };
    677 
    678 int
    679 sys_epoll_create(struct tcb *tcp)
    680 {
    681 	if (entering(tcp))
    682 		tprintf("%ld", tcp->u_arg[0]);
    683 	return 0;
    684 }
    685 
    686 int
    687 sys_epoll_create1(struct tcb *tcp)
    688 {
    689 	if (entering(tcp))
    690 		printflags(open_mode_flags, tcp->u_arg[0], "O_???");
    691 	return 0;
    692 }
    693 
    694 #ifdef HAVE_SYS_EPOLL_H
    695 static void
    696 print_epoll_event(struct epoll_event *ev)
    697 {
    698 	tprintf("{");
    699 	printflags(epollevents, ev->events, "EPOLL???");
    700 	/* We cannot know what format the program uses, so print u32 and u64
    701 	   which will cover every value.  */
    702 	tprintf(", {u32=%" PRIu32 ", u64=%" PRIu64 "}}",
    703 		ev->data.u32, ev->data.u64);
    704 }
    705 #endif
    706 
    707 int
    708 sys_epoll_ctl(struct tcb *tcp)
    709 {
    710 	if (entering(tcp)) {
    711 		printfd(tcp, tcp->u_arg[0]);
    712 		tprintf(", ");
    713 		printxval(epollctls, tcp->u_arg[1], "EPOLL_CTL_???");
    714 		tprintf(", ");
    715 		printfd(tcp, tcp->u_arg[2]);
    716 		tprintf(", ");
    717 		if (tcp->u_arg[3] == 0)
    718 			tprintf("NULL");
    719 		else {
    720 #ifdef HAVE_SYS_EPOLL_H
    721 			struct epoll_event ev;
    722 			if (umove(tcp, tcp->u_arg[3], &ev) == 0)
    723 				print_epoll_event(&ev);
    724 			else
    725 #endif
    726 				tprintf("{...}");
    727 		}
    728 	}
    729 	return 0;
    730 }
    731 
    732 static void
    733 epoll_wait_common(struct tcb *tcp)
    734 {
    735 	if (entering(tcp)) {
    736 		printfd(tcp, tcp->u_arg[0]);
    737 		tprintf(", ");
    738 	} else {
    739 		if (syserror(tcp))
    740 			tprintf("%lx", tcp->u_arg[1]);
    741 		else if (tcp->u_rval == 0)
    742 			tprintf("{}");
    743 		else {
    744 #ifdef HAVE_SYS_EPOLL_H
    745 			struct epoll_event ev, *start, *cur, *end;
    746 			int failed = 0;
    747 
    748 			tprintf("{");
    749 			start = (struct epoll_event *) tcp->u_arg[1];
    750 			end = start + tcp->u_rval;
    751 			for (cur = start; cur < end; ++cur) {
    752 				if (cur > start)
    753 					tprintf(", ");
    754 				if (umove(tcp, (long) cur, &ev) == 0)
    755 					print_epoll_event(&ev);
    756 				else {
    757 					tprintf("?");
    758 					failed = 1;
    759 					break;
    760 				}
    761 			}
    762 			tprintf("}");
    763 			if (failed)
    764 				tprintf(" %#lx", (long) start);
    765 #else
    766 			tprintf("{...}");
    767 #endif
    768 		}
    769 		tprintf(", %ld, %ld", tcp->u_arg[2], tcp->u_arg[3]);
    770 	}
    771 }
    772 
    773 int
    774 sys_epoll_wait(struct tcb *tcp)
    775 {
    776 	epoll_wait_common(tcp);
    777 	return 0;
    778 }
    779 
    780 int
    781 sys_epoll_pwait(struct tcb *tcp)
    782 {
    783 	epoll_wait_common(tcp);
    784 	if (exiting(tcp)) {
    785 		tprintf(", ");
    786 		print_sigset(tcp, tcp->u_arg[4], 0);
    787 	}
    788 	return 0;
    789 }
    790 
    791 int
    792 sys_io_setup(struct tcb *tcp)
    793 {
    794 	if (entering(tcp))
    795 		tprintf("%ld, ", tcp->u_arg[0]);
    796 	else {
    797 		if (syserror(tcp))
    798 			tprintf("0x%0lx", tcp->u_arg[1]);
    799 		else {
    800 			unsigned long user_id;
    801 			if (umove(tcp, tcp->u_arg[1], &user_id) == 0)
    802 				tprintf("{%lu}", user_id);
    803 			else
    804 				tprintf("{...}");
    805 		}
    806 	}
    807 	return 0;
    808 }
    809 
    810 int
    811 sys_io_destroy(struct tcb *tcp)
    812 {
    813 	if (entering(tcp))
    814 		tprintf("%lu", tcp->u_arg[0]);
    815 	return 0;
    816 }
    817 
    818 int
    819 sys_io_submit(struct tcb *tcp)
    820 {
    821 	long nr;
    822 	if (entering(tcp)) {
    823 		tprintf("%lu, %ld, ", tcp->u_arg[0], tcp->u_arg[1]);
    824 		nr = tcp->u_arg[1];
    825 		/* and if nr is negative? */
    826 		if (nr == 0)
    827 			tprintf("{}");
    828 		else {
    829 #ifdef HAVE_LIBAIO_H
    830 			long i;
    831 			struct iocb *iocbp, **iocbs = (void *)tcp->u_arg[2];
    832 
    833 			for (i = 0; i < nr; i++, iocbs++) {
    834 				struct iocb iocb;
    835 				if (i == 0)
    836 					tprintf("{");
    837 				else
    838 					tprintf(", ");
    839 
    840 				if (umove(tcp, (unsigned long)iocbs, &iocbp) ||
    841 				    umove(tcp, (unsigned long)iocbp, &iocb)) {
    842 					tprintf("{...}");
    843 					continue;
    844 				}
    845 				tprintf("{%p, %u, %hu, %hu, %d}",
    846 					iocb.data, iocb.key,
    847 					iocb.aio_lio_opcode,
    848 					iocb.aio_reqprio, iocb.aio_fildes);
    849 			}
    850 			if (i)
    851 				tprintf("}");
    852 #else
    853 			tprintf("{...}");
    854 #endif
    855 		}
    856 	}
    857 	return 0;
    858 }
    859 
    860 int
    861 sys_io_cancel(struct tcb *tcp)
    862 {
    863 	if (entering(tcp)) {
    864 #ifdef HAVE_LIBAIO_H
    865 		struct iocb iocb;
    866 #endif
    867 		tprintf("%lu, ", tcp->u_arg[0]);
    868 #ifdef HAVE_LIBAIO_H
    869 		if (umove(tcp, tcp->u_arg[1], &iocb) == 0) {
    870 			tprintf("{%p, %u, %hu, %hu, %d}, ",
    871 				iocb.data, iocb.key,
    872 				iocb.aio_lio_opcode,
    873 				iocb.aio_reqprio, iocb.aio_fildes);
    874 		} else
    875 #endif
    876 			tprintf("{...}, ");
    877 	} else {
    878 		if (tcp->u_rval < 0)
    879 			tprintf("{...}");
    880 		else {
    881 #ifdef HAVE_LIBAIO_H
    882 			struct io_event event;
    883 			if (umove(tcp, tcp->u_arg[2], &event) == 0)
    884 				tprintf("{%p, %p, %ld, %ld}",
    885 					event.data, event.obj,
    886 					event.res, event.res2);
    887 			else
    888 #endif
    889 				tprintf("{...}");
    890 		}
    891 	}
    892 	return 0;
    893 }
    894 
    895 int
    896 sys_io_getevents(struct tcb *tcp)
    897 {
    898 	if (entering(tcp)) {
    899 		tprintf("%ld, %ld, %ld, ", tcp->u_arg[0], tcp->u_arg[1],
    900 			tcp->u_arg[2]);
    901 	} else {
    902 		if (tcp->u_rval == 0) {
    903 			tprintf("{}");
    904 		} else  {
    905 #ifdef HAVE_LIBAIO_H
    906 			struct io_event *events = (void *)tcp->u_arg[3];
    907 			long i, nr = tcp->u_rval;
    908 
    909 			for (i = 0; i < nr; i++, events++) {
    910 				struct io_event event;
    911 
    912 				if (i == 0)
    913 					tprintf("{");
    914 				else
    915 					tprintf(", ");
    916 
    917 				if (umove(tcp, (unsigned long)events, &event) != 0) {
    918 					tprintf("{...}");
    919 					continue;
    920 				}
    921 				tprintf("{%p, %p, %ld, %ld}", event.data,
    922 					event.obj, event.res, event.res2);
    923 			}
    924 			tprintf("}, ");
    925 #else
    926 				tprintf("{...}");
    927 #endif
    928 		}
    929 
    930 		print_timespec(tcp, tcp->u_arg[4]);
    931 	}
    932 	return 0;
    933 }
    934 #endif /* LINUX */
    935 
    936 int
    937 sys_select(struct tcb *tcp)
    938 {
    939 	return decode_select(tcp, tcp->u_arg, BITNESS_CURRENT);
    940 }
    941 
    942 #ifdef LINUX
    943 int
    944 sys_pselect6(struct tcb *tcp)
    945 {
    946 	int rc = decode_select(tcp, tcp->u_arg, BITNESS_CURRENT);
    947 	if (entering(tcp)) {
    948 		struct {
    949 			void *ss;
    950 			unsigned long len;
    951 		} data;
    952 		if (umove(tcp, tcp->u_arg[5], &data) < 0)
    953 			tprintf(", %#lx", tcp->u_arg[5]);
    954 		else {
    955 			tprintf(", {");
    956 			if (data.len < sizeof(long))
    957 				tprintf("%#lx", (long)data.ss);
    958 			else
    959 				print_sigset(tcp, (long)data.ss, 0);
    960 			tprintf(", %lu}", data.len);
    961 		}
    962 	}
    963 	return rc;
    964 }
    965 
    966 static int
    967 do_eventfd(struct tcb *tcp, int flags_arg)
    968 {
    969 	if (entering(tcp)) {
    970 		tprintf("%lu", tcp->u_arg[0]);
    971 		if (flags_arg >= 0) {
    972 			tprintf(", ");
    973 			printflags(open_mode_flags, tcp->u_arg[flags_arg], "O_???");
    974 		}
    975 	}
    976 	return 0;
    977 }
    978 
    979 int
    980 sys_eventfd(struct tcb *tcp)
    981 {
    982 	return do_eventfd(tcp, -1);
    983 }
    984 
    985 int
    986 sys_eventfd2(struct tcb *tcp)
    987 {
    988 	return do_eventfd(tcp, 1);
    989 }
    990 #endif
    991