]> granicus.if.org Git - strace/blob - desc.c
* desc.c (printflock): Fix display of fcntl(F_SETLK) on
[strace] / desc.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  * Copyright (c) 1996-1999 Wichert Akkerman <wichert@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         { 0,            NULL            },
152 };
153
154 static const struct xlat fdflags[] = {
155 #ifdef FD_CLOEXEC
156         { FD_CLOEXEC,   "FD_CLOEXEC"    },
157 #endif
158         { 0,            NULL            },
159 };
160
161 #ifdef LOCK_SH
162
163 static const struct xlat flockcmds[] = {
164         { LOCK_SH,      "LOCK_SH"       },
165         { LOCK_EX,      "LOCK_EX"       },
166         { LOCK_NB,      "LOCK_NB"       },
167         { LOCK_UN,      "LOCK_UN"       },
168         { 0,            NULL            },
169 };
170
171 #endif /* LOCK_SH */
172
173 static const struct xlat lockfcmds[] = {
174         { F_RDLCK,      "F_RDLCK"       },
175         { F_WRLCK,      "F_WRLCK"       },
176         { F_UNLCK,      "F_UNLCK"       },
177 #ifdef F_EXLCK
178         { F_EXLCK,      "F_EXLCK"       },
179 #endif
180 #ifdef F_SHLCK
181         { F_SHLCK,      "F_SHLCK"       },
182 #endif
183         { 0,            NULL            },
184 };
185
186 static const struct xlat whence[] = {
187         { SEEK_SET,     "SEEK_SET"      },
188         { SEEK_CUR,     "SEEK_CUR"      },
189         { SEEK_END,     "SEEK_END"      },
190         { 0,            NULL            },
191 };
192
193 #ifndef HAVE_LONG_LONG_OFF_T
194 /* fcntl/lockf */
195 static void
196 printflock(struct tcb *tcp, long addr, int getlk)
197 {
198         struct flock fl;
199
200         if (personality_wordsize[current_personality] == sizeof(fl.l_start)) {
201                 if (umove(tcp, addr, &fl) < 0) {
202                         tprintf("{...}");
203                         return;
204                 }
205         } else if (personality_wordsize[current_personality] == 4) {
206                 /* 32-bit x86 app on x86_64 and similar cases */
207                 struct {
208                         short int l_type;
209                         short int l_whence;
210                         int32_t l_start; /* off_t */
211                         int32_t l_len; /* off_t */
212                         int32_t l_pid; /* pid_t */
213                 } fl32;
214                 if (umove(tcp, addr, &fl32) < 0) {
215                         tprintf("{...}");
216                         return;
217                 }
218                 fl.l_type = fl32.l_type;
219                 fl.l_whence = fl32.l_whence;
220                 fl.l_start = fl32.l_start;
221                 fl.l_len = fl32.l_len;
222                 fl.l_pid = fl32.l_pid;
223         } else {
224                 /* let people know we have a problem here */
225                 tprintf("{ <decode error: unsupported wordsize %d> }",
226                                 personality_wordsize[current_personality]);
227                 return;
228         }
229         tprintf("{type=");
230         printxval(lockfcmds, fl.l_type, "F_???");
231         tprintf(", whence=");
232         printxval(whence, fl.l_whence, "SEEK_???");
233         tprintf(", start=%ld, len=%ld", fl.l_start, fl.l_len);
234         if (getlk)
235                 tprintf(", pid=%lu}", (unsigned long) fl.l_pid);
236         else
237                 tprintf("}");
238 }
239 #endif
240
241 #if _LFS64_LARGEFILE || HAVE_LONG_LONG_OFF_T
242 /* fcntl/lockf */
243 static void
244 printflock64(struct tcb *tcp, long addr, int getlk)
245 {
246         struct flock64 fl;
247
248         if (umove(tcp, addr, &fl) < 0) {
249                 tprintf("{...}");
250                 return;
251         }
252         tprintf("{type=");
253         printxval(lockfcmds, fl.l_type, "F_???");
254         tprintf(", whence=");
255         printxval(whence, fl.l_whence, "SEEK_???");
256         tprintf(", start=%lld, len=%lld", (long long) fl.l_start, (long long) fl.l_len);
257         if (getlk)
258                 tprintf(", pid=%lu}", (unsigned long) fl.l_pid);
259         else
260                 tprintf("}");
261 }
262 #endif
263
264 extern const struct xlat open_mode_flags[];
265
266 /*
267  * low bits of the open(2) flags define access mode,
268  * other bits are real flags.
269  */
270 static const char *
271 sprint_open_modes(mode_t flags)
272 {
273         extern const struct xlat open_access_modes[];
274         static char outstr[1024];
275         const char *str = xlookup(open_access_modes, flags & 3);
276         const char *sep = "";
277         const struct xlat *x;
278
279         strcpy(outstr, "flags ");
280         if (str) {
281                 strcat(outstr, str);
282                 flags &= ~3;
283                 if (!flags)
284                         return outstr;
285                 strcat(outstr, "|");
286         }
287
288         for (x = open_mode_flags; x->str; x++) {
289                 if ((flags & x->val) == x->val) {
290                         sprintf(outstr + strlen(outstr),
291                                 "%s%s", sep, x->str);
292                         sep = "|";
293                         flags &= ~x->val;
294                 }
295         }
296         if (flags)
297                 sprintf(outstr + strlen(outstr), "%s%#x", sep, flags);
298         return outstr;
299 }
300
301 int
302 sys_fcntl(struct tcb *tcp)
303 {
304         if (entering(tcp)) {
305                 tprintf("%ld, ", tcp->u_arg[0]);
306                 printxval(fcntlcmds, tcp->u_arg[1], "F_???");
307                 switch (tcp->u_arg[1]) {
308                 case F_SETFD:
309                         tprintf(", ");
310                         printflags(fdflags, tcp->u_arg[2], "FD_???");
311                         break;
312                 case F_SETOWN: case F_DUPFD:
313                         tprintf(", %ld", tcp->u_arg[2]);
314                         break;
315                 case F_SETFL:
316                         tprintf(", ");
317                         tprint_open_modes(tcp, tcp->u_arg[2]);
318                         break;
319                 case F_SETLK: case F_SETLKW:
320 #ifdef F_FREESP
321                 case F_FREESP:
322 #endif
323                         tprintf(", ");
324                         printflock(tcp, tcp->u_arg[2], 0);
325                         break;
326 #if _LFS64_LARGEFILE
327 #ifdef F_FREESP64
328                 case F_FREESP64:
329 #endif
330                 /* Linux glibc defines SETLK64 as SETLK,
331                    even though the kernel has different values - as does Solaris. */
332 #if defined(F_SETLK64) && F_SETLK64+0!=F_SETLK
333                 case F_SETLK64:
334 #endif
335 #if defined(F_SETLKW64) && F_SETLKW64+0!=F_SETLKW
336                 case F_SETLKW64:
337 #endif
338                         tprintf(", ");
339                         printflock64(tcp, tcp->u_arg[2], 0);
340                         break;
341 #endif
342                 }
343         }
344         else {
345                 switch (tcp->u_arg[1]) {
346                 case F_DUPFD:
347                 case F_SETFD: case F_SETFL:
348                 case F_SETLK: case F_SETLKW:
349                 case F_SETOWN: case F_GETOWN:
350                         break;
351                 case F_GETFD:
352                         if (syserror(tcp) || tcp->u_rval == 0)
353                                 return 0;
354                         tcp->auxstr =
355                                 sprintflags("flags ", fdflags, tcp->u_rval);
356                         return RVAL_HEX|RVAL_STR;
357                 case F_GETFL:
358                         if (syserror(tcp))
359                                 return 0;
360                         tcp->auxstr = sprint_open_modes(tcp->u_rval);
361                         return RVAL_HEX|RVAL_STR;
362                 case F_GETLK:
363                         tprintf(", ");
364                         printflock(tcp, tcp->u_arg[2], 1);
365                         break;
366 #if _LFS64_LARGEFILE
367 #if defined(F_GETLK64) && F_GETLK64+0!=F_GETLK
368                 case F_GETLK64:
369 #endif
370                         tprintf(", ");
371                         printflock64(tcp, tcp->u_arg[2], 1);
372                         break;
373 #endif
374                 default:
375                         tprintf(", %#lx", tcp->u_arg[2]);
376                         break;
377                 }
378         }
379         return 0;
380 }
381
382 #ifdef LOCK_SH
383
384 int
385 sys_flock(struct tcb *tcp)
386 {
387         if (entering(tcp)) {
388                 tprintf("%ld, ", tcp->u_arg[0]);
389                 printflags(flockcmds, tcp->u_arg[1], "LOCK_???");
390         }
391         return 0;
392 }
393 #endif /* LOCK_SH */
394
395 int
396 sys_close(struct tcb *tcp)
397 {
398         if (entering(tcp)) {
399                 tprintf("%ld", tcp->u_arg[0]);
400         }
401         return 0;
402 }
403
404 int
405 sys_dup(struct tcb *tcp)
406 {
407         if (entering(tcp)) {
408                 tprintf("%ld", tcp->u_arg[0]);
409         }
410         return 0;
411 }
412
413 static int
414 do_dup2(struct tcb *tcp, int flags_arg)
415 {
416         if (entering(tcp)) {
417                 tprintf("%ld, %ld", tcp->u_arg[0], tcp->u_arg[1]);
418                 if (flags_arg >= 0) {
419                         tprintf(", ");
420                         printflags(open_mode_flags, tcp->u_arg[flags_arg], "O_???");
421                 }
422         }
423         return 0;
424 }
425
426 int
427 sys_dup2(struct tcb *tcp)
428 {
429         return do_dup2(tcp, -1);
430 }
431
432 #ifdef LINUX
433 int
434 sys_dup3(struct tcb *tcp)
435 {
436         return do_dup2(tcp, 2);
437 }
438 #endif
439
440 #if defined(ALPHA) || defined(FREEBSD) || defined(SUNOS4)
441 int
442 sys_getdtablesize(struct tcb *tcp)
443 {
444         return 0;
445 }
446 #endif /* ALPHA || FREEBSD || SUNOS4 */
447
448 static int
449 decode_select(struct tcb *tcp, long *args, enum bitness_t bitness)
450 {
451         int i, j, nfds;
452         unsigned int fdsize = ((((args[0] + 7) / 8) + sizeof(long) - 1)
453                                & -sizeof(long));
454         fd_set *fds;
455         static char outstr[1024];
456         char *sep;
457         long arg;
458
459         if (entering(tcp)) {
460                 fds = (fd_set *) malloc(fdsize);
461                 if (fds == NULL)
462                         fprintf(stderr, "out of memory\n");
463                 nfds = args[0];
464                 tprintf("%d", nfds);
465                 for (i = 0; i < 3; i++) {
466                         arg = args[i+1];
467                         if (arg == 0) {
468                                 tprintf(", NULL");
469                                 continue;
470                         }
471                         if (fds == NULL || !verbose(tcp)) {
472                                 tprintf(", %#lx", arg);
473                                 continue;
474                         }
475                         if (umoven(tcp, arg, fdsize, (char *) fds) < 0) {
476                                 tprintf(", [?]");
477                                 continue;
478                         }
479                         tprintf(", [");
480                         for (j = 0, sep = ""; j < nfds; j++) {
481                                 if (FD_ISSET(j, fds)) {
482                                         tprintf("%s%u", sep, j);
483                                         sep = " ";
484                                 }
485                         }
486                         tprintf("]");
487                 }
488                 free(fds);
489                 tprintf(", ");
490                 printtv_bitness(tcp, args[4], bitness, 0);
491         }
492         else
493         {
494                 unsigned int cumlen = 0;
495                 char *sep = "";
496
497                 if (syserror(tcp))
498                         return 0;
499
500                 if ((nfds = tcp->u_rval) == 0) {
501                         tcp->auxstr = "Timeout";
502                         return RVAL_STR;
503                 }
504
505                 fds = (fd_set *) malloc(fdsize);
506                 if (fds == NULL)
507                         fprintf(stderr, "out of memory\n");
508
509                 outstr[0] = '\0';
510                 for (i = 0; i < 3; i++) {
511                         int first = 1;
512                         char str[20];
513
514                         tcp->auxstr = outstr;
515                         arg = args[i+1];
516                         if (fds == NULL || !arg ||
517                             umoven(tcp, arg, fdsize, (char *) fds) < 0)
518                                 continue;
519                         for (j = 0; j < args[0]; j++) {
520                                 if (FD_ISSET(j, fds)) {
521                                         if (first) {
522                                                 sprintf(str, "%s%s [%u", sep,
523                                                         i == 0 ? "in" :
524                                                         i == 1 ? "out" :
525                                                         "except", j);
526                                                 first = 0;
527                                                 sep = ", ";
528                                         }
529                                         else
530                                                 sprintf(str, " %u", j);
531                                         cumlen += strlen(str);
532                                         if (cumlen < sizeof(outstr))
533                                                 strcat(outstr, str);
534                                         nfds--;
535                                 }
536                         }
537                         if (cumlen)
538                                 strcat(outstr, "]");
539                         if (nfds == 0)
540                                 break;
541                 }
542                 free(fds);
543 #ifdef LINUX
544                 /* This contains no useful information on SunOS.  */
545                 if (args[4]) {
546                         char str[128];
547
548                         sprintf(str, "%sleft ", sep);
549                         sprinttv(tcp, args[4], bitness, str + strlen(str));
550                         if ((cumlen += strlen(str)) < sizeof(outstr))
551                                 strcat(outstr, str);
552                 }
553 #endif /* LINUX */
554                 return RVAL_STR;
555         }
556         return 0;
557 }
558
559 #ifdef LINUX
560
561 int
562 sys_oldselect(struct tcb *tcp)
563 {
564         long args[5];
565
566         if (umoven(tcp, tcp->u_arg[0], sizeof args, (char *) args) < 0) {
567                 tprintf("[...]");
568                 return 0;
569         }
570         return decode_select(tcp, args, BITNESS_CURRENT);
571 }
572
573 #ifdef ALPHA
574 int
575 sys_osf_select(struct tcb *tcp)
576 {
577         long *args = tcp->u_arg;
578         return decode_select(tcp, args, BITNESS_32);
579 }
580 #endif
581
582 static const struct xlat epollctls[] = {
583 #ifdef EPOLL_CTL_ADD
584         { EPOLL_CTL_ADD,        "EPOLL_CTL_ADD" },
585 #endif
586 #ifdef EPOLL_CTL_MOD
587         { EPOLL_CTL_MOD,        "EPOLL_CTL_MOD" },
588 #endif
589 #ifdef EPOLL_CTL_DEL
590         { EPOLL_CTL_DEL,        "EPOLL_CTL_DEL" },
591 #endif
592         { 0,                    NULL            }
593 };
594
595 static const struct xlat epollevents[] = {
596 #ifdef EPOLLIN
597         { EPOLLIN,      "EPOLLIN"       },
598 #endif
599 #ifdef EPOLLPRI
600         { EPOLLPRI,     "EPOLLPRI"      },
601 #endif
602 #ifdef EPOLLOUT
603         { EPOLLOUT,     "EPOLLOUT"      },
604 #endif
605 #ifdef EPOLLRDNORM
606         { EPOLLRDNORM,  "EPOLLRDNORM"   },
607 #endif
608 #ifdef EPOLLRDBAND
609         { EPOLLRDBAND,  "EPOLLRDBAND"   },
610 #endif
611 #ifdef EPOLLWRNORM
612         { EPOLLWRNORM,  "EPOLLWRNORM"   },
613 #endif
614 #ifdef EPOLLWRBAND
615         { EPOLLWRBAND,  "EPOLLWRBAND"   },
616 #endif
617 #ifdef EPOLLMSG
618         { EPOLLMSG,     "EPOLLMSG"      },
619 #endif
620 #ifdef EPOLLERR
621         { EPOLLERR,     "EPOLLERR"      },
622 #endif
623 #ifdef EPOLLHUP
624         { EPOLLHUP,     "EPOLLHUP"      },
625 #endif
626 #ifdef EPOLLONESHOT
627         { EPOLLONESHOT, "EPOLLONESHOT"  },
628 #endif
629 #ifdef EPOLLET
630         { EPOLLET,      "EPOLLET"       },
631 #endif
632         { 0,            NULL            }
633 };
634
635 int
636 sys_epoll_create(struct tcb *tcp)
637 {
638         if (entering(tcp))
639                 tprintf("%ld", tcp->u_arg[0]);
640         return 0;
641 }
642
643 int
644 sys_epoll_create1(struct tcb *tcp)
645 {
646         if (entering(tcp))
647                 printflags(open_mode_flags, tcp->u_arg[0], "O_???");
648         return 0;
649 }
650
651 #ifdef HAVE_SYS_EPOLL_H
652 static void
653 print_epoll_event(struct epoll_event *ev)
654 {
655         tprintf("{");
656         printflags(epollevents, ev->events, "EPOLL???");
657         /* We cannot know what format the program uses, so print u32 and u64
658            which will cover every value.  */
659         tprintf(", {u32=%" PRIu32 ", u64=%" PRIu64 "}}",
660                 ev->data.u32, ev->data.u64);
661 }
662 #endif
663
664 int
665 sys_epoll_ctl(struct tcb *tcp)
666 {
667         if (entering(tcp)) {
668                 tprintf("%ld, ", tcp->u_arg[0]);
669                 printxval(epollctls, tcp->u_arg[1], "EPOLL_CTL_???");
670                 tprintf(", %ld, ", tcp->u_arg[2]);
671                 if (tcp->u_arg[3] == 0)
672                         tprintf("NULL");
673                 else {
674 #ifdef HAVE_SYS_EPOLL_H
675                         struct epoll_event ev;
676                         if (umove(tcp, tcp->u_arg[3], &ev) == 0)
677                                 print_epoll_event(&ev);
678                         else
679 #endif
680                                 tprintf("{...}");
681                 }
682         }
683         return 0;
684 }
685
686 static void
687 epoll_wait_common(struct tcb *tcp)
688 {
689         if (entering(tcp))
690                 tprintf("%ld, ", tcp->u_arg[0]);
691         else {
692                 if (syserror(tcp))
693                         tprintf("%lx", tcp->u_arg[1]);
694                 else if (tcp->u_rval == 0)
695                         tprintf("{}");
696                 else {
697 #ifdef HAVE_SYS_EPOLL_H
698                         struct epoll_event ev, *start, *cur, *end;
699                         int failed = 0;
700
701                         tprintf("{");
702                         start = (struct epoll_event *) tcp->u_arg[1];
703                         end = start + tcp->u_rval;
704                         for (cur = start; cur < end; ++cur) {
705                                 if (cur > start)
706                                         tprintf(", ");
707                                 if (umove(tcp, (long) cur, &ev) == 0)
708                                         print_epoll_event(&ev);
709                                 else {
710                                         tprintf("?");
711                                         failed = 1;
712                                         break;
713                                 }
714                         }
715                         tprintf("}");
716                         if (failed)
717                                 tprintf(" %#lx", (long) start);
718 #else
719                         tprintf("{...}");
720 #endif
721                 }
722                 tprintf(", %ld, %ld", tcp->u_arg[2], tcp->u_arg[3]);
723         }
724 }
725
726 int
727 sys_epoll_wait(struct tcb *tcp)
728 {
729         epoll_wait_common(tcp);
730         return 0;
731 }
732
733 int
734 sys_epoll_pwait(struct tcb *tcp)
735 {
736         epoll_wait_common(tcp);
737         if (exiting(tcp))
738                 print_sigset(tcp, tcp->u_arg[4], 0);
739         return 0;
740 }
741
742 int
743 sys_io_setup(struct tcb *tcp)
744 {
745         if (entering(tcp))
746                 tprintf("%ld, ", tcp->u_arg[0]);
747         else {
748                 if (syserror(tcp))
749                         tprintf("0x%0lx", tcp->u_arg[1]);
750                 else {
751                         unsigned long user_id;
752                         if (umove(tcp, tcp->u_arg[1], &user_id) == 0)
753                                 tprintf("{%lu}", user_id);
754                         else
755                                 tprintf("{...}");
756                 }
757         }
758         return 0;
759 }
760
761 int
762 sys_io_destroy(struct tcb *tcp)
763 {
764         if (entering(tcp))
765                 tprintf("%lu", tcp->u_arg[0]);
766         return 0;
767 }
768
769 int
770 sys_io_submit(struct tcb *tcp)
771 {
772         long nr;
773         if (entering(tcp)) {
774                 tprintf("%lu, %ld, ", tcp->u_arg[0], tcp->u_arg[1]);
775                 nr = tcp->u_arg[1];
776                 /* and if nr is negative? */
777                 if (nr == 0)
778                         tprintf("{}");
779                 else {
780 #ifdef HAVE_LIBAIO_H
781                         long i;
782                         struct iocb *iocbp, **iocbs = (void *)tcp->u_arg[2];
783
784                         for (i = 0; i < nr; i++, iocbs++) {
785                                 struct iocb iocb;
786                                 if (i == 0)
787                                         tprintf("{");
788                                 else
789                                         tprintf(", ");
790
791                                 if (umove(tcp, (unsigned long)iocbs, &iocbp) ||
792                                     umove(tcp, (unsigned long)iocbp, &iocb)) {
793                                         tprintf("{...}");
794                                         continue;
795                                 }
796                                 tprintf("{%p, %u, %hu, %hu, %d}",
797                                         iocb.data, iocb.key,
798                                         iocb.aio_lio_opcode,
799                                         iocb.aio_reqprio, iocb.aio_fildes);
800                         }
801                         if (i)
802                                 tprintf("}");
803 #else
804                         tprintf("{...}");
805 #endif
806                 }
807         }
808         return 0;
809 }
810
811 int
812 sys_io_cancel(struct tcb *tcp)
813 {
814         if (entering(tcp)) {
815 #ifdef HAVE_LIBAIO_H
816                 struct iocb iocb;
817 #endif
818                 tprintf("%lu, ", tcp->u_arg[0]);
819 #ifdef HAVE_LIBAIO_H
820                 if (umove(tcp, tcp->u_arg[1], &iocb) == 0) {
821                         tprintf("{%p, %u, %hu, %hu, %d}, ",
822                                 iocb.data, iocb.key,
823                                 iocb.aio_lio_opcode,
824                                 iocb.aio_reqprio, iocb.aio_fildes);
825                 } else
826 #endif
827                         tprintf("{...}, ");
828         } else {
829                 if (tcp->u_rval < 0)
830                         tprintf("{...}");
831                 else {
832 #ifdef HAVE_LIBAIO_H
833                         struct io_event event;
834                         if (umove(tcp, tcp->u_arg[2], &event) == 0)
835                                 tprintf("{%p, %p, %ld, %ld}",
836                                         event.data, event.obj,
837                                         event.res, event.res2);
838                         else
839 #endif
840                                 tprintf("{...}");
841                 }
842         }
843         return 0;
844 }
845
846 int
847 sys_io_getevents(struct tcb *tcp)
848 {
849         if (entering(tcp)) {
850                 tprintf("%ld, %ld, %ld, ", tcp->u_arg[0], tcp->u_arg[1],
851                         tcp->u_arg[2]);
852         } else {
853                 if (tcp->u_rval == 0) {
854                         tprintf("{}");
855                 } else  {
856 #ifdef HAVE_LIBAIO_H
857                         struct io_event *events = (void *)tcp->u_arg[3];
858                         long i, nr = tcp->u_rval;
859
860                         for (i = 0; i < nr; i++, events++) {
861                                 struct io_event event;
862
863                                 if (i == 0)
864                                         tprintf("{");
865                                 else
866                                         tprintf(", ");
867
868                                 if (umove(tcp, (unsigned long)events, &event) != 0) {
869                                         tprintf("{...}");
870                                         continue;
871                                 }
872                                 tprintf("{%p, %p, %ld, %ld}", event.data,
873                                         event.obj, event.res, event.res2);
874                         }
875                         tprintf("}, ");
876 #else
877                                 tprintf("{...}");
878 #endif
879                 }
880
881                 print_timespec(tcp, tcp->u_arg[4]);
882         }
883         return 0;
884 }
885 #endif /* LINUX */
886
887 int
888 sys_select(struct tcb *tcp)
889 {
890         return decode_select(tcp, tcp->u_arg, BITNESS_CURRENT);
891 }
892
893 #ifdef LINUX
894 int
895 sys_pselect6(struct tcb *tcp)
896 {
897         int rc = decode_select(tcp, tcp->u_arg, BITNESS_CURRENT);
898         if (entering(tcp)) {
899                 struct {
900                         void *ss;
901                         unsigned long len;
902                 } data;
903                 if (umove(tcp, tcp->u_arg[5], &data) < 0)
904                         tprintf(", %#lx", tcp->u_arg[5]);
905                 else {
906                         tprintf(", {");
907                         if (data.len < sizeof(long))
908                                 tprintf("%#lx", (long)data.ss);
909                         else
910                                 print_sigset(tcp, (long)data.ss, 0);
911                         tprintf(", %lu}", data.len);
912                 }
913         }
914         return rc;
915 }
916
917 static int
918 do_eventfd(struct tcb *tcp, int flags_arg)
919 {
920         if (entering(tcp)) {
921                 tprintf("%lu", tcp->u_arg[0]);
922                 if (flags_arg >= 0) {
923                         tprintf(", ");
924                         printflags(open_mode_flags, tcp->u_arg[flags_arg], "O_???");
925                 }
926         }
927         return 0;
928 }
929
930 int
931 sys_eventfd(struct tcb *tcp)
932 {
933         return do_eventfd(tcp, -1);
934 }
935
936 int
937 sys_eventfd2(struct tcb *tcp)
938 {
939         return do_eventfd(tcp, 1);
940 }
941 #endif