desc.c revision c2982b5b72335205849265182b23866ffbe7a16c
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 44static 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 154static 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 163static 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 173static 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 187static 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 213static 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 */ 228static void 229printflock64(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 */ 250static void 251printflock(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 310int 311sys_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 424int 425sys_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 436int 437sys_close(struct tcb *tcp) 438{ 439 if (entering(tcp)) { 440 printfd(tcp, tcp->u_arg[0]); 441 } 442 return 0; 443} 444 445static int 446do_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 460int 461sys_dup2(struct tcb *tcp) 462{ 463 return do_dup2(tcp, -1); 464} 465 466int 467sys_dup3(struct tcb *tcp) 468{ 469 return do_dup2(tcp, 2); 470} 471 472#if defined(ALPHA) 473int 474sys_getdtablesize(struct tcb *tcp) 475{ 476 return 0; 477} 478#endif 479 480static int 481fd_isset(int d, fd_set *fds) 482{ 483 const int bpl = 8 * sizeof(long); 484 long *s = (long *) fds; 485 return !!(s[d / bpl] & (1L << (d % bpl))); 486} 487 488static int 489decode_select(struct tcb *tcp, long *args, enum bitness_t bitness) 490{ 491 int i, j; 492 int nfds, fdsize; 493 fd_set *fds; 494 const char *sep; 495 long arg; 496 497 /* Kernel truncates arg[0] to int, we do the same. */ 498 nfds = (int) args[0]; 499 500 /* Kernel rejects negative nfds, so we don't parse it either. */ 501 if (nfds < 0) { 502 nfds = 0; 503 fds = NULL; 504 } 505 /* Beware of select(2^31-1, NULL, NULL, NULL) and similar... */ 506 if (nfds > 1024*1024) 507 nfds = 1024*1024; 508 509 /* 510 * We had bugs a-la "while (j < args[0])" and "umoven(args[0])" below. 511 * Instead of args[0], use nfds for fd count, fdsize for array lengths. 512 */ 513 fdsize = (((nfds + 7) / 8) + sizeof(long)-1) & -sizeof(long); 514 515 if (entering(tcp)) { 516 tprintf("%d", (int) args[0]); 517 518 if (fdsize > 0) { 519 fds = malloc(fdsize); 520 if (!fds) 521 die_out_of_memory(); 522 } 523 for (i = 0; i < 3; i++) { 524 arg = args[i+1]; 525 if (arg == 0) { 526 tprints(", NULL"); 527 continue; 528 } 529 if (!verbose(tcp) || !fds) { 530 tprintf(", %#lx", arg); 531 continue; 532 } 533 if (umoven(tcp, arg, fdsize, (char *) fds) < 0) { 534 tprints(", [?]"); 535 continue; 536 } 537 tprints(", ["); 538 for (j = 0, sep = ""; j < nfds; j++) { 539 if (fd_isset(j, fds)) { 540 tprints(sep); 541 printfd(tcp, j); 542 sep = " "; 543 } 544 } 545 tprints("]"); 546 } 547 free(fds); 548 tprints(", "); 549 printtv_bitness(tcp, args[4], bitness, 0); 550 } 551 else { 552 static char outstr[1024]; 553 char *outptr; 554#define end_outstr (outstr + sizeof(outstr)) 555 int ready_fds; 556 557 if (syserror(tcp)) 558 return 0; 559 560 ready_fds = tcp->u_rval; 561 if (ready_fds == 0) { 562 tcp->auxstr = "Timeout"; 563 return RVAL_STR; 564 } 565 566 fds = malloc(fdsize); 567 if (!fds) 568 die_out_of_memory(); 569 570 outptr = outstr; 571 sep = ""; 572 for (i = 0; i < 3 && ready_fds > 0; i++) { 573 int first = 1; 574 575 arg = args[i+1]; 576 if (!arg || umoven(tcp, arg, fdsize, (char *) fds) < 0) 577 continue; 578 for (j = 0; j < nfds; j++) { 579 if (fd_isset(j, fds)) { 580 /* +2 chars needed at the end: ']',NUL */ 581 if (outptr < end_outstr - (sizeof(", except [") + sizeof(int)*3 + 2)) { 582 if (first) { 583 outptr += sprintf(outptr, "%s%s [%u", 584 sep, 585 i == 0 ? "in" : i == 1 ? "out" : "except", 586 j 587 ); 588 first = 0; 589 sep = ", "; 590 } 591 else { 592 outptr += sprintf(outptr, " %u", j); 593 } 594 } 595 if (--ready_fds == 0) 596 break; 597 } 598 } 599 if (outptr != outstr) 600 *outptr++ = ']'; 601 } 602 free(fds); 603 /* This contains no useful information on SunOS. */ 604 if (args[4]) { 605 if (outptr < end_outstr - (10 + TIMEVAL_TEXT_BUFSIZE)) { 606 outptr += sprintf(outptr, "%sleft ", sep); 607 outptr = sprinttv(outptr, tcp, args[4], bitness, /*special:*/ 0); 608 } 609 } 610 *outptr = '\0'; 611 tcp->auxstr = outstr; 612 return RVAL_STR; 613#undef end_outstr 614 } 615 return 0; 616} 617 618int 619sys_oldselect(struct tcb *tcp) 620{ 621 long args[5]; 622 623 if (umoven(tcp, tcp->u_arg[0], sizeof args, (char *) args) < 0) { 624 tprints("[...]"); 625 return 0; 626 } 627 return decode_select(tcp, args, BITNESS_CURRENT); 628} 629 630#ifdef ALPHA 631int 632sys_osf_select(struct tcb *tcp) 633{ 634 long *args = tcp->u_arg; 635 return decode_select(tcp, args, BITNESS_32); 636} 637#endif 638 639static const struct xlat epollctls[] = { 640#ifdef EPOLL_CTL_ADD 641 { EPOLL_CTL_ADD, "EPOLL_CTL_ADD" }, 642#endif 643#ifdef EPOLL_CTL_MOD 644 { EPOLL_CTL_MOD, "EPOLL_CTL_MOD" }, 645#endif 646#ifdef EPOLL_CTL_DEL 647 { EPOLL_CTL_DEL, "EPOLL_CTL_DEL" }, 648#endif 649 { 0, NULL } 650}; 651 652static const struct xlat epollevents[] = { 653#ifdef EPOLLIN 654 { EPOLLIN, "EPOLLIN" }, 655#endif 656#ifdef EPOLLPRI 657 { EPOLLPRI, "EPOLLPRI" }, 658#endif 659#ifdef EPOLLOUT 660 { EPOLLOUT, "EPOLLOUT" }, 661#endif 662#ifdef EPOLLRDNORM 663 { EPOLLRDNORM, "EPOLLRDNORM" }, 664#endif 665#ifdef EPOLLRDBAND 666 { EPOLLRDBAND, "EPOLLRDBAND" }, 667#endif 668#ifdef EPOLLWRNORM 669 { EPOLLWRNORM, "EPOLLWRNORM" }, 670#endif 671#ifdef EPOLLWRBAND 672 { EPOLLWRBAND, "EPOLLWRBAND" }, 673#endif 674#ifdef EPOLLMSG 675 { EPOLLMSG, "EPOLLMSG" }, 676#endif 677#ifdef EPOLLERR 678 { EPOLLERR, "EPOLLERR" }, 679#endif 680#ifdef EPOLLHUP 681 { EPOLLHUP, "EPOLLHUP" }, 682#endif 683#ifdef EPOLLRDHUP 684 { EPOLLRDHUP, "EPOLLRDHUP" }, 685#endif 686#ifdef EPOLLONESHOT 687 { EPOLLONESHOT, "EPOLLONESHOT" }, 688#endif 689#ifdef EPOLLET 690 { EPOLLET, "EPOLLET" }, 691#endif 692 { 0, NULL } 693}; 694 695/* Not aliased to printargs_ld: we want it to have a distinct address */ 696int 697sys_epoll_create(struct tcb *tcp) 698{ 699 return printargs_ld(tcp); 700} 701 702static const struct xlat epollflags[] = { 703#ifdef EPOLL_CLOEXEC 704 { EPOLL_CLOEXEC, "EPOLL_CLOEXEC" }, 705#endif 706#ifdef EPOLL_NONBLOCK 707 { EPOLL_NONBLOCK, "EPOLL_NONBLOCK" }, 708#endif 709 { 0, NULL } 710}; 711 712int 713sys_epoll_create1(struct tcb *tcp) 714{ 715 if (entering(tcp)) 716 printflags(epollflags, tcp->u_arg[0], "EPOLL_???"); 717 return 0; 718} 719 720#ifdef HAVE_SYS_EPOLL_H 721static void 722print_epoll_event(struct epoll_event *ev) 723{ 724 tprints("{"); 725 printflags(epollevents, ev->events, "EPOLL???"); 726 /* We cannot know what format the program uses, so print u32 and u64 727 which will cover every value. */ 728 tprintf(", {u32=%" PRIu32 ", u64=%" PRIu64 "}}", 729 ev->data.u32, ev->data.u64); 730} 731#endif 732 733int 734sys_epoll_ctl(struct tcb *tcp) 735{ 736 if (entering(tcp)) { 737 printfd(tcp, tcp->u_arg[0]); 738 tprints(", "); 739 printxval(epollctls, tcp->u_arg[1], "EPOLL_CTL_???"); 740 tprints(", "); 741 printfd(tcp, tcp->u_arg[2]); 742 tprints(", "); 743 if (tcp->u_arg[3] == 0) 744 tprints("NULL"); 745 else { 746#ifdef HAVE_SYS_EPOLL_H 747 struct epoll_event ev; 748 if (umove(tcp, tcp->u_arg[3], &ev) == 0) 749 print_epoll_event(&ev); 750 else 751#endif 752 tprints("{...}"); 753 } 754 } 755 return 0; 756} 757 758static void 759epoll_wait_common(struct tcb *tcp) 760{ 761 if (entering(tcp)) { 762 printfd(tcp, tcp->u_arg[0]); 763 tprints(", "); 764 } else { 765 if (syserror(tcp)) 766 tprintf("%lx", tcp->u_arg[1]); 767 else if (tcp->u_rval == 0) 768 tprints("{}"); 769 else { 770#ifdef HAVE_SYS_EPOLL_H 771 struct epoll_event ev, *start, *cur, *end; 772 int failed = 0; 773 774 tprints("{"); 775 start = (struct epoll_event *) tcp->u_arg[1]; 776 end = start + tcp->u_rval; 777 for (cur = start; cur < end; ++cur) { 778 if (cur > start) 779 tprints(", "); 780 if (umove(tcp, (long) cur, &ev) == 0) 781 print_epoll_event(&ev); 782 else { 783 tprints("?"); 784 failed = 1; 785 break; 786 } 787 } 788 tprints("}"); 789 if (failed) 790 tprintf(" %#lx", (long) start); 791#else 792 tprints("{...}"); 793#endif 794 } 795 tprintf(", %d, %d", (int) tcp->u_arg[2], (int) tcp->u_arg[3]); 796 } 797} 798 799int 800sys_epoll_wait(struct tcb *tcp) 801{ 802 epoll_wait_common(tcp); 803 return 0; 804} 805 806int 807sys_epoll_pwait(struct tcb *tcp) 808{ 809 epoll_wait_common(tcp); 810 if (exiting(tcp)) { 811 tprints(", "); 812 /* NB: kernel requires arg[5] == NSIG / 8 */ 813 print_sigset_addr_len(tcp, tcp->u_arg[4], tcp->u_arg[5]); 814 tprintf(", %lu", tcp->u_arg[5]); 815 } 816 return 0; 817} 818 819int 820sys_io_setup(struct tcb *tcp) 821{ 822 if (entering(tcp)) 823 tprintf("%ld, ", tcp->u_arg[0]); 824 else { 825 if (syserror(tcp)) 826 tprintf("0x%0lx", tcp->u_arg[1]); 827 else { 828 unsigned long user_id; 829 if (umove(tcp, tcp->u_arg[1], &user_id) == 0) 830 tprintf("{%lu}", user_id); 831 else 832 tprints("{...}"); 833 } 834 } 835 return 0; 836} 837 838int 839sys_io_destroy(struct tcb *tcp) 840{ 841 if (entering(tcp)) 842 tprintf("%lu", tcp->u_arg[0]); 843 return 0; 844} 845 846#ifdef HAVE_LIBAIO_H 847 848enum iocb_sub { 849 SUB_NONE, SUB_COMMON, SUB_POLL, SUB_VECTOR 850}; 851 852static const char * 853iocb_cmd_lookup(unsigned cmd, enum iocb_sub *sub) 854{ 855 static char buf[sizeof("%u /* SUB_??? */") + sizeof(int)*3]; 856 static const struct { 857 const char *name; 858 enum iocb_sub sub; 859 } cmds[] = { 860 { "pread", SUB_COMMON }, 861 { "pwrite", SUB_COMMON }, 862 { "fsync", SUB_NONE }, 863 { "fdsync", SUB_NONE }, 864 { "op4", SUB_NONE }, 865 { "poll", SUB_POLL }, 866 { "noop", SUB_NONE }, 867 { "preadv", SUB_VECTOR }, 868 { "pwritev", SUB_VECTOR }, 869 }; 870 871 if (cmd < ARRAY_SIZE(cmds)) { 872 *sub = cmds[cmd].sub; 873 return cmds[cmd].name; 874 } 875 *sub = SUB_NONE; 876 sprintf(buf, "%u /* SUB_??? */", cmd); 877 return buf; 878} 879 880/* Not defined in libaio.h */ 881#ifndef IOCB_RESFD 882# define IOCB_RESFD (1 << 0) 883#endif 884 885static void 886print_common_flags(struct iocb *iocb) 887{ 888#if HAVE_STRUCT_IOCB_U_C_FLAGS 889 if (iocb->u.c.flags & IOCB_RESFD) 890 tprintf(", resfd=%d", iocb->u.c.resfd); 891 if (iocb->u.c.flags & ~IOCB_RESFD) 892 tprintf(", flags=%x", iocb->u.c.flags); 893#else 894# warning "libaio.h is too old => limited io_submit decoding" 895#endif 896} 897 898#endif /* HAVE_LIBAIO_H */ 899 900int 901sys_io_submit(struct tcb *tcp) 902{ 903 long nr; 904 if (entering(tcp)) { 905 tprintf("%lu, %ld, ", tcp->u_arg[0], tcp->u_arg[1]); 906 nr = tcp->u_arg[1]; 907 /* and if nr is negative? */ 908 if (nr == 0) 909 tprints("{}"); 910 else { 911#ifdef HAVE_LIBAIO_H 912 long i; 913 struct iocb *iocbp, **iocbs = (void *)tcp->u_arg[2]; 914 915 for (i = 0; i < nr; i++, iocbs++) { 916 enum iocb_sub sub; 917 struct iocb iocb; 918 if (i == 0) 919 tprints("{"); 920 else 921 tprints(", "); 922 923 if (umove(tcp, (unsigned long)iocbs, &iocbp) || 924 umove(tcp, (unsigned long)iocbp, &iocb)) { 925 tprints("{...}"); 926 continue; 927 } 928 tprints("{"); 929 if (iocb.data) 930 tprintf("data:%p, ", iocb.data); 931 if (iocb.key) 932 tprintf("key:%u, ", iocb.key); 933 tprintf("%s, ", iocb_cmd_lookup(iocb.aio_lio_opcode, &sub)); 934 if (iocb.aio_reqprio) 935 tprintf("reqprio:%d, ", iocb.aio_reqprio); 936 tprintf("filedes:%d", iocb.aio_fildes); 937 switch (sub) { 938 case SUB_COMMON: 939#if HAVE_DECL_IO_CMD_PWRITE 940 if (iocb.aio_lio_opcode == IO_CMD_PWRITE) { 941 tprints(", str:"); 942 printstr(tcp, (unsigned long)iocb.u.c.buf, 943 iocb.u.c.nbytes); 944 } else 945#endif 946 tprintf(", buf:%p", iocb.u.c.buf); 947 tprintf(", nbytes:%lu, offset:%lld", 948 iocb.u.c.nbytes, 949 iocb.u.c.offset); 950 print_common_flags(&iocb); 951 break; 952 case SUB_VECTOR: 953 tprintf(", %lld", iocb.u.v.offset); 954 print_common_flags(&iocb); 955 tprints(", "); 956 tprint_iov(tcp, iocb.u.v.nr, 957 (unsigned long)iocb.u.v.vec, 958#if HAVE_DECL_IO_CMD_PWRITEV 959 iocb.aio_lio_opcode == IO_CMD_PWRITEV 960#else 961 0 962#endif 963 ); 964 break; 965 case SUB_POLL: 966 tprintf(", %x", iocb.u.poll.events); 967 break; 968 case SUB_NONE: 969 break; 970 } 971 tprints("}"); 972 } 973 if (i) 974 tprints("}"); 975#else 976#warning "libaio.h is not available => no io_submit decoding" 977 tprintf("%#lx", tcp->u_arg[2]); 978#endif 979 } 980 } 981 return 0; 982} 983 984int 985sys_io_cancel(struct tcb *tcp) 986{ 987 if (entering(tcp)) { 988#ifdef HAVE_LIBAIO_H 989 struct iocb iocb; 990#endif 991 tprintf("%lu, ", tcp->u_arg[0]); 992#ifdef HAVE_LIBAIO_H 993 if (umove(tcp, tcp->u_arg[1], &iocb) == 0) { 994 tprintf("{%p, %u, %u, %u, %d}, ", 995 iocb.data, iocb.key, 996 (unsigned)iocb.aio_lio_opcode, 997 (unsigned)iocb.aio_reqprio, iocb.aio_fildes); 998 } else 999#endif 1000 tprints("{...}, "); 1001 } else { 1002 if (tcp->u_rval < 0) 1003 tprints("{...}"); 1004 else { 1005#ifdef HAVE_LIBAIO_H 1006 struct io_event event; 1007 if (umove(tcp, tcp->u_arg[2], &event) == 0) 1008 tprintf("{%p, %p, %ld, %ld}", 1009 event.data, event.obj, 1010 event.res, event.res2); 1011 else 1012#endif 1013 tprints("{...}"); 1014 } 1015 } 1016 return 0; 1017} 1018 1019int 1020sys_io_getevents(struct tcb *tcp) 1021{ 1022 if (entering(tcp)) { 1023 tprintf("%ld, %ld, %ld, ", tcp->u_arg[0], tcp->u_arg[1], 1024 tcp->u_arg[2]); 1025 } else { 1026 if (tcp->u_rval == 0) { 1027 tprints("{}"); 1028 } else { 1029#ifdef HAVE_LIBAIO_H 1030 struct io_event *events = (void *)tcp->u_arg[3]; 1031 long i, nr = tcp->u_rval; 1032 1033 for (i = 0; i < nr; i++, events++) { 1034 struct io_event event; 1035 1036 if (i == 0) 1037 tprints("{"); 1038 else 1039 tprints(", "); 1040 1041 if (umove(tcp, (unsigned long)events, &event) != 0) { 1042 tprints("{...}"); 1043 continue; 1044 } 1045 tprintf("{%p, %p, %ld, %ld}", event.data, 1046 event.obj, event.res, event.res2); 1047 } 1048 tprints("}, "); 1049#else 1050 tprints("{...}"); 1051#endif 1052 } 1053 1054 print_timespec(tcp, tcp->u_arg[4]); 1055 } 1056 return 0; 1057} 1058 1059int 1060sys_select(struct tcb *tcp) 1061{ 1062 return decode_select(tcp, tcp->u_arg, BITNESS_CURRENT); 1063} 1064 1065int 1066sys_pselect6(struct tcb *tcp) 1067{ 1068 int rc = decode_select(tcp, tcp->u_arg, BITNESS_CURRENT); 1069 if (entering(tcp)) { 1070 long r; 1071 struct { 1072 unsigned long ptr; 1073 unsigned long len; 1074 } data; 1075#if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4 1076 if (current_wordsize == 4) { 1077 struct { 1078 uint32_t ptr; 1079 uint32_t len; 1080 } data32; 1081 r = umove(tcp, tcp->u_arg[5], &data32); 1082 data.ptr = data32.ptr; 1083 data.len = data32.len; 1084 } else 1085#endif 1086 r = umove(tcp, tcp->u_arg[5], &data); 1087 if (r < 0) 1088 tprintf(", %#lx", tcp->u_arg[5]); 1089 else { 1090 tprints(", {"); 1091 /* NB: kernel requires data.len == NSIG / 8 */ 1092 print_sigset_addr_len(tcp, data.ptr, data.len); 1093 tprintf(", %lu}", data.len); 1094 } 1095 } 1096 return rc; 1097} 1098 1099static int 1100do_eventfd(struct tcb *tcp, int flags_arg) 1101{ 1102 if (entering(tcp)) { 1103 tprintf("%lu", tcp->u_arg[0]); 1104 if (flags_arg >= 0) { 1105 tprints(", "); 1106 printflags(open_mode_flags, tcp->u_arg[flags_arg], "O_???"); 1107 } 1108 } 1109 return 0; 1110} 1111 1112int 1113sys_eventfd(struct tcb *tcp) 1114{ 1115 return do_eventfd(tcp, -1); 1116} 1117 1118int 1119sys_eventfd2(struct tcb *tcp) 1120{ 1121 return do_eventfd(tcp, 1); 1122} 1123 1124int 1125sys_perf_event_open(struct tcb *tcp) 1126{ 1127 if (entering(tcp)) { 1128 tprintf("%#lx, %d, %d, %d, ", 1129 tcp->u_arg[0], 1130 (int) tcp->u_arg[1], 1131 (int) tcp->u_arg[2], 1132 (int) tcp->u_arg[3]); 1133 printflags(perf_event_open_flags, tcp->u_arg[4], 1134 "PERF_FLAG_???"); 1135 } 1136 return 0; 1137} 1138