X-Git-Url: https://granicus.if.org/sourcecode?a=blobdiff_plain;f=desc.c;h=5cb8a1a973dc82d35b02b1e31119abc6bea71471;hb=5940e6593911dcace424c668a1c0934c71fccb9e;hp=c4c5a6980c8ec7e2afa6440469cea69d9e5a5564;hpb=f535b54bc40373c81b13df0975aef4212dacbbde;p=strace diff --git a/desc.c b/desc.c index c4c5a698..5cb8a1a9 100644 --- a/desc.c +++ b/desc.c @@ -147,6 +147,18 @@ static const struct xlat fcntlcmds[] = { #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 }, }; @@ -183,6 +195,33 @@ static const struct xlat lockfcmds[] = { { 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 whence[] = { { SEEK_SET, "SEEK_SET" }, { SEEK_CUR, "SEEK_CUR" }, @@ -197,34 +236,39 @@ printflock(struct tcb *tcp, long addr, int getlk) { struct flock fl; - if (personality_wordsize[current_personality] == sizeof(fl.l_start)) { - if (umove(tcp, addr, &fl) < 0) { - tprintf("{...}"); +#if SUPPORTED_PERSONALITIES > 1 + if (personality_wordsize[current_personality] != sizeof(fl.l_start)) { + if (personality_wordsize[current_personality] == 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) { + tprintf("{...}"); + 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("{ }", + personality_wordsize[current_personality]); return; } - } else if (personality_wordsize[current_personality] == 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) { + } else +#endif + { + if (umove(tcp, addr, &fl) < 0) { tprintf("{...}"); 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("{ }", - personality_wordsize[current_personality]); - return; } tprintf("{type="); printxval(lockfcmds, fl.l_type, "F_???"); @@ -261,45 +305,12 @@ printflock64(struct tcb *tcp, long addr, int getlk) } #endif -/* - * low bits of the open(2) flags define access mode, - * other bits are real flags. - */ -static const char * -sprint_open_modes(mode_t flags) -{ - static char outstr[1024]; - const char *str = xlookup(open_access_modes, flags & 3); - const char *sep = ""; - const struct xlat *x; - - strcpy(outstr, "flags "); - if (str) { - strcat(outstr, str); - flags &= ~3; - if (!flags) - return outstr; - strcat(outstr, "|"); - } - - for (x = open_mode_flags; x->str; x++) { - if ((flags & x->val) == x->val) { - sprintf(outstr + strlen(outstr), - "%s%s", sep, x->str); - sep = "|"; - flags &= ~x->val; - } - } - if (flags) - sprintf(outstr + strlen(outstr), "%s%#x", sep, flags); - return outstr; -} - int sys_fcntl(struct tcb *tcp) { if (entering(tcp)) { - tprintf("%ld, ", tcp->u_arg[0]); + printfd(tcp, tcp->u_arg[0]); + tprintf(", "); printxval(fcntlcmds, tcp->u_arg[1], "F_???"); switch (tcp->u_arg[1]) { case F_SETFD: @@ -307,11 +318,14 @@ sys_fcntl(struct tcb *tcp) 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: tprintf(", "); - tprint_open_modes(tcp, tcp->u_arg[2]); + tprint_open_modes(tcp->u_arg[2]); break; case F_SETLK: case F_SETLKW: #ifdef F_FREESP @@ -326,30 +340,50 @@ sys_fcntl(struct tcb *tcp) #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 +#if defined(F_SETLK64) && F_SETLK64 + 0 != F_SETLK case F_SETLK64: #endif -#if defined(F_SETLKW64) && F_SETLKW64+0!=F_SETLKW +#if defined(F_SETLKW64) && F_SETLKW64 + 0 != F_SETLKW case F_SETLKW64: #endif tprintf(", "); printflock64(tcp, tcp->u_arg[2], 0); break; #endif - } +#ifdef F_NOTIFY + case F_NOTIFY: + tprintf(", "); + printflags(notifyflags, tcp->u_arg[2], "DN_???"); + break; +#endif +#ifdef F_SETLEASE + case F_SETLEASE: + tprintf(", "); + 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); + tcp->auxstr = sprintflags("flags ", fdflags, tcp->u_rval); return RVAL_HEX|RVAL_STR; case F_GETFL: if (syserror(tcp)) @@ -361,14 +395,21 @@ sys_fcntl(struct tcb *tcp) printflock(tcp, tcp->u_arg[2], 1); break; #if _LFS64_LARGEFILE -#if defined(F_GETLK64) && F_GETLK64+0!=F_GETLK +#if defined(F_GETLK64) && F_GETLK64+0 != F_GETLK case F_GETLK64: #endif tprintf(", "); printflock64(tcp, tcp->u_arg[2], 1); break; #endif - default: +#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; } @@ -382,7 +423,8 @@ int sys_flock(struct tcb *tcp) { if (entering(tcp)) { - tprintf("%ld, ", tcp->u_arg[0]); + printfd(tcp, tcp->u_arg[0]); + tprintf(", "); printflags(flockcmds, tcp->u_arg[1], "LOCK_???"); } return 0; @@ -393,7 +435,7 @@ int sys_close(struct tcb *tcp) { if (entering(tcp)) { - tprintf("%ld", tcp->u_arg[0]); + printfd(tcp, tcp->u_arg[0]); } return 0; } @@ -402,7 +444,7 @@ int sys_dup(struct tcb *tcp) { if (entering(tcp)) { - tprintf("%ld", tcp->u_arg[0]); + printfd(tcp, tcp->u_arg[0]); } return 0; } @@ -411,7 +453,9 @@ static int do_dup2(struct tcb *tcp, int flags_arg) { if (entering(tcp)) { - tprintf("%ld, %ld", tcp->u_arg[0], tcp->u_arg[1]); + printfd(tcp, tcp->u_arg[0]); + tprintf(", "); + printfd(tcp, tcp->u_arg[1]); if (flags_arg >= 0) { tprintf(", "); printflags(open_mode_flags, tcp->u_arg[flags_arg], "O_???"); @@ -449,14 +493,13 @@ decode_select(struct tcb *tcp, long *args, enum bitness_t bitness) unsigned int fdsize = ((((args[0] + 7) / 8) + sizeof(long) - 1) & -sizeof(long)); fd_set *fds; - static char outstr[1024]; - char *sep; + const char *sep; long arg; if (entering(tcp)) { - fds = (fd_set *) malloc(fdsize); - if (fds == NULL) - fprintf(stderr, "out of memory\n"); + fds = malloc(fdsize); + if (!fds) + die_out_of_memory(); nfds = args[0]; tprintf("%d", nfds); for (i = 0; i < 3; i++) { @@ -465,7 +508,7 @@ decode_select(struct tcb *tcp, long *args, enum bitness_t bitness) tprintf(", NULL"); continue; } - if (fds == NULL || !verbose(tcp)) { + if (!verbose(tcp)) { tprintf(", %#lx", arg); continue; } @@ -476,7 +519,8 @@ decode_select(struct tcb *tcp, long *args, enum bitness_t bitness) tprintf(", ["); for (j = 0, sep = ""; j < nfds; j++) { if (FD_ISSET(j, fds)) { - tprintf("%s%u", sep, j); + tprints(sep); + printfd(tcp, j); sep = " "; } } @@ -486,53 +530,56 @@ decode_select(struct tcb *tcp, long *args, enum bitness_t bitness) tprintf(", "); printtv_bitness(tcp, args[4], bitness, 0); } - else - { - unsigned int cumlen = 0; - char *sep = ""; + else { + static char outstr[1024]; + char *outptr; +#define end_outstr (outstr + sizeof(outstr)) + const char *sep; if (syserror(tcp)) return 0; - if ((nfds = tcp->u_rval) == 0) { + nfds = tcp->u_rval; + if (nfds == 0) { tcp->auxstr = "Timeout"; return RVAL_STR; } - fds = (fd_set *) malloc(fdsize); - if (fds == NULL) - fprintf(stderr, "out of memory\n"); + fds = malloc(fdsize); + if (!fds) + die_out_of_memory(); - outstr[0] = '\0'; + tcp->auxstr = outstr; + outptr = outstr; + sep = ""; for (i = 0; i < 3; i++) { int first = 1; - char str[20]; - tcp->auxstr = outstr; arg = args[i+1]; - if (fds == NULL || !arg || - umoven(tcp, arg, fdsize, (char *) fds) < 0) + if (!arg || umoven(tcp, arg, fdsize, (char *) fds) < 0) continue; for (j = 0; j < args[0]; j++) { if (FD_ISSET(j, fds)) { - if (first) { - sprintf(str, "%s%s [%u", sep, - i == 0 ? "in" : - i == 1 ? "out" : - "except", j); - first = 0; - sep = ", "; + /* +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); + } } - else - sprintf(str, " %u", j); - cumlen += strlen(str); - if (cumlen < sizeof(outstr)) - strcat(outstr, str); nfds--; } } - if (cumlen) - strcat(outstr, "]"); + if (outptr != outstr) + *outptr++ = ']'; if (nfds == 0) break; } @@ -540,15 +587,15 @@ decode_select(struct tcb *tcp, long *args, enum bitness_t bitness) #ifdef LINUX /* This contains no useful information on SunOS. */ if (args[4]) { - char str[128]; - - sprintf(str, "%sleft ", sep); - sprinttv(tcp, args[4], bitness, str + strlen(str)); - if ((cumlen += strlen(str)) < sizeof(outstr)) - strcat(outstr, str); + if (outptr < end_outstr - 128) { + outptr += sprintf(outptr, "%sleft ", sep); + outptr = sprinttv(tcp, args[4], bitness, outptr); + } } #endif /* LINUX */ + *outptr = '\0'; return RVAL_STR; +#undef end_outstr } return 0; } @@ -662,9 +709,12 @@ int sys_epoll_ctl(struct tcb *tcp) { if (entering(tcp)) { - tprintf("%ld, ", tcp->u_arg[0]); + printfd(tcp, tcp->u_arg[0]); + tprintf(", "); printxval(epollctls, tcp->u_arg[1], "EPOLL_CTL_???"); - tprintf(", %ld, ", tcp->u_arg[2]); + tprintf(", "); + printfd(tcp, tcp->u_arg[2]); + tprintf(", "); if (tcp->u_arg[3] == 0) tprintf("NULL"); else { @@ -683,9 +733,10 @@ sys_epoll_ctl(struct tcb *tcp) static void epoll_wait_common(struct tcb *tcp) { - if (entering(tcp)) - tprintf("%ld, ", tcp->u_arg[0]); - else { + if (entering(tcp)) { + printfd(tcp, tcp->u_arg[0]); + tprintf(", "); + } else { if (syserror(tcp)) tprintf("%lx", tcp->u_arg[1]); else if (tcp->u_rval == 0) @@ -731,8 +782,10 @@ int sys_epoll_pwait(struct tcb *tcp) { epoll_wait_common(tcp); - if (exiting(tcp)) + if (exiting(tcp)) { + tprintf(", "); print_sigset(tcp, tcp->u_arg[4], 0); + } return 0; } @@ -763,6 +816,56 @@ sys_io_destroy(struct tcb *tcp) return 0; } +#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) +{ + 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; +} + +/* Not defined in libaio.h */ +#ifndef IOCB_RESFD +# define IOCB_RESFD (1 << 0) +#endif + +static void +print_common_flags(struct iocb *iocb) +{ + 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); +} + +#endif /* HAVE_LIBAIO_H */ + int sys_io_submit(struct tcb *tcp) { @@ -779,6 +882,7 @@ sys_io_submit(struct tcb *tcp) 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) tprintf("{"); @@ -790,15 +894,49 @@ sys_io_submit(struct tcb *tcp) tprintf("{...}"); continue; } - tprintf("{%p, %u, %hu, %hu, %d}", - iocb.data, iocb.key, - iocb.aio_lio_opcode, - iocb.aio_reqprio, iocb.aio_fildes); + tprintf("{"); + 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 (iocb.aio_lio_opcode == IO_CMD_PWRITE) { + tprintf(", str:"); + printstr(tcp, (unsigned long)iocb.u.c.buf, + iocb.u.c.nbytes); + } else { + tprintf(", buf:%p", iocb.u.c.buf); + } + tprintf(", nbytes:%lu, offset:%llx", + iocb.u.c.nbytes, + iocb.u.c.offset); + print_common_flags(&iocb); + break; + case SUB_VECTOR: + tprintf(", %llx, ", iocb.u.v.offset); + print_common_flags(&iocb); + tprint_iov(tcp, iocb.u.v.nr, + (unsigned long)iocb.u.v.vec, + iocb.aio_lio_opcode == IO_CMD_PWRITEV); + break; + case SUB_POLL: + tprintf(", %x", iocb.u.poll.events); + break; + case SUB_NONE: + break; + } + tprintf("}"); } if (i) tprintf("}"); #else - tprintf("{...}"); +#warning "libaio-devel is not available => no io_submit decoding" + tprintf("%#lx", tcp->u_arg[2]); #endif } }