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