From 31968bcd5953e8802cfa40700610a8eba0aec9f1 Mon Sep 17 00:00:00 2001 From: dwmalone Date: Tue, 23 Mar 2004 12:37:02 +0000 Subject: Add support for decoding Timespec, Timeval, Itimerval, Pollfd, Fd_set and Sigaction structures. Use these for printing the arguments to sigaction(), nanosleep(), select(), poll(), gettimeofday(), clock_gettime(), recvfrom(), getitimer() and setitimer(). This is based on Dan's patch from the PR but I've hacked it for style and some other issues. While Dan has checked this patch, any goofs are probably my fault. (The PR also contains support for the dual return values of pipe(). These will follow once I've ported that support to platforms other than i386.) PR: 52190 Submitted by: Dan Nelson --- usr.bin/truss/syscall.h | 14 +++- usr.bin/truss/syscalls.c | 168 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 179 insertions(+), 3 deletions(-) diff --git a/usr.bin/truss/syscall.h b/usr.bin/truss/syscall.h index 8546cc3..a6cdbec 100644 --- a/usr.bin/truss/syscall.h +++ b/usr.bin/truss/syscall.h @@ -9,9 +9,18 @@ * write() arguments as such, even though they may *not* be * printable data. * Ptr -- pointer to some specific structure. Just print as hex for now. - * Quad -- a double-word value. e.g., lseek(int, offset_t, int) * Stat -- a pointer to a stat buffer. Currently unused. * Ioctl -- an ioctl command. Woefully limited. + * Quad -- a double-word value. e.g., lseek(int, offset_t, int) + * Signal -- a signal number. Prints the signal name (SIGxxx) + * Sockaddr -- a pointer to a struct sockaddr. Prints symbolic AF, and IP:Port + * StringArray -- a pointer to an array of string pointers. + * Timespec -- a pointer to a struct timespec. Prints both elements. + * Timeval -- a pointer to a struct timeval. Prints both elements. + * Itimerval -- a pointer to a struct itimerval. Prints all elements. + * Pollfd -- a pointer to an array of struct pollfd. Prints .fd and .events. + * Fd_set -- a pointer to an array of fd_set. Prints the fds that are set. + * Sigaction -- a pointer to a struct sigaction. Prints all elements. * * In addition, the pointer types (String, Ptr) may have OUT masked in -- * this means that the data is set on *return* from the system call -- or @@ -22,7 +31,8 @@ */ enum Argtype { None = 1, Hex, Octal, Int, String, Ptr, Stat, Ioctl, Quad, - Signal, Sockaddr, StringArray, Fcntl, Mprot, Mmapflags }; + Signal, Sockaddr, StringArray, Timespec, Timeval, Itimerval, Pollfd, + Fd_set, Sigaction, Fcntl, Mprot, Mmapflags }; #define ARG_MASK 0xff #define OUT 0x100 diff --git a/usr.bin/truss/syscalls.c b/usr.bin/truss/syscalls.c index 6f35f99..ba34257 100644 --- a/usr.bin/truss/syscalls.c +++ b/usr.bin/truss/syscalls.c @@ -50,7 +50,10 @@ static const char rcsid[] = #include #include #include +#include +#define COMPAT_SUNOS #include +#include #include #include #include @@ -116,7 +119,7 @@ struct syscall syscalls[] = { { "exit", 0, 1, { { Hex, 0 }}}, { "access", 1, 2, { { String | IN, 0 }, { Int, 1 }}}, { "sigaction", 1, 3, - { { Signal, 0 }, { Ptr | IN, 1 }, { Ptr | OUT, 2 }}}, + { { Signal, 0 }, { Sigaction | IN, 1 }, { Sigaction | OUT, 2 }}}, { "accept", 1, 3, { { Hex, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } }, { "bind", 1, 3, @@ -141,6 +144,14 @@ struct syscall syscalls[] = { { "kldnext", 0, 1, { { Int, 0 }}}, { "kldstat", 0, 2, { { Int, 0 }, { Ptr, 1 }}}, { "kldfirstmod", 0, 1, { { Int, 0 }}}, + { "nanosleep", 0, 1, { { Timespec, 0 }}}, + { "select", 1, 5, { { Int, 0 }, { Fd_set, 1 }, { Fd_set, 2 }, { Fd_set, 3 }, { Timeval, 4 }}}, + { "poll", 1, 3, { { Pollfd, 0 }, { Int, 1 }, { Int, 2 }}}, + { "gettimeofday", 1, 2, { { Timeval | OUT, 0 }, { Ptr, 1 }}}, + { "clock_gettime", 1, 2, { { Int, 0 }, { Timeval | OUT, 1 }}}, + { "recvfrom", 1, 6, { { Int, 0 }, { Ptr | OUT, 1 }, { Int, 2 }, { Int, 3 }, { Sockaddr | OUT, 4}, {Ptr | OUT, 5}}}, + { "getitimer", 1, 2, { { Int, 0 }, { Itimerval | OUT, 2 }}}, + { "setitimer", 1, 3, { { Int, 0 }, { Itimerval, 1} , { Itimerval | OUT, 2 }}}, { 0, 0, 0, { { 0, 0 }}}, }; @@ -335,6 +346,125 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args) { asprintf(&tmp, "0x%lx", args[sc->offset]); } break; + case Timespec: + { + struct timespec ts; + if (get_struct(fd, (void *)args[sc->offset], &ts, sizeof(ts)) != -1) + asprintf(&tmp, "{%jd %jd}", (intmax_t)ts.tv_sec, (intmax_t)ts.tv_nsec); + else + asprintf(&tmp, "0x%lx", args[sc->offset]); + } + break; + case Timeval: + { + struct timeval tv; + if (get_struct(fd, (void *)args[sc->offset], &tv, sizeof(tv)) != -1) + asprintf(&tmp, "{%jd %jd}", (intmax_t)tv.tv_sec, (intmax_t)tv.tv_usec); + else + asprintf(&tmp, "0x%lx", args[sc->offset]); + } + break; + case Itimerval: + { + struct itimerval itv; + if (get_struct(fd, (void *)args[sc->offset], &itv, sizeof(itv)) != -1) + asprintf(&tmp, "{%jd %jd, %jd %jd}", + (intmax_t)itv.it_interval.tv_sec, + (intmax_t)itv.it_interval.tv_usec, + (intmax_t)itv.it_value.tv_sec, + (intmax_t)itv.it_value.tv_usec); + else + asprintf(&tmp, "0x%lx", args[sc->offset]); + } + break; + case Pollfd: + { + /* + * XXX: A Pollfd argument expects the /next/ syscall argument to be + * the number of fds in the array. This matches the poll syscall. + */ + struct pollfd *pfd; + int numfds = args[sc->offset+1]; + int bytes = sizeof(struct pollfd) * numfds; + int i, tmpsize, u, used; + const int per_fd = 100; + + if ((pfd = malloc(bytes)) == NULL) + err(1, "Cannot malloc %d bytes for pollfd array", bytes); + if (get_struct(fd, (void *)args[sc->offset], pfd, bytes) != -1) { + + used = 0; + tmpsize = 1 + per_fd * numfds + 2; + if ((tmp = malloc(tmpsize)) == NULL) + err(1, "Cannot alloc %d bytes for poll output", tmpsize); + + tmp[used++] = '{'; + for (i = 0; i < numfds; i++) { +#define POLLKNOWN_EVENTS \ + (POLLIN | POLLPRI | POLLOUT | POLLERR | POLLHUP | POLLNVAL | \ + POLLRDNORM |POLLRDBAND | POLLWRBAND | POLLINIGNEOF) + + u += snprintf(tmp + used, per_fd, + "%s%d 0x%hx%s%s%s%s%s%s%s%s%s ", + i > 0 ? " " : "", + pfd[i].fd, + pfd[i].events & ~POLLKNOWN_EVENTS, + pfd[i].events & POLLIN ? "" : "|IN", + pfd[i].events & POLLPRI ? "" : "|PRI", + pfd[i].events & POLLOUT ? "" : "|OUT", + pfd[i].events & POLLERR ? "" : "|ERR", + pfd[i].events & POLLHUP ? "" : "|HUP", + pfd[i].events & POLLNVAL ? "" : "|NVAL", + pfd[i].events & POLLRDNORM ? "" : "|RDNORM", + pfd[i].events & POLLRDBAND ? "" : "|RDBAND", + pfd[i].events & POLLWRBAND ? "" : "|WRBAND"); + if (u > 0) + used += u < per_fd ? u : per_fd; + } + tmp[used++] = '}'; + tmp[used++] = '\0'; + } else + asprintf(&tmp, "0x%lx", args[sc->offset]); + free(pfd); + } + break; + case Fd_set: + { + /* + * XXX: A Fd_set argument expects the /first/ syscall argument to be + * the number of fds in the array. This matches the select syscall. + */ + fd_set *fds; + int numfds = args[0]; + int bytes = _howmany(numfds, _NFDBITS) * _NFDBITS; + int i, tmpsize, u, used; + const int per_fd = 20; + + if ((fds = malloc(bytes)) == NULL) + err(1, "Cannot malloc %d bytes for fd_set array", bytes); + if (get_struct(fd, (void *)args[sc->offset], fds, bytes) != -1) { + used = 0; + tmpsize = 1 + numfds * per_fd + 2; + if ((tmp = malloc(tmpsize)) == NULL) + err(1, "Cannot alloc %d bytes for fd_set output", tmpsize); + + tmp[used++] = '{'; + for (i = 0; i < numfds; i++) { + if (FD_ISSET(i, fds)) { + u = snprintf(tmp + used, per_fd, "%d ", i); + if (u > 0) + used += u < per_fd ? u : per_fd; + } + } + if (tmp[used-1] == ' ') + used--; + tmp[used++] = '}'; + tmp[used++] = '\0'; + } else + asprintf(&tmp, "0x%lx", args[sc->offset]); + free(fds); + } + break; case Signal: { long sig; @@ -456,6 +586,42 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args) { } } break; + case Sigaction: + { + struct sigaction sa; + char *hand; + const char *h; +#define SA_KNOWN_FLAGS \ + (SA_ONSTACK | SA_RESTART | SA_RESETHAND | SA_NOCLDSTOP | SA_NODEFER | \ + SA_NOCLDWAIT | SA_SIGINFO | SA_USERTRAMP) + + + if (get_struct(fd, (void *)args[sc->offset], &sa, sizeof(sa)) != -1) { + + asprintf(&hand, "%p", sa.sa_handler); + if (sa.sa_handler == SIG_DFL) + h = "SIG_DFL"; + else if (sa.sa_handler == SIG_IGN) + h = "SIG_IGN"; + else + h = hand; + asprintf(&tmp, "{ %s 0x%x%s%s%s%s%s%s%s%s ss_t }", + h, + sa.sa_flags & ~SA_KNOWN_FLAGS, + sa.sa_flags & SA_ONSTACK ? "" : "|ONSTACK", + sa.sa_flags & SA_RESTART ? "" : "|RESTART", + sa.sa_flags & SA_RESETHAND ? "" : "|RESETHAND", + sa.sa_flags & SA_NOCLDSTOP ? "" : "|NOCLDSTOP", + sa.sa_flags & SA_NODEFER ? "" : "|NODEFER", + sa.sa_flags & SA_NOCLDWAIT ? "" : "|NOCLDWAIT", + sa.sa_flags & SA_SIGINFO ? "" : "|SIGINFO", + sa.sa_flags & SA_USERTRAMP ? "" : "|USERTRAMP"); + free(hand); + } else + asprintf(&tmp, "0x%lx", args[sc->offset]); + + } + break; } return tmp; } -- cgit v1.1