]> granicus.if.org Git - strace/blob - desc.c
x32: fix build regressions introduced by commit v4.7-96-g8435d67
[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
31 #include "defs.h"
32 #include <fcntl.h>
33 #include <sys/file.h>
34 #ifdef HAVE_SYS_EPOLL_H
35 # include <sys/epoll.h>
36 #endif
37 #ifdef HAVE_LIBAIO_H
38 # include <libaio.h>
39 #endif
40 #ifdef HAVE_LINUX_PERF_EVENT_H
41 # include  <linux/perf_event.h>
42 #endif
43
44 static const struct xlat fcntlcmds[] = {
45         { F_DUPFD,      "F_DUPFD"       },
46         { F_GETFD,      "F_GETFD"       },
47         { F_SETFD,      "F_SETFD"       },
48         { F_GETFL,      "F_GETFL"       },
49         { F_SETFL,      "F_SETFL"       },
50         { F_GETLK,      "F_GETLK"       },
51         { F_SETLK,      "F_SETLK"       },
52         { F_SETLKW,     "F_SETLKW"      },
53         { F_GETOWN,     "F_GETOWN"      },
54         { F_SETOWN,     "F_SETOWN"      },
55 #ifdef F_RSETLK
56         { F_RSETLK,     "F_RSETLK"      },
57 #endif
58 #ifdef F_RSETLKW
59         { F_RSETLKW,    "F_RSETLKW"     },
60 #endif
61 #ifdef F_RGETLK
62         { F_RGETLK,     "F_RGETLK"      },
63 #endif
64 #ifdef F_CNVT
65         { F_CNVT,       "F_CNVT"        },
66 #endif
67 #ifdef F_SETSIG
68         { F_SETSIG,     "F_SETSIG"      },
69 #endif
70 #ifdef F_GETSIG
71         { F_GETSIG,     "F_GETSIG"      },
72 #endif
73 #ifdef F_CHKFL
74         { F_CHKFL,      "F_CHKFL"       },
75 #endif
76 #ifdef F_DUP2FD
77         { F_DUP2FD,     "F_DUP2FD"      },
78 #endif
79 #ifdef F_ALLOCSP
80         { F_ALLOCSP,    "F_ALLOCSP"     },
81 #endif
82 #ifdef F_ISSTREAM
83         { F_ISSTREAM,   "F_ISSTREAM"    },
84 #endif
85 #ifdef F_PRIV
86         { F_PRIV,       "F_PRIV"        },
87 #endif
88 #ifdef F_NPRIV
89         { F_NPRIV,      "F_NPRIV"       },
90 #endif
91 #ifdef F_QUOTACL
92         { F_QUOTACL,    "F_QUOTACL"     },
93 #endif
94 #ifdef F_BLOCKS
95         { F_BLOCKS,     "F_BLOCKS"      },
96 #endif
97 #ifdef F_BLKSIZE
98         { F_BLKSIZE,    "F_BLKSIZE"     },
99 #endif
100 #ifdef F_GETOWN
101         { F_GETOWN,     "F_GETOWN"      },
102 #endif
103 #ifdef F_SETOWN
104         { F_SETOWN,     "F_SETOWN"      },
105 #endif
106 #ifdef F_REVOKE
107         { F_REVOKE,     "F_REVOKE"      },
108 #endif
109 #ifdef F_SETLK
110         { F_SETLK,      "F_SETLK"       },
111 #endif
112 #ifdef F_SETLKW
113         { F_SETLKW,     "F_SETLKW"      },
114 #endif
115 #ifdef F_FREESP
116         { F_FREESP,     "F_FREESP"      },
117 #endif
118 #ifdef F_GETLK
119         { F_GETLK,      "F_GETLK"       },
120 #endif
121 #ifdef F_SETLK64
122         { F_SETLK64,    "F_SETLK64"     },
123 #endif
124 #ifdef F_SETLKW64
125         { F_SETLKW64,   "F_SETLKW64"    },
126 #endif
127 #ifdef F_FREESP64
128         { F_FREESP64,   "F_FREESP64"    },
129 #endif
130 #ifdef F_GETLK64
131         { F_GETLK64,    "F_GETLK64"     },
132 #endif
133 #ifdef F_SHARE
134         { F_SHARE,      "F_SHARE"       },
135 #endif
136 #ifdef F_UNSHARE
137         { F_UNSHARE,    "F_UNSHARE"     },
138 #endif
139 #ifdef F_SETLEASE
140         { F_SETLEASE,   "F_SETLEASE"    },
141 #endif
142 #ifdef F_GETLEASE
143         { F_GETLEASE,   "F_GETLEASE"    },
144 #endif
145 #ifdef F_NOTIFY
146         { F_NOTIFY,     "F_NOTIFY"      },
147 #endif
148 #ifdef F_DUPFD_CLOEXEC
149         { F_DUPFD_CLOEXEC,"F_DUPFD_CLOEXEC"},
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 #ifdef F_NOTIFY
187 static const struct xlat notifyflags[] = {
188 #ifdef DN_ACCESS
189         { DN_ACCESS,    "DN_ACCESS"     },
190 #endif
191 #ifdef DN_MODIFY
192         { DN_MODIFY,    "DN_MODIFY"     },
193 #endif
194 #ifdef DN_CREATE
195         { DN_CREATE,    "DN_CREATE"     },
196 #endif
197 #ifdef DN_DELETE
198         { DN_DELETE,    "DN_DELETE"     },
199 #endif
200 #ifdef DN_RENAME
201         { DN_RENAME,    "DN_RENAME"     },
202 #endif
203 #ifdef DN_ATTRIB
204         { DN_ATTRIB,    "DN_ATTRIB"     },
205 #endif
206 #ifdef DN_MULTISHOT
207         { DN_MULTISHOT, "DN_MULTISHOT"  },
208 #endif
209         { 0,            NULL            },
210 };
211 #endif
212
213 static const struct xlat perf_event_open_flags[] = {
214 #ifdef PERF_FLAG_FD_NO_GROUP
215         { PERF_FLAG_FD_NO_GROUP,        "PERF_FLAG_FD_NO_GROUP" },
216 #endif
217 #ifdef PERF_FLAG_FD_OUTPUT
218         { PERF_FLAG_FD_OUTPUT,          "PERF_FLAG_FD_OUTPUT"   },
219 #endif
220 #ifdef PERF_FLAG_PID_CGROUP
221         { PERF_FLAG_PID_CGROUP,         "PERF_FLAG_PID_CGROUP"  },
222 #endif
223         { 0,                            NULL                    },
224 };
225
226 #if _LFS64_LARGEFILE
227 /* fcntl/lockf */
228 static void
229 printflock64(struct tcb *tcp, long addr, int getlk)
230 {
231         struct flock64 fl;
232
233         if (umove(tcp, addr, &fl) < 0) {
234                 tprints("{...}");
235                 return;
236         }
237         tprints("{type=");
238         printxval(lockfcmds, fl.l_type, "F_???");
239         tprints(", whence=");
240         printxval(whence_codes, fl.l_whence, "SEEK_???");
241         tprintf(", start=%lld, len=%lld", (long long) fl.l_start, (long long) fl.l_len);
242         if (getlk)
243                 tprintf(", pid=%lu}", (unsigned long) fl.l_pid);
244         else
245                 tprints("}");
246 }
247 #endif
248
249 /* fcntl/lockf */
250 static void
251 printflock(struct tcb *tcp, long addr, int getlk)
252 {
253         struct flock fl;
254
255 #if SUPPORTED_PERSONALITIES > 1
256 # ifdef X32
257         if (current_personality == 0) {
258                 printflock64(tcp, addr, getlk);
259                 return;
260         }
261 # endif
262         if (current_wordsize != sizeof(fl.l_start)) {
263                 if (current_wordsize == 4) {
264                         /* 32-bit x86 app on x86_64 and similar cases */
265                         struct {
266                                 short int l_type;
267                                 short int l_whence;
268                                 int32_t l_start; /* off_t */
269                                 int32_t l_len; /* off_t */
270                                 int32_t l_pid; /* pid_t */
271                         } fl32;
272                         if (umove(tcp, addr, &fl32) < 0) {
273                                 tprints("{...}");
274                                 return;
275                         }
276                         fl.l_type = fl32.l_type;
277                         fl.l_whence = fl32.l_whence;
278                         fl.l_start = fl32.l_start;
279                         fl.l_len = fl32.l_len;
280                         fl.l_pid = fl32.l_pid;
281                 } else {
282                         /* let people know we have a problem here */
283                         tprintf("<decode error: unsupported wordsize %d>",
284                                 current_wordsize);
285                         return;
286                 }
287         } else
288 #endif
289         {
290                 if (umove(tcp, addr, &fl) < 0) {
291                         tprints("{...}");
292                         return;
293                 }
294         }
295         tprints("{type=");
296         printxval(lockfcmds, fl.l_type, "F_???");
297         tprints(", whence=");
298         printxval(whence_codes, fl.l_whence, "SEEK_???");
299 #ifdef X32
300         tprintf(", start=%lld, len=%lld", fl.l_start, fl.l_len);
301 #else
302         tprintf(", start=%ld, len=%ld", fl.l_start, fl.l_len);
303 #endif
304         if (getlk)
305                 tprintf(", pid=%lu}", (unsigned long) fl.l_pid);
306         else
307                 tprints("}");
308 }
309
310 int
311 sys_fcntl(struct tcb *tcp)
312 {
313         if (entering(tcp)) {
314                 printfd(tcp, tcp->u_arg[0]);
315                 tprints(", ");
316                 printxval(fcntlcmds, tcp->u_arg[1], "F_???");
317                 switch (tcp->u_arg[1]) {
318                 case F_SETFD:
319                         tprints(", ");
320                         printflags(fdflags, tcp->u_arg[2], "FD_???");
321                         break;
322                 case F_SETOWN: case F_DUPFD:
323 #ifdef F_DUPFD_CLOEXEC
324                 case F_DUPFD_CLOEXEC:
325 #endif
326                         tprintf(", %ld", tcp->u_arg[2]);
327                         break;
328                 case F_SETFL:
329                         tprints(", ");
330                         tprint_open_modes(tcp->u_arg[2]);
331                         break;
332                 case F_SETLK: case F_SETLKW:
333 #ifdef F_FREESP
334                 case F_FREESP:
335 #endif
336                         tprints(", ");
337                         printflock(tcp, tcp->u_arg[2], 0);
338                         break;
339 #if _LFS64_LARGEFILE
340 #ifdef F_FREESP64
341                 case F_FREESP64:
342 #endif
343                 /* Linux glibc defines SETLK64 as SETLK,
344                    even though the kernel has different values - as does Solaris. */
345 #if defined(F_SETLK64) && F_SETLK64 + 0 != F_SETLK
346                 case F_SETLK64:
347 #endif
348 #if defined(F_SETLKW64) && F_SETLKW64 + 0 != F_SETLKW
349                 case F_SETLKW64:
350 #endif
351                         tprints(", ");
352                         printflock64(tcp, tcp->u_arg[2], 0);
353                         break;
354 #endif
355 #ifdef F_NOTIFY
356                 case F_NOTIFY:
357                         tprints(", ");
358                         printflags(notifyflags, tcp->u_arg[2], "DN_???");
359                         break;
360 #endif
361 #ifdef F_SETLEASE
362                 case F_SETLEASE:
363                         tprints(", ");
364                         printxval(lockfcmds, tcp->u_arg[2], "F_???");
365                         break;
366 #endif
367                 }
368         }
369         else {
370                 switch (tcp->u_arg[1]) {
371                 case F_DUPFD:
372 #ifdef F_DUPFD_CLOEXEC
373                 case F_DUPFD_CLOEXEC:
374 #endif
375                 case F_SETFD: case F_SETFL:
376                 case F_SETLK: case F_SETLKW:
377                 case F_SETOWN: case F_GETOWN:
378 #ifdef F_NOTIFY
379                 case F_NOTIFY:
380 #endif
381 #ifdef F_SETLEASE
382                 case F_SETLEASE:
383 #endif
384                         break;
385                 case F_GETFD:
386                         if (syserror(tcp) || tcp->u_rval == 0)
387                                 return 0;
388                         tcp->auxstr = sprintflags("flags ", fdflags, tcp->u_rval);
389                         return RVAL_HEX|RVAL_STR;
390                 case F_GETFL:
391                         if (syserror(tcp))
392                                 return 0;
393                         tcp->auxstr = sprint_open_modes(tcp->u_rval);
394                         return RVAL_HEX|RVAL_STR;
395                 case F_GETLK:
396                         tprints(", ");
397                         printflock(tcp, tcp->u_arg[2], 1);
398                         break;
399 #if _LFS64_LARGEFILE
400 #if defined(F_GETLK64) && F_GETLK64+0 != F_GETLK
401                 case F_GETLK64:
402 #endif
403                         tprints(", ");
404                         printflock64(tcp, tcp->u_arg[2], 1);
405                         break;
406 #endif
407 #ifdef F_GETLEASE
408                 case F_GETLEASE:
409                         if (syserror(tcp))
410                                 return 0;
411                         tcp->auxstr = xlookup(lockfcmds, tcp->u_rval);
412                         return RVAL_HEX|RVAL_STR;
413 #endif
414                 default:
415                         tprintf(", %#lx", tcp->u_arg[2]);
416                         break;
417                 }
418         }
419         return 0;
420 }
421
422 #ifdef LOCK_SH
423
424 int
425 sys_flock(struct tcb *tcp)
426 {
427         if (entering(tcp)) {
428                 printfd(tcp, tcp->u_arg[0]);
429                 tprints(", ");
430                 printflags(flockcmds, tcp->u_arg[1], "LOCK_???");
431         }
432         return 0;
433 }
434 #endif /* LOCK_SH */
435
436 int
437 sys_close(struct tcb *tcp)
438 {
439         if (entering(tcp)) {
440                 printfd(tcp, tcp->u_arg[0]);
441         }
442         return 0;
443 }
444
445 static int
446 do_dup2(struct tcb *tcp, int flags_arg)
447 {
448         if (entering(tcp)) {
449                 printfd(tcp, tcp->u_arg[0]);
450                 tprints(", ");
451                 printfd(tcp, tcp->u_arg[1]);
452                 if (flags_arg >= 0) {
453                         tprints(", ");
454                         printflags(open_mode_flags, tcp->u_arg[flags_arg], "O_???");
455                 }
456         }
457         return 0;
458 }
459
460 int
461 sys_dup2(struct tcb *tcp)
462 {
463         return do_dup2(tcp, -1);
464 }
465
466 int
467 sys_dup3(struct tcb *tcp)
468 {
469         return do_dup2(tcp, 2);
470 }
471
472 #if defined(ALPHA)
473 int
474 sys_getdtablesize(struct tcb *tcp)
475 {
476         return 0;
477 }
478 #endif
479
480 static int
481 decode_select(struct tcb *tcp, long *args, enum bitness_t bitness)
482 {
483         int i, j;
484         unsigned nfds, fdsize;
485         fd_set *fds;
486         const char *sep;
487         long arg;
488
489         fdsize = args[0];
490         /* Beware of select(2^31-1, NULL, NULL, NULL) and similar... */
491         if (args[0] > 1024*1024)
492                 fdsize = 1024*1024;
493         if (args[0] < 0)
494                 fdsize = 0;
495         fdsize = (((fdsize + 7) / 8) + sizeof(long)-1) & -sizeof(long);
496
497         if (entering(tcp)) {
498                 fds = malloc(fdsize);
499                 if (!fds)
500                         die_out_of_memory();
501                 nfds = args[0];
502                 tprintf("%d", nfds);
503                 for (i = 0; i < 3; i++) {
504                         arg = args[i+1];
505                         if (arg == 0) {
506                                 tprints(", NULL");
507                                 continue;
508                         }
509                         if (!verbose(tcp)) {
510                                 tprintf(", %#lx", arg);
511                                 continue;
512                         }
513                         if (umoven(tcp, arg, fdsize, (char *) fds) < 0) {
514                                 tprints(", [?]");
515                                 continue;
516                         }
517                         tprints(", [");
518                         for (j = 0, sep = ""; j < nfds; j++) {
519                                 if (FD_ISSET(j, fds)) {
520                                         tprints(sep);
521                                         printfd(tcp, j);
522                                         sep = " ";
523                                 }
524                         }
525                         tprints("]");
526                 }
527                 free(fds);
528                 tprints(", ");
529                 printtv_bitness(tcp, args[4], bitness, 0);
530         }
531         else {
532                 static char outstr[1024];
533                 char *outptr;
534 #define end_outstr (outstr + sizeof(outstr))
535                 const char *sep;
536
537                 if (syserror(tcp))
538                         return 0;
539
540                 nfds = tcp->u_rval;
541                 if (nfds == 0) {
542                         tcp->auxstr = "Timeout";
543                         return RVAL_STR;
544                 }
545
546                 fds = malloc(fdsize);
547                 if (!fds)
548                         die_out_of_memory();
549
550                 outptr = outstr;
551                 sep = "";
552                 for (i = 0; i < 3; i++) {
553                         int first = 1;
554
555                         arg = args[i+1];
556                         if (!arg || umoven(tcp, arg, fdsize, (char *) fds) < 0)
557                                 continue;
558                         for (j = 0; j < args[0]; j++) {
559                                 if (FD_ISSET(j, fds)) {
560                                         /* +2 chars needed at the end: ']',NUL */
561                                         if (outptr < end_outstr - (sizeof(", except [") + sizeof(int)*3 + 2)) {
562                                                 if (first) {
563                                                         outptr += sprintf(outptr, "%s%s [%u",
564                                                                 sep,
565                                                                 i == 0 ? "in" : i == 1 ? "out" : "except",
566                                                                 j
567                                                         );
568                                                         first = 0;
569                                                         sep = ", ";
570                                                 }
571                                                 else {
572                                                         outptr += sprintf(outptr, " %u", j);
573                                                 }
574                                         }
575                                         nfds--;
576                                 }
577                         }
578                         if (outptr != outstr)
579                                 *outptr++ = ']';
580                         if (nfds == 0)
581                                 break;
582                 }
583                 free(fds);
584                 /* This contains no useful information on SunOS.  */
585                 if (args[4]) {
586                         if (outptr < end_outstr - (10 + TIMEVAL_TEXT_BUFSIZE)) {
587                                 outptr += sprintf(outptr, "%sleft ", sep);
588                                 outptr = sprinttv(outptr, tcp, args[4], bitness, /*special:*/ 0);
589                         }
590                 }
591                 *outptr = '\0';
592                 tcp->auxstr = outstr;
593                 return RVAL_STR;
594 #undef end_outstr
595         }
596         return 0;
597 }
598
599 int
600 sys_oldselect(struct tcb *tcp)
601 {
602         long args[5];
603
604         if (umoven(tcp, tcp->u_arg[0], sizeof args, (char *) args) < 0) {
605                 tprints("[...]");
606                 return 0;
607         }
608         return decode_select(tcp, args, BITNESS_CURRENT);
609 }
610
611 #ifdef ALPHA
612 int
613 sys_osf_select(struct tcb *tcp)
614 {
615         long *args = tcp->u_arg;
616         return decode_select(tcp, args, BITNESS_32);
617 }
618 #endif
619
620 static const struct xlat epollctls[] = {
621 #ifdef EPOLL_CTL_ADD
622         { EPOLL_CTL_ADD,        "EPOLL_CTL_ADD" },
623 #endif
624 #ifdef EPOLL_CTL_MOD
625         { EPOLL_CTL_MOD,        "EPOLL_CTL_MOD" },
626 #endif
627 #ifdef EPOLL_CTL_DEL
628         { EPOLL_CTL_DEL,        "EPOLL_CTL_DEL" },
629 #endif
630         { 0,                    NULL            }
631 };
632
633 static const struct xlat epollevents[] = {
634 #ifdef EPOLLIN
635         { EPOLLIN,      "EPOLLIN"       },
636 #endif
637 #ifdef EPOLLPRI
638         { EPOLLPRI,     "EPOLLPRI"      },
639 #endif
640 #ifdef EPOLLOUT
641         { EPOLLOUT,     "EPOLLOUT"      },
642 #endif
643 #ifdef EPOLLRDNORM
644         { EPOLLRDNORM,  "EPOLLRDNORM"   },
645 #endif
646 #ifdef EPOLLRDBAND
647         { EPOLLRDBAND,  "EPOLLRDBAND"   },
648 #endif
649 #ifdef EPOLLWRNORM
650         { EPOLLWRNORM,  "EPOLLWRNORM"   },
651 #endif
652 #ifdef EPOLLWRBAND
653         { EPOLLWRBAND,  "EPOLLWRBAND"   },
654 #endif
655 #ifdef EPOLLMSG
656         { EPOLLMSG,     "EPOLLMSG"      },
657 #endif
658 #ifdef EPOLLERR
659         { EPOLLERR,     "EPOLLERR"      },
660 #endif
661 #ifdef EPOLLHUP
662         { EPOLLHUP,     "EPOLLHUP"      },
663 #endif
664 #ifdef EPOLLRDHUP
665         { EPOLLRDHUP,   "EPOLLRDHUP"    },
666 #endif
667 #ifdef EPOLLONESHOT
668         { EPOLLONESHOT, "EPOLLONESHOT"  },
669 #endif
670 #ifdef EPOLLET
671         { EPOLLET,      "EPOLLET"       },
672 #endif
673         { 0,            NULL            }
674 };
675
676 /* Not aliased to printargs_ld: we want it to have a distinct address */
677 int
678 sys_epoll_create(struct tcb *tcp)
679 {
680         return printargs_ld(tcp);
681 }
682
683 static const struct xlat epollflags[] = {
684 #ifdef EPOLL_CLOEXEC
685         { EPOLL_CLOEXEC,        "EPOLL_CLOEXEC" },
686 #endif
687 #ifdef EPOLL_NONBLOCK
688         { EPOLL_NONBLOCK,       "EPOLL_NONBLOCK"        },
689 #endif
690         { 0,            NULL            }
691 };
692
693 int
694 sys_epoll_create1(struct tcb *tcp)
695 {
696         if (entering(tcp))
697                 printflags(epollflags, tcp->u_arg[0], "EPOLL_???");
698         return 0;
699 }
700
701 #ifdef HAVE_SYS_EPOLL_H
702 static void
703 print_epoll_event(struct epoll_event *ev)
704 {
705         tprints("{");
706         printflags(epollevents, ev->events, "EPOLL???");
707         /* We cannot know what format the program uses, so print u32 and u64
708            which will cover every value.  */
709         tprintf(", {u32=%" PRIu32 ", u64=%" PRIu64 "}}",
710                 ev->data.u32, ev->data.u64);
711 }
712 #endif
713
714 int
715 sys_epoll_ctl(struct tcb *tcp)
716 {
717         if (entering(tcp)) {
718                 printfd(tcp, tcp->u_arg[0]);
719                 tprints(", ");
720                 printxval(epollctls, tcp->u_arg[1], "EPOLL_CTL_???");
721                 tprints(", ");
722                 printfd(tcp, tcp->u_arg[2]);
723                 tprints(", ");
724                 if (tcp->u_arg[3] == 0)
725                         tprints("NULL");
726                 else {
727 #ifdef HAVE_SYS_EPOLL_H
728                         struct epoll_event ev;
729                         if (umove(tcp, tcp->u_arg[3], &ev) == 0)
730                                 print_epoll_event(&ev);
731                         else
732 #endif
733                                 tprints("{...}");
734                 }
735         }
736         return 0;
737 }
738
739 static void
740 epoll_wait_common(struct tcb *tcp)
741 {
742         if (entering(tcp)) {
743                 printfd(tcp, tcp->u_arg[0]);
744                 tprints(", ");
745         } else {
746                 if (syserror(tcp))
747                         tprintf("%lx", tcp->u_arg[1]);
748                 else if (tcp->u_rval == 0)
749                         tprints("{}");
750                 else {
751 #ifdef HAVE_SYS_EPOLL_H
752                         struct epoll_event ev, *start, *cur, *end;
753                         int failed = 0;
754
755                         tprints("{");
756                         start = (struct epoll_event *) tcp->u_arg[1];
757                         end = start + tcp->u_rval;
758                         for (cur = start; cur < end; ++cur) {
759                                 if (cur > start)
760                                         tprints(", ");
761                                 if (umove(tcp, (long) cur, &ev) == 0)
762                                         print_epoll_event(&ev);
763                                 else {
764                                         tprints("?");
765                                         failed = 1;
766                                         break;
767                                 }
768                         }
769                         tprints("}");
770                         if (failed)
771                                 tprintf(" %#lx", (long) start);
772 #else
773                         tprints("{...}");
774 #endif
775                 }
776                 tprintf(", %d, %d", (int) tcp->u_arg[2], (int) tcp->u_arg[3]);
777         }
778 }
779
780 int
781 sys_epoll_wait(struct tcb *tcp)
782 {
783         epoll_wait_common(tcp);
784         return 0;
785 }
786
787 int
788 sys_epoll_pwait(struct tcb *tcp)
789 {
790         epoll_wait_common(tcp);
791         if (exiting(tcp)) {
792                 tprints(", ");
793                 print_sigset(tcp, tcp->u_arg[4], 0);
794         }
795         return 0;
796 }
797
798 int
799 sys_io_setup(struct tcb *tcp)
800 {
801         if (entering(tcp))
802                 tprintf("%ld, ", tcp->u_arg[0]);
803         else {
804                 if (syserror(tcp))
805                         tprintf("0x%0lx", tcp->u_arg[1]);
806                 else {
807                         unsigned long user_id;
808                         if (umove(tcp, tcp->u_arg[1], &user_id) == 0)
809                                 tprintf("{%lu}", user_id);
810                         else
811                                 tprints("{...}");
812                 }
813         }
814         return 0;
815 }
816
817 int
818 sys_io_destroy(struct tcb *tcp)
819 {
820         if (entering(tcp))
821                 tprintf("%lu", tcp->u_arg[0]);
822         return 0;
823 }
824
825 #ifdef HAVE_LIBAIO_H
826
827 enum iocb_sub {
828         SUB_NONE, SUB_COMMON, SUB_POLL, SUB_VECTOR
829 };
830
831 static const char *
832 iocb_cmd_lookup(unsigned cmd, enum iocb_sub *sub)
833 {
834         static char buf[sizeof("%u /* SUB_??? */") + sizeof(int)*3];
835         static const struct {
836                 const char *name;
837                 enum iocb_sub sub;
838         } cmds[] = {
839                 { "pread", SUB_COMMON },
840                 { "pwrite", SUB_COMMON },
841                 { "fsync", SUB_NONE },
842                 { "fdsync", SUB_NONE },
843                 { "op4", SUB_NONE },
844                 { "poll", SUB_POLL },
845                 { "noop", SUB_NONE },
846                 { "preadv", SUB_VECTOR },
847                 { "pwritev", SUB_VECTOR },
848         };
849
850         if (cmd < ARRAY_SIZE(cmds)) {
851                 *sub = cmds[cmd].sub;
852                 return cmds[cmd].name;
853         }
854         *sub = SUB_NONE;
855         sprintf(buf, "%u /* SUB_??? */", cmd);
856         return buf;
857 }
858
859 /* Not defined in libaio.h */
860 #ifndef IOCB_RESFD
861 # define IOCB_RESFD (1 << 0)
862 #endif
863
864 static void
865 print_common_flags(struct iocb *iocb)
866 {
867 #if HAVE_STRUCT_IOCB_U_C_FLAGS
868         if (iocb->u.c.flags & IOCB_RESFD)
869                 tprintf(", resfd=%d", iocb->u.c.resfd);
870         if (iocb->u.c.flags & ~IOCB_RESFD)
871                 tprintf(", flags=%x", iocb->u.c.flags);
872 #else
873 # warning "libaio.h is too old => limited io_submit decoding"
874 #endif
875 }
876
877 #endif /* HAVE_LIBAIO_H */
878
879 int
880 sys_io_submit(struct tcb *tcp)
881 {
882         long nr;
883         if (entering(tcp)) {
884                 tprintf("%lu, %ld, ", tcp->u_arg[0], tcp->u_arg[1]);
885                 nr = tcp->u_arg[1];
886                 /* and if nr is negative? */
887                 if (nr == 0)
888                         tprints("{}");
889                 else {
890 #ifdef HAVE_LIBAIO_H
891                         long i;
892                         struct iocb *iocbp, **iocbs = (void *)tcp->u_arg[2];
893
894                         for (i = 0; i < nr; i++, iocbs++) {
895                                 enum iocb_sub sub;
896                                 struct iocb iocb;
897                                 if (i == 0)
898                                         tprints("{");
899                                 else
900                                         tprints(", ");
901
902                                 if (umove(tcp, (unsigned long)iocbs, &iocbp) ||
903                                     umove(tcp, (unsigned long)iocbp, &iocb)) {
904                                         tprints("{...}");
905                                         continue;
906                                 }
907                                 tprints("{");
908                                 if (iocb.data)
909                                         tprintf("data:%p, ", iocb.data);
910                                 if (iocb.key)
911                                         tprintf("key:%u, ", iocb.key);
912                                 tprintf("%s, ", iocb_cmd_lookup(iocb.aio_lio_opcode, &sub));
913                                 if (iocb.aio_reqprio)
914                                         tprintf("reqprio:%d, ", iocb.aio_reqprio);
915                                 tprintf("filedes:%d", iocb.aio_fildes);
916                                 switch (sub) {
917                                 case SUB_COMMON:
918 #if HAVE_DECL_IO_CMD_PWRITE
919                                         if (iocb.aio_lio_opcode == IO_CMD_PWRITE) {
920                                                 tprints(", str:");
921                                                 printstr(tcp, (unsigned long)iocb.u.c.buf,
922                                                          iocb.u.c.nbytes);
923                                         } else
924 #endif
925                                                 tprintf(", buf:%p", iocb.u.c.buf);
926                                         tprintf(", nbytes:%lu, offset:%lld",
927                                                 iocb.u.c.nbytes,
928                                                 iocb.u.c.offset);
929                                         print_common_flags(&iocb);
930                                         break;
931                                 case SUB_VECTOR:
932                                         tprintf(", %lld", iocb.u.v.offset);
933                                         print_common_flags(&iocb);
934                                         tprints(", ");
935                                         tprint_iov(tcp, iocb.u.v.nr,
936                                                    (unsigned long)iocb.u.v.vec,
937 #if HAVE_DECL_IO_CMD_PWRITEV
938                                                    iocb.aio_lio_opcode == IO_CMD_PWRITEV
939 #else
940                                                    0
941 #endif
942                                                   );
943                                         break;
944                                 case SUB_POLL:
945                                         tprintf(", %x", iocb.u.poll.events);
946                                         break;
947                                 case SUB_NONE:
948                                         break;
949                                 }
950                                 tprints("}");
951                         }
952                         if (i)
953                                 tprints("}");
954 #else
955 #warning "libaio.h is not available => no io_submit decoding"
956                         tprintf("%#lx", tcp->u_arg[2]);
957 #endif
958                 }
959         }
960         return 0;
961 }
962
963 int
964 sys_io_cancel(struct tcb *tcp)
965 {
966         if (entering(tcp)) {
967 #ifdef HAVE_LIBAIO_H
968                 struct iocb iocb;
969 #endif
970                 tprintf("%lu, ", tcp->u_arg[0]);
971 #ifdef HAVE_LIBAIO_H
972                 if (umove(tcp, tcp->u_arg[1], &iocb) == 0) {
973                         tprintf("{%p, %u, %u, %u, %d}, ",
974                                 iocb.data, iocb.key,
975                                 (unsigned)iocb.aio_lio_opcode,
976                                 (unsigned)iocb.aio_reqprio, iocb.aio_fildes);
977                 } else
978 #endif
979                         tprints("{...}, ");
980         } else {
981                 if (tcp->u_rval < 0)
982                         tprints("{...}");
983                 else {
984 #ifdef HAVE_LIBAIO_H
985                         struct io_event event;
986                         if (umove(tcp, tcp->u_arg[2], &event) == 0)
987                                 tprintf("{%p, %p, %ld, %ld}",
988                                         event.data, event.obj,
989                                         event.res, event.res2);
990                         else
991 #endif
992                                 tprints("{...}");
993                 }
994         }
995         return 0;
996 }
997
998 int
999 sys_io_getevents(struct tcb *tcp)
1000 {
1001         if (entering(tcp)) {
1002                 tprintf("%ld, %ld, %ld, ", tcp->u_arg[0], tcp->u_arg[1],
1003                         tcp->u_arg[2]);
1004         } else {
1005                 if (tcp->u_rval == 0) {
1006                         tprints("{}");
1007                 } else {
1008 #ifdef HAVE_LIBAIO_H
1009                         struct io_event *events = (void *)tcp->u_arg[3];
1010                         long i, nr = tcp->u_rval;
1011
1012                         for (i = 0; i < nr; i++, events++) {
1013                                 struct io_event event;
1014
1015                                 if (i == 0)
1016                                         tprints("{");
1017                                 else
1018                                         tprints(", ");
1019
1020                                 if (umove(tcp, (unsigned long)events, &event) != 0) {
1021                                         tprints("{...}");
1022                                         continue;
1023                                 }
1024                                 tprintf("{%p, %p, %ld, %ld}", event.data,
1025                                         event.obj, event.res, event.res2);
1026                         }
1027                         tprints("}, ");
1028 #else
1029                         tprints("{...}");
1030 #endif
1031                 }
1032
1033                 print_timespec(tcp, tcp->u_arg[4]);
1034         }
1035         return 0;
1036 }
1037
1038 int
1039 sys_select(struct tcb *tcp)
1040 {
1041         return decode_select(tcp, tcp->u_arg, BITNESS_CURRENT);
1042 }
1043
1044 int
1045 sys_pselect6(struct tcb *tcp)
1046 {
1047         int rc = decode_select(tcp, tcp->u_arg, BITNESS_CURRENT);
1048         if (entering(tcp)) {
1049                 struct {
1050                         void *ss;
1051                         unsigned long len;
1052                 } data;
1053                 if (umove(tcp, tcp->u_arg[5], &data) < 0)
1054                         tprintf(", %#lx", tcp->u_arg[5]);
1055                 else {
1056                         tprints(", {");
1057                         if (data.len < sizeof(long))
1058                                 tprintf("%#lx", (long)data.ss);
1059                         else
1060                                 print_sigset(tcp, (long)data.ss, 0);
1061                         tprintf(", %lu}", data.len);
1062                 }
1063         }
1064         return rc;
1065 }
1066
1067 static int
1068 do_eventfd(struct tcb *tcp, int flags_arg)
1069 {
1070         if (entering(tcp)) {
1071                 tprintf("%lu", tcp->u_arg[0]);
1072                 if (flags_arg >= 0) {
1073                         tprints(", ");
1074                         printflags(open_mode_flags, tcp->u_arg[flags_arg], "O_???");
1075                 }
1076         }
1077         return 0;
1078 }
1079
1080 int
1081 sys_eventfd(struct tcb *tcp)
1082 {
1083         return do_eventfd(tcp, -1);
1084 }
1085
1086 int
1087 sys_eventfd2(struct tcb *tcp)
1088 {
1089         return do_eventfd(tcp, 1);
1090 }
1091
1092 int
1093 sys_perf_event_open(struct tcb *tcp)
1094 {
1095         if (entering(tcp)) {
1096                 tprintf("%#lx, %d, %d, %d, ",
1097                         tcp->u_arg[0],
1098                         (int) tcp->u_arg[1],
1099                         (int) tcp->u_arg[2],
1100                         (int) tcp->u_arg[3]);
1101                 printflags(perf_event_open_flags, tcp->u_arg[4],
1102                            "PERF_FLAG_???");
1103         }
1104         return 0;
1105 }