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