X-Git-Url: https://granicus.if.org/sourcecode?a=blobdiff_plain;f=desc.c;h=48824697fc090f48a4bab68177fa661c5440e86f;hb=3fb78d7305cd5b38bbed2d91b328c3181207b4e9;hp=cd2c85724d7694e3d4a7fded98abe450c8972834;hpb=72cdefbb72d3bd376fbcaa97c41666388cc31e92;p=strace diff --git a/desc.c b/desc.c index cd2c8572..48824697 100644 --- a/desc.c +++ b/desc.c @@ -29,553 +29,157 @@ */ #include "defs.h" -#include -#include -#ifdef HAVE_SYS_EPOLL_H -# include -#endif -#ifdef HAVE_LIBAIO_H -# include -#endif -#ifdef HAVE_LINUX_PERF_EVENT_H -# include -#endif -static const struct xlat fcntlcmds[] = { - { F_DUPFD, "F_DUPFD" }, - { F_GETFD, "F_GETFD" }, - { F_SETFD, "F_SETFD" }, - { F_GETFL, "F_GETFL" }, - { F_SETFL, "F_SETFL" }, - { F_GETLK, "F_GETLK" }, - { F_SETLK, "F_SETLK" }, - { F_SETLKW, "F_SETLKW" }, - { F_GETOWN, "F_GETOWN" }, - { F_SETOWN, "F_SETOWN" }, -#ifdef F_RSETLK - { F_RSETLK, "F_RSETLK" }, -#endif -#ifdef F_RSETLKW - { F_RSETLKW, "F_RSETLKW" }, -#endif -#ifdef F_RGETLK - { F_RGETLK, "F_RGETLK" }, -#endif -#ifdef F_CNVT - { F_CNVT, "F_CNVT" }, -#endif -#ifdef F_SETSIG - { F_SETSIG, "F_SETSIG" }, -#endif -#ifdef F_GETSIG - { F_GETSIG, "F_GETSIG" }, -#endif -#ifdef F_CHKFL - { F_CHKFL, "F_CHKFL" }, -#endif -#ifdef F_DUP2FD - { F_DUP2FD, "F_DUP2FD" }, -#endif -#ifdef F_ALLOCSP - { F_ALLOCSP, "F_ALLOCSP" }, -#endif -#ifdef F_ISSTREAM - { F_ISSTREAM, "F_ISSTREAM" }, -#endif -#ifdef F_PRIV - { F_PRIV, "F_PRIV" }, -#endif -#ifdef F_NPRIV - { F_NPRIV, "F_NPRIV" }, -#endif -#ifdef F_QUOTACL - { F_QUOTACL, "F_QUOTACL" }, -#endif -#ifdef F_BLOCKS - { F_BLOCKS, "F_BLOCKS" }, -#endif -#ifdef F_BLKSIZE - { F_BLKSIZE, "F_BLKSIZE" }, -#endif -#ifdef F_GETOWN - { F_GETOWN, "F_GETOWN" }, -#endif -#ifdef F_SETOWN - { F_SETOWN, "F_SETOWN" }, -#endif -#ifdef F_REVOKE - { F_REVOKE, "F_REVOKE" }, -#endif -#ifdef F_SETLK - { F_SETLK, "F_SETLK" }, -#endif -#ifdef F_SETLKW - { F_SETLKW, "F_SETLKW" }, -#endif -#ifdef F_FREESP - { F_FREESP, "F_FREESP" }, -#endif -#ifdef F_GETLK - { F_GETLK, "F_GETLK" }, -#endif -#ifdef F_SETLK64 - { F_SETLK64, "F_SETLK64" }, -#endif -#ifdef F_SETLKW64 - { F_SETLKW64, "F_SETLKW64" }, -#endif -#ifdef F_FREESP64 - { F_FREESP64, "F_FREESP64" }, -#endif -#ifdef F_GETLK64 - { F_GETLK64, "F_GETLK64" }, -#endif -#ifdef F_SHARE - { F_SHARE, "F_SHARE" }, -#endif -#ifdef F_UNSHARE - { F_UNSHARE, "F_UNSHARE" }, -#endif -#ifdef F_SETLEASE - { F_SETLEASE, "F_SETLEASE" }, -#endif -#ifdef F_GETLEASE - { F_GETLEASE, "F_GETLEASE" }, -#endif -#ifdef F_NOTIFY - { F_NOTIFY, "F_NOTIFY" }, -#endif -#ifdef F_DUPFD_CLOEXEC - { F_DUPFD_CLOEXEC,"F_DUPFD_CLOEXEC"}, -#endif - { 0, NULL }, -}; - -static const struct xlat fdflags[] = { -#ifdef FD_CLOEXEC - { FD_CLOEXEC, "FD_CLOEXEC" }, -#endif - { 0, NULL }, -}; - -#ifdef LOCK_SH - -static const struct xlat flockcmds[] = { - { LOCK_SH, "LOCK_SH" }, - { LOCK_EX, "LOCK_EX" }, - { LOCK_NB, "LOCK_NB" }, - { LOCK_UN, "LOCK_UN" }, - { 0, NULL }, -}; - -#endif /* LOCK_SH */ - -static const struct xlat lockfcmds[] = { - { F_RDLCK, "F_RDLCK" }, - { F_WRLCK, "F_WRLCK" }, - { F_UNLCK, "F_UNLCK" }, -#ifdef F_EXLCK - { F_EXLCK, "F_EXLCK" }, -#endif -#ifdef F_SHLCK - { F_SHLCK, "F_SHLCK" }, -#endif - { 0, NULL }, -}; - -#ifdef F_NOTIFY -static const struct xlat notifyflags[] = { -#ifdef DN_ACCESS - { DN_ACCESS, "DN_ACCESS" }, -#endif -#ifdef DN_MODIFY - { DN_MODIFY, "DN_MODIFY" }, -#endif -#ifdef DN_CREATE - { DN_CREATE, "DN_CREATE" }, -#endif -#ifdef DN_DELETE - { DN_DELETE, "DN_DELETE" }, -#endif -#ifdef DN_RENAME - { DN_RENAME, "DN_RENAME" }, -#endif -#ifdef DN_ATTRIB - { DN_ATTRIB, "DN_ATTRIB" }, -#endif -#ifdef DN_MULTISHOT - { DN_MULTISHOT, "DN_MULTISHOT" }, -#endif - { 0, NULL }, -}; -#endif - -static const struct xlat perf_event_open_flags[] = { -#ifdef PERF_FLAG_FD_NO_GROUP - { PERF_FLAG_FD_NO_GROUP, "PERF_FLAG_FD_NO_GROUP" }, -#endif -#ifdef PERF_FLAG_FD_OUTPUT - { PERF_FLAG_FD_OUTPUT, "PERF_FLAG_FD_OUTPUT" }, -#endif -#ifdef PERF_FLAG_PID_CGROUP - { PERF_FLAG_PID_CGROUP, "PERF_FLAG_PID_CGROUP" }, -#endif - { 0, NULL }, -}; - -/* fcntl/lockf */ -static void -printflock(struct tcb *tcp, long addr, int getlk) +SYS_FUNC(close) { - struct flock fl; + printfd(tcp, tcp->u_arg[0]); -#if SUPPORTED_PERSONALITIES > 1 - if (current_wordsize != sizeof(fl.l_start)) { - if (current_wordsize == 4) { - /* 32-bit x86 app on x86_64 and similar cases */ - struct { - short int l_type; - short int l_whence; - int32_t l_start; /* off_t */ - int32_t l_len; /* off_t */ - int32_t l_pid; /* pid_t */ - } fl32; - if (umove(tcp, addr, &fl32) < 0) { - tprints("{...}"); - return; - } - fl.l_type = fl32.l_type; - fl.l_whence = fl32.l_whence; - fl.l_start = fl32.l_start; - fl.l_len = fl32.l_len; - fl.l_pid = fl32.l_pid; - } else { - /* let people know we have a problem here */ - tprintf("", - current_wordsize); - return; - } - } else -#endif - { - if (umove(tcp, addr, &fl) < 0) { - tprints("{...}"); - return; - } - } - tprints("{type="); - printxval(lockfcmds, fl.l_type, "F_???"); - tprints(", whence="); - printxval(whence_codes, fl.l_whence, "SEEK_???"); - tprintf(", start=%ld, len=%ld", fl.l_start, fl.l_len); - if (getlk) - tprintf(", pid=%lu}", (unsigned long) fl.l_pid); - else - tprints("}"); + return RVAL_DECODED; } -#if _LFS64_LARGEFILE -/* fcntl/lockf */ -static void -printflock64(struct tcb *tcp, long addr, int getlk) +SYS_FUNC(dup) { - struct flock64 fl; + printfd(tcp, tcp->u_arg[0]); - if (umove(tcp, addr, &fl) < 0) { - tprints("{...}"); - return; - } - tprints("{type="); - printxval(lockfcmds, fl.l_type, "F_???"); - tprints(", whence="); - printxval(whence_codes, fl.l_whence, "SEEK_???"); - tprintf(", start=%lld, len=%lld", (long long) fl.l_start, (long long) fl.l_len); - if (getlk) - tprintf(", pid=%lu}", (unsigned long) fl.l_pid); - else - tprints("}"); -} -#endif - -int -sys_fcntl(struct tcb *tcp) -{ - if (entering(tcp)) { - printfd(tcp, tcp->u_arg[0]); - tprints(", "); - printxval(fcntlcmds, tcp->u_arg[1], "F_???"); - switch (tcp->u_arg[1]) { - case F_SETFD: - tprints(", "); - printflags(fdflags, tcp->u_arg[2], "FD_???"); - break; - case F_SETOWN: case F_DUPFD: -#ifdef F_DUPFD_CLOEXEC - case F_DUPFD_CLOEXEC: -#endif - tprintf(", %ld", tcp->u_arg[2]); - break; - case F_SETFL: - tprints(", "); - tprint_open_modes(tcp->u_arg[2]); - break; - case F_SETLK: case F_SETLKW: -#ifdef F_FREESP - case F_FREESP: -#endif - tprints(", "); - printflock(tcp, tcp->u_arg[2], 0); - break; -#if _LFS64_LARGEFILE -#ifdef F_FREESP64 - case F_FREESP64: -#endif - /* Linux glibc defines SETLK64 as SETLK, - even though the kernel has different values - as does Solaris. */ -#if defined(F_SETLK64) && F_SETLK64 + 0 != F_SETLK - case F_SETLK64: -#endif -#if defined(F_SETLKW64) && F_SETLKW64 + 0 != F_SETLKW - case F_SETLKW64: -#endif - tprints(", "); - printflock64(tcp, tcp->u_arg[2], 0); - break; -#endif -#ifdef F_NOTIFY - case F_NOTIFY: - tprints(", "); - printflags(notifyflags, tcp->u_arg[2], "DN_???"); - break; -#endif -#ifdef F_SETLEASE - case F_SETLEASE: - tprints(", "); - printxval(lockfcmds, tcp->u_arg[2], "F_???"); - break; -#endif - } - } - else { - switch (tcp->u_arg[1]) { - case F_DUPFD: -#ifdef F_DUPFD_CLOEXEC - case F_DUPFD_CLOEXEC: -#endif - case F_SETFD: case F_SETFL: - case F_SETLK: case F_SETLKW: - case F_SETOWN: case F_GETOWN: -#ifdef F_NOTIFY - case F_NOTIFY: -#endif -#ifdef F_SETLEASE - case F_SETLEASE: -#endif - break; - case F_GETFD: - if (syserror(tcp) || tcp->u_rval == 0) - return 0; - tcp->auxstr = sprintflags("flags ", fdflags, tcp->u_rval); - return RVAL_HEX|RVAL_STR; - case F_GETFL: - if (syserror(tcp)) - return 0; - tcp->auxstr = sprint_open_modes(tcp->u_rval); - return RVAL_HEX|RVAL_STR; - case F_GETLK: - tprints(", "); - printflock(tcp, tcp->u_arg[2], 1); - break; -#if _LFS64_LARGEFILE -#if defined(F_GETLK64) && F_GETLK64+0 != F_GETLK - case F_GETLK64: -#endif - tprints(", "); - printflock64(tcp, tcp->u_arg[2], 1); - break; -#endif -#ifdef F_GETLEASE - case F_GETLEASE: - if (syserror(tcp)) - return 0; - tcp->auxstr = xlookup(lockfcmds, tcp->u_rval); - return RVAL_HEX|RVAL_STR; -#endif - default: - tprintf(", %#lx", tcp->u_arg[2]); - break; - } - } - return 0; -} - -#ifdef LOCK_SH - -int -sys_flock(struct tcb *tcp) -{ - if (entering(tcp)) { - printfd(tcp, tcp->u_arg[0]); - tprints(", "); - printflags(flockcmds, tcp->u_arg[1], "LOCK_???"); - } - return 0; -} -#endif /* LOCK_SH */ - -int -sys_close(struct tcb *tcp) -{ - if (entering(tcp)) { - printfd(tcp, tcp->u_arg[0]); - } - return 0; + return RVAL_DECODED | RVAL_FD; } static int do_dup2(struct tcb *tcp, int flags_arg) { - if (entering(tcp)) { - printfd(tcp, tcp->u_arg[0]); + printfd(tcp, tcp->u_arg[0]); + tprints(", "); + printfd(tcp, tcp->u_arg[1]); + if (flags_arg >= 0) { tprints(", "); - printfd(tcp, tcp->u_arg[1]); - if (flags_arg >= 0) { - tprints(", "); - printflags(open_mode_flags, tcp->u_arg[flags_arg], "O_???"); - } + printflags(open_mode_flags, tcp->u_arg[flags_arg], "O_???"); } - return 0; + + return RVAL_DECODED | RVAL_FD; } -int -sys_dup2(struct tcb *tcp) +SYS_FUNC(dup2) { return do_dup2(tcp, -1); } -int -sys_dup3(struct tcb *tcp) +SYS_FUNC(dup3) { return do_dup2(tcp, 2); } -#if defined(ALPHA) -int -sys_getdtablesize(struct tcb *tcp) -{ - return 0; -} -#endif - static int -decode_select(struct tcb *tcp, long *args, enum bitness_t bitness) +decode_select(struct tcb *const tcp, const kernel_ulong_t *const args, + void (*const print_tv_ts) (struct tcb *, kernel_ulong_t), + const char * (*const sprint_tv_ts) (struct tcb *, kernel_ulong_t)) { int i, j; - unsigned nfds, fdsize; - fd_set *fds; + int nfds, fdsize; + fd_set *fds = NULL; const char *sep; - long arg; + kernel_ulong_t addr; + + /* Kernel truncates args[0] to int, we do the same. */ + nfds = (int) args[0]; + + /* Kernel rejects negative nfds, so we don't parse it either. */ + if (nfds < 0) + nfds = 0; - fdsize = args[0]; /* Beware of select(2^31-1, NULL, NULL, NULL) and similar... */ - if (args[0] > 1024*1024) - fdsize = 1024*1024; - if (args[0] < 0) - fdsize = 0; - fdsize = (((fdsize + 7) / 8) + sizeof(long)-1) & -sizeof(long); + if (nfds > 1024*1024) + nfds = 1024*1024; + + /* + * We had bugs a-la "while (j < args[0])" and "umoven(args[0])" below. + * Instead of args[0], use nfds for fd count, fdsize for array lengths. + */ + fdsize = (((nfds + 7) / 8) + current_wordsize-1) & -current_wordsize; if (entering(tcp)) { - fds = malloc(fdsize); - if (!fds) - die_out_of_memory(); - nfds = args[0]; - tprintf("%d", nfds); + tprintf("%d", (int) args[0]); + + if (verbose(tcp) && fdsize > 0) + fds = malloc(fdsize); for (i = 0; i < 3; i++) { - arg = args[i+1]; - if (arg == 0) { - tprints(", NULL"); - continue; - } - if (!verbose(tcp)) { - tprintf(", %#lx", arg); + addr = args[i+1]; + tprints(", "); + if (!fds) { + printaddr(addr); continue; } - if (umoven(tcp, arg, fdsize, (char *) fds) < 0) { - tprints(", [?]"); + if (umoven_or_printaddr(tcp, addr, fdsize, fds)) continue; - } - tprints(", ["); - for (j = 0, sep = ""; j < nfds; j++) { - if (FD_ISSET(j, fds)) { - tprints(sep); - printfd(tcp, j); - sep = " "; - } + tprints("["); + for (j = 0, sep = "";; j++) { + j = next_set_bit(fds, j, nfds); + if (j < 0) + break; + tprints(sep); + printfd(tcp, j); + sep = " "; } tprints("]"); } free(fds); tprints(", "); - printtv_bitness(tcp, args[4], bitness, 0); - } - else { + print_tv_ts(tcp, args[4]); + } else { static char outstr[1024]; char *outptr; #define end_outstr (outstr + sizeof(outstr)) - const char *sep; + int ready_fds; if (syserror(tcp)) return 0; - nfds = tcp->u_rval; - if (nfds == 0) { + ready_fds = tcp->u_rval; + if (ready_fds == 0) { tcp->auxstr = "Timeout"; return RVAL_STR; } fds = malloc(fdsize); - if (!fds) - die_out_of_memory(); outptr = outstr; sep = ""; - for (i = 0; i < 3; i++) { + for (i = 0; i < 3 && ready_fds > 0; i++) { int first = 1; - arg = args[i+1]; - if (!arg || umoven(tcp, arg, fdsize, (char *) fds) < 0) + addr = args[i+1]; + if (!addr || !fds || umoven(tcp, addr, fdsize, fds) < 0) continue; - for (j = 0; j < args[0]; j++) { - if (FD_ISSET(j, fds)) { - /* +2 chars needed at the end: ']',NUL */ - if (outptr < end_outstr - (sizeof(", except [") + sizeof(int)*3 + 2)) { - if (first) { - outptr += sprintf(outptr, "%s%s [%u", - sep, - i == 0 ? "in" : i == 1 ? "out" : "except", - j - ); - first = 0; - sep = ", "; - } - else { - outptr += sprintf(outptr, " %u", j); - } + for (j = 0;; j++) { + j = next_set_bit(fds, j, nfds); + if (j < 0) + break; + /* +2 chars needed at the end: ']',NUL */ + if (outptr < end_outstr - (sizeof(", except [") + sizeof(int)*3 + 2)) { + if (first) { + outptr += sprintf(outptr, "%s%s [%u", + sep, + i == 0 ? "in" : i == 1 ? "out" : "except", + j + ); + first = 0; + sep = ", "; + } + else { + outptr += sprintf(outptr, " %u", j); } - nfds--; } + if (--ready_fds == 0) + break; } if (outptr != outstr) *outptr++ = ']'; - if (nfds == 0) - break; } free(fds); /* This contains no useful information on SunOS. */ if (args[4]) { - if (outptr < end_outstr - (10 + TIMEVAL_TEXT_BUFSIZE)) { - outptr += sprintf(outptr, "%sleft ", sep); - outptr = sprinttv(outptr, tcp, args[4], bitness, /*special:*/ 0); + const char *str = sprint_tv_ts(tcp, args[4]); + if (outptr + sizeof("left ") + strlen(sep) + strlen(str) < end_outstr) { + outptr += sprintf(outptr, "%sleft %s", sep, str); } } *outptr = '\0'; @@ -586,510 +190,77 @@ decode_select(struct tcb *tcp, long *args, enum bitness_t bitness) return 0; } -int -sys_oldselect(struct tcb *tcp) +SYS_FUNC(oldselect) { - long args[5]; - - if (umoven(tcp, tcp->u_arg[0], sizeof args, (char *) args) < 0) { - tprints("[...]"); - return 0; - } - return decode_select(tcp, args, BITNESS_CURRENT); -} - -#ifdef ALPHA -int -sys_osf_select(struct tcb *tcp) -{ - long *args = tcp->u_arg; - return decode_select(tcp, args, BITNESS_32); -} -#endif + kernel_ulong_t select_args[5]; + unsigned int oldselect_args[5]; -static const struct xlat epollctls[] = { -#ifdef EPOLL_CTL_ADD - { EPOLL_CTL_ADD, "EPOLL_CTL_ADD" }, -#endif -#ifdef EPOLL_CTL_MOD - { EPOLL_CTL_MOD, "EPOLL_CTL_MOD" }, -#endif -#ifdef EPOLL_CTL_DEL - { EPOLL_CTL_DEL, "EPOLL_CTL_DEL" }, -#endif - { 0, NULL } -}; - -static const struct xlat epollevents[] = { -#ifdef EPOLLIN - { EPOLLIN, "EPOLLIN" }, -#endif -#ifdef EPOLLPRI - { EPOLLPRI, "EPOLLPRI" }, -#endif -#ifdef EPOLLOUT - { EPOLLOUT, "EPOLLOUT" }, -#endif -#ifdef EPOLLRDNORM - { EPOLLRDNORM, "EPOLLRDNORM" }, -#endif -#ifdef EPOLLRDBAND - { EPOLLRDBAND, "EPOLLRDBAND" }, -#endif -#ifdef EPOLLWRNORM - { EPOLLWRNORM, "EPOLLWRNORM" }, -#endif -#ifdef EPOLLWRBAND - { EPOLLWRBAND, "EPOLLWRBAND" }, -#endif -#ifdef EPOLLMSG - { EPOLLMSG, "EPOLLMSG" }, -#endif -#ifdef EPOLLERR - { EPOLLERR, "EPOLLERR" }, -#endif -#ifdef EPOLLHUP - { EPOLLHUP, "EPOLLHUP" }, -#endif -#ifdef EPOLLRDHUP - { EPOLLRDHUP, "EPOLLRDHUP" }, -#endif -#ifdef EPOLLONESHOT - { EPOLLONESHOT, "EPOLLONESHOT" }, -#endif -#ifdef EPOLLET - { EPOLLET, "EPOLLET" }, -#endif - { 0, NULL } -}; - -/* Not aliased to printargs_ld: we want it to have a distinct address */ -int -sys_epoll_create(struct tcb *tcp) -{ - return printargs_ld(tcp); -} - -static const struct xlat epollflags[] = { -#ifdef EPOLL_CLOEXEC - { EPOLL_CLOEXEC, "EPOLL_CLOEXEC" }, -#endif -#ifdef EPOLL_NONBLOCK - { EPOLL_NONBLOCK, "EPOLL_NONBLOCK" }, -#endif - { 0, NULL } -}; - -int -sys_epoll_create1(struct tcb *tcp) -{ - if (entering(tcp)) - printflags(epollflags, tcp->u_arg[0], "EPOLL_???"); - return 0; -} - -#ifdef HAVE_SYS_EPOLL_H -static void -print_epoll_event(struct epoll_event *ev) -{ - tprints("{"); - printflags(epollevents, ev->events, "EPOLL???"); - /* We cannot know what format the program uses, so print u32 and u64 - which will cover every value. */ - tprintf(", {u32=%" PRIu32 ", u64=%" PRIu64 "}}", - ev->data.u32, ev->data.u64); -} -#endif - -int -sys_epoll_ctl(struct tcb *tcp) -{ - if (entering(tcp)) { - printfd(tcp, tcp->u_arg[0]); - tprints(", "); - printxval(epollctls, tcp->u_arg[1], "EPOLL_CTL_???"); - tprints(", "); - printfd(tcp, tcp->u_arg[2]); - tprints(", "); - if (tcp->u_arg[3] == 0) - tprints("NULL"); - else { -#ifdef HAVE_SYS_EPOLL_H - struct epoll_event ev; - if (umove(tcp, tcp->u_arg[3], &ev) == 0) - print_epoll_event(&ev); - else -#endif - tprints("{...}"); + if (sizeof(*select_args) == sizeof(*oldselect_args)) { + if (umove_or_printaddr(tcp, tcp->u_arg[0], &select_args)) { + return 0; } - } - return 0; -} - -static void -epoll_wait_common(struct tcb *tcp) -{ - if (entering(tcp)) { - printfd(tcp, tcp->u_arg[0]); - tprints(", "); } else { - if (syserror(tcp)) - tprintf("%lx", tcp->u_arg[1]); - else if (tcp->u_rval == 0) - tprints("{}"); - else { -#ifdef HAVE_SYS_EPOLL_H - struct epoll_event ev, *start, *cur, *end; - int failed = 0; + unsigned int i; - tprints("{"); - start = (struct epoll_event *) tcp->u_arg[1]; - end = start + tcp->u_rval; - for (cur = start; cur < end; ++cur) { - if (cur > start) - tprints(", "); - if (umove(tcp, (long) cur, &ev) == 0) - print_epoll_event(&ev); - else { - tprints("?"); - failed = 1; - break; - } - } - tprints("}"); - if (failed) - tprintf(" %#lx", (long) start); -#else - tprints("{...}"); -#endif + if (umove_or_printaddr(tcp, tcp->u_arg[0], &oldselect_args)) { + return 0; } - tprintf(", %d, %d", (int) tcp->u_arg[2], (int) tcp->u_arg[3]); - } -} - -int -sys_epoll_wait(struct tcb *tcp) -{ - epoll_wait_common(tcp); - return 0; -} - -int -sys_epoll_pwait(struct tcb *tcp) -{ - epoll_wait_common(tcp); - if (exiting(tcp)) { - tprints(", "); - print_sigset(tcp, tcp->u_arg[4], 0); - } - return 0; -} -int -sys_io_setup(struct tcb *tcp) -{ - if (entering(tcp)) - tprintf("%ld, ", tcp->u_arg[0]); - else { - if (syserror(tcp)) - tprintf("0x%0lx", tcp->u_arg[1]); - else { - unsigned long user_id; - if (umove(tcp, tcp->u_arg[1], &user_id) == 0) - tprintf("{%lu}", user_id); - else - tprints("{...}"); + for (i = 0; i < 5; ++i) { + select_args[i] = oldselect_args[i]; } } - return 0; -} -int -sys_io_destroy(struct tcb *tcp) -{ - if (entering(tcp)) - tprintf("%lu", tcp->u_arg[0]); - return 0; + return decode_select(tcp, select_args, print_timeval, sprint_timeval); } -#ifdef HAVE_LIBAIO_H - -enum iocb_sub { - SUB_NONE, SUB_COMMON, SUB_POLL, SUB_VECTOR -}; - -static const char * -iocb_cmd_lookup(unsigned cmd, enum iocb_sub *sub) +#ifdef ALPHA +SYS_FUNC(osf_select) { - static char buf[sizeof("%u /* SUB_??? */") + sizeof(int)*3]; - static const struct { - const char *name; - enum iocb_sub sub; - } cmds[] = { - { "pread", SUB_COMMON }, - { "pwrite", SUB_COMMON }, - { "fsync", SUB_NONE }, - { "fdsync", SUB_NONE }, - { "op4", SUB_NONE }, - { "poll", SUB_POLL }, - { "noop", SUB_NONE }, - { "preadv", SUB_VECTOR }, - { "pwritev", SUB_VECTOR }, - }; - - if (cmd < ARRAY_SIZE(cmds)) { - *sub = cmds[cmd].sub; - return cmds[cmd].name; - } - *sub = SUB_NONE; - sprintf(buf, "%u /* SUB_??? */", cmd); - return buf; + return decode_select(tcp, tcp->u_arg, print_timeval32, sprint_timeval32); } - -/* Not defined in libaio.h */ -#ifndef IOCB_RESFD -# define IOCB_RESFD (1 << 0) #endif -static void -print_common_flags(struct iocb *iocb) -{ -#if HAVE_STRUCT_IOCB_U_C_FLAGS - if (iocb->u.c.flags & IOCB_RESFD) - tprintf(", resfd=%d", iocb->u.c.resfd); - if (iocb->u.c.flags & ~IOCB_RESFD) - tprintf(", flags=%x", iocb->u.c.flags); -#else -# warning "libaio.h is too old => limited io_submit decoding" -#endif -} - -#endif /* HAVE_LIBAIO_H */ - -int -sys_io_submit(struct tcb *tcp) +SYS_FUNC(select) { - long nr; - if (entering(tcp)) { - tprintf("%lu, %ld, ", tcp->u_arg[0], tcp->u_arg[1]); - nr = tcp->u_arg[1]; - /* and if nr is negative? */ - if (nr == 0) - tprints("{}"); - else { -#ifdef HAVE_LIBAIO_H - long i; - struct iocb *iocbp, **iocbs = (void *)tcp->u_arg[2]; - - for (i = 0; i < nr; i++, iocbs++) { - enum iocb_sub sub; - struct iocb iocb; - if (i == 0) - tprints("{"); - else - tprints(", "); - - if (umove(tcp, (unsigned long)iocbs, &iocbp) || - umove(tcp, (unsigned long)iocbp, &iocb)) { - tprints("{...}"); - continue; - } - tprints("{"); - if (iocb.data) - tprintf("data:%p, ", iocb.data); - if (iocb.key) - tprintf("key:%u, ", iocb.key); - tprintf("%s, ", iocb_cmd_lookup(iocb.aio_lio_opcode, &sub)); - if (iocb.aio_reqprio) - tprintf("reqprio:%d, ", iocb.aio_reqprio); - tprintf("filedes:%d", iocb.aio_fildes); - switch (sub) { - case SUB_COMMON: -#if HAVE_DECL_IO_CMD_PWRITE - if (iocb.aio_lio_opcode == IO_CMD_PWRITE) { - tprints(", str:"); - printstr(tcp, (unsigned long)iocb.u.c.buf, - iocb.u.c.nbytes); - } else -#endif - tprintf(", buf:%p", iocb.u.c.buf); - tprintf(", nbytes:%lu, offset:%lld", - iocb.u.c.nbytes, - iocb.u.c.offset); - print_common_flags(&iocb); - break; - case SUB_VECTOR: - tprintf(", %lld", iocb.u.v.offset); - print_common_flags(&iocb); - tprints(", "); - tprint_iov(tcp, iocb.u.v.nr, - (unsigned long)iocb.u.v.vec, -#if HAVE_DECL_IO_CMD_PWRITEV - iocb.aio_lio_opcode == IO_CMD_PWRITEV -#else - 0 -#endif - ); - break; - case SUB_POLL: - tprintf(", %x", iocb.u.poll.events); - break; - case SUB_NONE: - break; - } - tprints("}"); - } - if (i) - tprints("}"); -#else -#warning "libaio.h is not available => no io_submit decoding" - tprintf("%#lx", tcp->u_arg[2]); -#endif - } - } - return 0; + return decode_select(tcp, tcp->u_arg, print_timeval, sprint_timeval); } -int -sys_io_cancel(struct tcb *tcp) -{ - if (entering(tcp)) { -#ifdef HAVE_LIBAIO_H - struct iocb iocb; -#endif - tprintf("%lu, ", tcp->u_arg[0]); -#ifdef HAVE_LIBAIO_H - if (umove(tcp, tcp->u_arg[1], &iocb) == 0) { - tprintf("{%p, %u, %u, %u, %d}, ", - iocb.data, iocb.key, - (unsigned)iocb.aio_lio_opcode, - (unsigned)iocb.aio_reqprio, iocb.aio_fildes); - } else -#endif - tprints("{...}, "); - } else { - if (tcp->u_rval < 0) - tprints("{...}"); - else { -#ifdef HAVE_LIBAIO_H - struct io_event event; - if (umove(tcp, tcp->u_arg[2], &event) == 0) - tprintf("{%p, %p, %ld, %ld}", - event.data, event.obj, - event.res, event.res2); - else -#endif - tprints("{...}"); +static int +umove_kulong_array_or_printaddr(struct tcb *const tcp, const kernel_ulong_t addr, + kernel_ulong_t *const ptr, const size_t n) +{ +#ifndef current_klongsize + if (current_klongsize < sizeof(*ptr)) { + uint32_t ptr32[n]; + int r = umove_or_printaddr(tcp, addr, &ptr32); + if (!r) { + size_t i; + + for (i = 0; i < n; ++i) + ptr[i] = ptr32[i]; } + return r; } - return 0; +#endif /* !current_klongsize */ + return umoven_or_printaddr(tcp, addr, n * sizeof(*ptr), ptr); } -int -sys_io_getevents(struct tcb *tcp) +SYS_FUNC(pselect6) { + int rc = decode_select(tcp, tcp->u_arg, print_timespec, sprint_timespec); if (entering(tcp)) { - tprintf("%ld, %ld, %ld, ", tcp->u_arg[0], tcp->u_arg[1], - tcp->u_arg[2]); - } else { - if (tcp->u_rval == 0) { - tprints("{}"); - } else { -#ifdef HAVE_LIBAIO_H - struct io_event *events = (void *)tcp->u_arg[3]; - long i, nr = tcp->u_rval; - - for (i = 0; i < nr; i++, events++) { - struct io_event event; - - if (i == 0) - tprints("{"); - else - tprints(", "); + kernel_ulong_t data[2]; - if (umove(tcp, (unsigned long)events, &event) != 0) { - tprints("{...}"); - continue; - } - tprintf("{%p, %p, %ld, %ld}", event.data, - event.obj, event.res, event.res2); - } - tprints("}, "); -#else - tprints("{...}"); -#endif + tprints(", "); + if (!umove_kulong_array_or_printaddr(tcp, tcp->u_arg[5], + data, ARRAY_SIZE(data))) { + tprints("{"); + /* NB: kernel requires data[1] == NSIG_BYTES */ + print_sigset_addr_len(tcp, data[0], data[1]); + tprintf(", %" PRI_klu "}", data[1]); } - - print_timespec(tcp, tcp->u_arg[4]); } - return 0; -} - -int -sys_select(struct tcb *tcp) -{ - return decode_select(tcp, tcp->u_arg, BITNESS_CURRENT); -} -int -sys_pselect6(struct tcb *tcp) -{ - int rc = decode_select(tcp, tcp->u_arg, BITNESS_CURRENT); - if (entering(tcp)) { - struct { - void *ss; - unsigned long len; - } data; - if (umove(tcp, tcp->u_arg[5], &data) < 0) - tprintf(", %#lx", tcp->u_arg[5]); - else { - tprints(", {"); - if (data.len < sizeof(long)) - tprintf("%#lx", (long)data.ss); - else - print_sigset(tcp, (long)data.ss, 0); - tprintf(", %lu}", data.len); - } - } return rc; } - -static int -do_eventfd(struct tcb *tcp, int flags_arg) -{ - if (entering(tcp)) { - tprintf("%lu", tcp->u_arg[0]); - if (flags_arg >= 0) { - tprints(", "); - printflags(open_mode_flags, tcp->u_arg[flags_arg], "O_???"); - } - } - return 0; -} - -int -sys_eventfd(struct tcb *tcp) -{ - return do_eventfd(tcp, -1); -} - -int -sys_eventfd2(struct tcb *tcp) -{ - return do_eventfd(tcp, 1); -} - -int -sys_perf_event_open(struct tcb *tcp) -{ - if (entering(tcp)) { - tprintf("%#lx, %d, %d, %d, ", - tcp->u_arg[0], - (int) tcp->u_arg[1], - (int) tcp->u_arg[2], - (int) tcp->u_arg[3]); - printflags(perf_event_open_flags, tcp->u_arg[4], - "PERF_FLAG_???"); - } - return 0; -}