From d8984f48cb06c45ffa36b832e96510b4235ef9e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Thu, 31 Jul 2008 17:15:21 +0000 Subject: [PATCH] Try to make this code slightly less painful to read. --- usr.bin/truss/syscall.h | 2 +- usr.bin/truss/syscalls.c | 1329 +++++++++++++++++++------------------- 2 files changed, 657 insertions(+), 674 deletions(-) diff --git a/usr.bin/truss/syscall.h b/usr.bin/truss/syscall.h index ccd83bb512c7..39a796a71370 100644 --- a/usr.bin/truss/syscall.h +++ b/usr.bin/truss/syscall.h @@ -25,7 +25,7 @@ * Sigset -- a pointer to a sigset_t. Prints the signals that are set. * Sigprocmask -- the first argument to sigprocmask(). Prints the name. * Kevent -- a pointer to an array of struct kevents. Prints all elements. - * Pathconf -- the 2nd argument of patchconf(). + * Pathconf -- the 2nd argument of pathconf(). * * 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 diff --git a/usr.bin/truss/syscalls.c b/usr.bin/truss/syscalls.c index 18f87fec8807..d1b390b09d59 100644 --- a/usr.bin/truss/syscalls.c +++ b/usr.bin/truss/syscalls.c @@ -92,64 +92,62 @@ static const char rcsid[] = struct syscall syscalls[] = { { "fcntl", 1, 3, - { { Int, 0 } , { Fcntl, 1 }, { Fcntlflag | OUT, 2 }}}, + { { Int, 0 } , { Fcntl, 1 }, { Fcntlflag | OUT, 2 } } }, { "readlink", 1, 3, - { { Name, 0 } , { Readlinkres | OUT, 1 }, { Int, 2 }}}, + { { Name, 0 } , { Readlinkres | OUT, 1 }, { Int, 2 } } }, { "lseek", 2, 3, - { {Int, 0}, {Quad, 1 + QUAD_ALIGN}, - {Whence, 1 + QUAD_SLOTS + QUAD_ALIGN}}}, + { { Int, 0 }, { Quad, 1 + QUAD_ALIGN }, { Whence, 1 + QUAD_SLOTS + QUAD_ALIGN } } }, { "linux_lseek", 2, 3, - { { Int, 0 }, {Int, 1 }, { Whence, 2 }}}, + { { Int, 0 }, { Int, 1 }, { Whence, 2 } } }, { "mmap", 2, 6, - { {Ptr, 0}, {Int, 1}, {Mprot, 2}, {Mmapflags, 3}, {Int, 4}, - {Quad, 5 + QUAD_ALIGN}}}, + { { Ptr, 0 }, { Int, 1 }, { Mprot, 2 }, { Mmapflags, 3 }, { Int, 4 }, { Quad, 5 + QUAD_ALIGN } } }, { "mprotect", 1, 3, - { { Ptr, 0 }, {Int, 1}, {Mprot, 2}}}, + { { Ptr, 0 }, { Int, 1 }, { Mprot, 2 } } }, { "open", 1, 3, - { { Name | IN, 0} , { Open, 1}, {Octal, 2}}}, + { { Name | IN, 0 } , { Open, 1 }, { Octal, 2 } } }, { "mkdir", 1, 2, - { { Name, 0} , {Octal, 1}}}, + { { Name, 0 } , { Octal, 1 } } }, { "linux_open", 1, 3, - { { Name, 0 }, { Hex, 1}, { Octal, 2 }}}, + { { Name, 0 }, { Hex, 1 }, { Octal, 2 } } }, { "close", 1, 1, { { Int, 0 } } }, { "link", 0, 2, - { { Name, 0 }, { Name, 1 }}}, + { { Name, 0 }, { Name, 1 } } }, { "unlink", 0, 1, - { { Name, 0 }}}, + { { Name, 0 } } }, { "chdir", 0, 1, - { { Name, 0 }}}, + { { Name, 0 } } }, { "chroot", 0, 1, - { { Name, 0 }}}, + { { Name, 0 } } }, { "mknod", 0, 3, - { { Name, 0 }, { Octal, 1 }, { Int, 3 }}}, + { { Name, 0 }, { Octal, 1 }, { Int, 3 } } }, { "chmod", 0, 2, - { { Name, 0 }, { Octal, 1 }}}, + { { Name, 0 }, { Octal, 1 } } }, { "chown", 0, 3, - { { Name, 0 }, { Int, 1 }, { Int, 2 }}}, + { { Name, 0 }, { Int, 1 }, { Int, 2 } } }, { "mount", 0, 4, - { { Name, 0 }, { Name, 1 }, { Int, 2 }, { Ptr, 3 }}}, + { { Name, 0 }, { Name, 1 }, { Int, 2 }, { Ptr, 3 } } }, { "umount", 0, 2, - { { Name, 0 }, { Int, 2 }}}, + { { Name, 0 }, { Int, 2 } } }, { "fstat", 1, 2, - { { Int, 0}, { Stat | OUT , 1 }}}, + { { Int, 0 }, { Stat | OUT , 1 } } }, { "stat", 1, 2, - { { Name | IN, 0 }, { Stat | OUT, 1 }}}, + { { Name | IN, 0 }, { Stat | OUT, 1 } } }, { "lstat", 1, 2, - { { Name | IN, 0 }, { Stat | OUT, 1 }}}, + { { Name | IN, 0 }, { Stat | OUT, 1 } } }, { "linux_newstat", 1, 2, - { { Name | IN, 0 }, { Ptr | OUT, 1 }}}, + { { Name | IN, 0 }, { Ptr | OUT, 1 } } }, { "linux_newfstat", 1, 2, - { { Int, 0 }, { Ptr | OUT, 1 }}}, + { { Int, 0 }, { Ptr | OUT, 1 } } }, { "write", 1, 3, - { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 }}}, + { { Int, 0 }, { BinString | IN, 1 }, { Int, 2 } } }, { "ioctl", 1, 3, - { { Int, 0 }, { Ioctl, 1 }, { Hex, 2 }}}, - { "break", 1, 1, { { Ptr, 0 }}}, - { "exit", 0, 1, { { Hex, 0 }}}, - { "access", 1, 2, { { Name | IN, 0 }, { Int, 1 }}}, + { { Int, 0 }, { Ioctl, 1 }, { Hex, 2 } } }, + { "break", 1, 1, { { Ptr, 0 } } }, + { "exit", 0, 1, { { Hex, 0 } } }, + { "access", 1, 2, { { Name | IN, 0 }, { Int, 1 } } }, { "sigaction", 1, 3, - { { Signal, 0 }, { Sigaction | IN, 1 }, { Sigaction | OUT, 2 }}}, + { { Signal, 0 }, { Sigaction | IN, 1 }, { Sigaction | OUT, 2 } } }, { "accept", 1, 3, { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } }, { "bind", 1, 3, @@ -168,58 +166,58 @@ struct syscall syscalls[] = { { { Name | IN, 0 }, { StringArray | IN, 1 }, { StringArray | IN, 2 } } }, { "linux_execve", 1, 3, { { Name | IN, 0 }, { StringArray | IN, 1 }, { StringArray | IN, 2 } } }, - { "kldload", 0, 1, { { Name | IN, 0 }}}, - { "kldunload", 0, 1, { { Int, 0 }}}, - { "kldfind", 0, 1, { { Name | IN, 0 }}}, - { "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 }, { Timespec | OUT, 1 }}}, - { "getitimer", 1, 2, { { Int, 0 }, { Itimerval | OUT, 2 }}}, - { "setitimer", 1, 3, { { Int, 0 }, { Itimerval, 1} , { Itimerval | OUT, 2 }}}, - { "kse_release", 0, 1, { { Timespec, 0 }}}, - { "kevent", 0, 6, { { Int, 0 }, { Kevent, 1 }, { Int, 2 }, { Kevent | OUT, 3 }, { Int, 4 }, { Timespec, 5 }}}, - { "_umtx_lock", 0, 1, { { Umtx, 0 }}}, - { "_umtx_unlock", 0, 1, { { Umtx, 0 }}}, - { "sigprocmask", 0, 3, { { Sigprocmask, 0 }, { Sigset, 1 }, { Sigset | OUT, 2 }}}, - { "unmount", 1, 2, { { Name, 0 }, { Int, 1 }}}, - { "socket", 1, 3, { { Sockdomain, 0}, { Socktype, 1}, {Int, 2 }}}, - { "getrusage", 1, 2, { { Int, 0 }, { Rusage | OUT, 1 }}}, - { "__getcwd", 1, 2, { { Name | OUT, 0}, { Int, 1 }}}, - { "shutdown", 1, 2, { { Int, 0}, { Shutdown, 1}}}, - { "getrlimit", 1, 2, { { Resource, 0}, {Rlimit | OUT, 1}}}, - { "setrlimit", 1, 2, { { Resource, 0}, {Rlimit | IN, 1}}}, + { "kldload", 0, 1, { { Name | IN, 0 } } }, + { "kldunload", 0, 1, { { Int, 0 } } }, + { "kldfind", 0, 1, { { Name | IN, 0 } } }, + { "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 }, { Timespec | OUT, 1 } } }, + { "getitimer", 1, 2, { { Int, 0 }, { Itimerval | OUT, 2 } } }, + { "setitimer", 1, 3, { { Int, 0 }, { Itimerval, 1 } , { Itimerval | OUT, 2 } } }, + { "kse_release", 0, 1, { { Timespec, 0 } } }, + { "kevent", 0, 6, { { Int, 0 }, { Kevent, 1 }, { Int, 2 }, { Kevent | OUT, 3 }, { Int, 4 }, { Timespec, 5 } } }, + { "_umtx_lock", 0, 1, { { Umtx, 0 } } }, + { "_umtx_unlock", 0, 1, { { Umtx, 0 } } }, + { "sigprocmask", 0, 3, { { Sigprocmask, 0 }, { Sigset, 1 }, { Sigset | OUT, 2 } } }, + { "unmount", 1, 2, { { Name, 0 }, { Int, 1 } } }, + { "socket", 1, 3, { { Sockdomain, 0 }, { Socktype, 1 }, { Int, 2 } } }, + { "getrusage", 1, 2, { { Int, 0 }, { Rusage | OUT, 1 } } }, + { "__getcwd", 1, 2, { { Name | OUT, 0 }, { Int, 1 } } }, + { "shutdown", 1, 2, { { Int, 0 }, { Shutdown, 1 } } }, + { "getrlimit", 1, 2, { { Resource, 0 }, { Rlimit | OUT, 1 } } }, + { "setrlimit", 1, 2, { { Resource, 0 }, { Rlimit | IN, 1 } } }, { "utimes", 1, 2, - { { Name | IN, 0 }, { Timeval2 | IN, 1 }}}, + { { Name | IN, 0 }, { Timeval2 | IN, 1 } } }, { "lutimes", 1, 2, - { { Name | IN, 0 }, { Timeval2 | IN, 1 }}}, + { { Name | IN, 0 }, { Timeval2 | IN, 1 } } }, { "futimes", 1, 2, - { { Int, 0 }, { Timeval | IN, 1 }}}, + { { Int, 0 }, { Timeval | IN, 1 } } }, { "chflags", 1, 2, - { { Name | IN, 0 }, { Hex, 1 }}}, + { { Name | IN, 0 }, { Hex, 1 } } }, { "lchflags", 1, 2, - { { Name | IN, 0 }, { Hex, 1 }}}, + { { Name | IN, 0 }, { Hex, 1 } } }, { "pathconf", 1, 2, - { { Name | IN, 0 }, { Pathconf, 1 }}}, + { { Name | IN, 0 }, { Pathconf, 1 } } }, { "truncate", 1, 3, - { { Name | IN, 0 }, { Int | IN, 1 }, { Quad | IN, 2 }}}, + { { Name | IN, 0 }, { Int | IN, 1 }, { Quad | IN, 2 } } }, { "ftruncate", 1, 3, - { { Int | IN, 0 }, { Int | IN, 1 }, { Quad | IN, 2 }}}, + { { Int | IN, 0 }, { Int | IN, 1 }, { Quad | IN, 2 } } }, { "kill", 1, 2, - { { Int | IN, 0 }, { Signal | IN, 1}}}, + { { Int | IN, 0 }, { Signal | IN, 1 } } }, { "munmap", 1, 2, - { { Ptr, 0 }, { Int, 1 }}}, + { { Ptr, 0 }, { Int, 1 } } }, { "read", 1, 3, - { { Int, 0}, { BinString | OUT, 1}, { Int, 2}}}, + { { Int, 0 }, { BinString | OUT, 1 }, { Int, 2 } } }, { "rename", 1, 2, - { { Name , 0} , { Name, 1}}}, + { { Name , 0 } , { Name, 1 } } }, { "symlink", 1, 2, - { { Name , 0} , { Name, 1}}}, - { 0, 0, 0, { { 0, 0 }}}, + { { Name , 0 } , { Name, 1 } } }, + { 0, 0, 0, { { 0, 0 } } }, }; /* Xlat idea taken from strace */ @@ -331,15 +329,18 @@ static struct xlat pathconf_arg[] = { #undef X #undef XEND -/* Searches an xlat array for a value, and returns it if found. Otherwise - return a string representation. */ -static const char -*lookup(struct xlat *xlat, int val, int base) +/* + * Searches an xlat array for a value, and returns it if found. Otherwise + * return a string representation. + */ +static const char * +lookup(struct xlat *xlat, int val, int base) { static char tmp[16]; + for (; xlat->str != NULL; xlat++) if (xlat->val == val) - return xlat->str; + return (xlat->str); switch (base) { case 8: sprintf(tmp, "0%o", val); @@ -354,29 +355,28 @@ static const char errx(1,"Unknown lookup base"); break; } - return tmp; + return (tmp); } static const char * xlookup(struct xlat *xlat, int val) { - return lookup(xlat, val, 16); + + return (lookup(xlat, val, 16)); } /* Searches an xlat array containing bitfield values. Remaining bits set after removing the known ones are printed at the end: IN|0x400 */ -static char -*xlookup_bits(struct xlat *xlat, int val) +static char * +xlookup_bits(struct xlat *xlat, int val) { static char str[512]; int len = 0; int rem = val; - for (; xlat->str != NULL; xlat++) - { - if ((xlat->val & rem) == xlat->val) - { + for (; xlat->str != NULL; xlat++) { + if ((xlat->val & rem) == xlat->val) { /* don't print the "all-bits-zero" string unless all bits are really zero */ if (xlat->val == 0 && val != 0) @@ -391,7 +391,7 @@ static char if (len && str[len - 1] == '|') len--; str[len] = 0; - return str; + return (str); } /* @@ -400,17 +400,18 @@ static char */ struct syscall * -get_syscall(const char *name) { +get_syscall(const char *name) +{ struct syscall *sc = syscalls; if (name == NULL) return (NULL); while (sc->name) { if (!strcmp(name, sc->name)) - return sc; + return (sc); sc++; } - return NULL; + return (NULL); } /* @@ -420,20 +421,21 @@ get_syscall(const char *name) { */ static int -get_struct(int pid, void *offset, void *buf, int len) { +get_struct(int pid, void *offset, void *buf, int len) +{ struct ptrace_io_desc iorequest; - + iorequest.piod_op = PIOD_READ_D; iorequest.piod_offs = offset; iorequest.piod_addr = buf; iorequest.piod_len = len; if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0) - return -1; - return 0; + return (-1); + return (0); } -#define MAXSIZE 4096 -#define BLOCKSIZE 1024 +#define MAXSIZE 4096 +#define BLOCKSIZE 1024 /* * get_string * Copy a string from the process. Note that it is @@ -442,18 +444,19 @@ get_struct(int pid, void *offset, void *buf, int len) { */ static char * -get_string(pid_t pid, void *offset, int max) { +get_string(pid_t pid, void *offset, int max) +{ char *buf; struct ptrace_io_desc iorequest; int totalsize, size; int diff = 0; int i; - - totalsize = size = max ? (max + 1) : BLOCKSIZE; + + totalsize = size = max ? (max + 1) : BLOCKSIZE; buf = malloc(totalsize); if (buf == NULL) - return NULL; - for(;;) { + return (NULL); + for (;;) { diff = totalsize - size; iorequest.piod_op = PIOD_READ_D; iorequest.piod_offs = (char *)offset + diff; @@ -461,7 +464,7 @@ get_string(pid_t pid, void *offset, int max) { iorequest.piod_len = size; if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0) { free(buf); - return NULL; + return (NULL); } for (i = 0 ; i < size; i++) { if (buf[diff + i] == '\0') @@ -471,10 +474,9 @@ get_string(pid_t pid, void *offset, int max) { totalsize += BLOCKSIZE; buf = realloc(buf, totalsize); size = BLOCKSIZE; - } - else { + } else { buf[totalsize] = '\0'; - return buf; + return (buf); } } } @@ -491,562 +493,541 @@ get_string(pid_t pid, void *offset, int max) { */ char * -print_arg(struct syscall_args *sc, unsigned long *args, long retval, struct trussinfo *trussinfo) { - char *tmp = NULL; - int pid = trussinfo->pid; - switch (sc->type & ARG_MASK) { - case Hex: - asprintf(&tmp, "0x%x", (int)args[sc->offset]); - break; - case Octal: - asprintf(&tmp, "0%o", (int)args[sc->offset]); - break; - case Int: - asprintf(&tmp, "%d", (int)args[sc->offset]); - break; - case Name: - { - /* NULL-terminated string. */ - char *tmp2; - tmp2 = get_string(pid, (void*)args[sc->offset], 0); - asprintf(&tmp, "\"%s\"", tmp2); - free(tmp2); - } - break; - case BinString: - { - /* Binary block of data that might have printable characters. - XXX If type|OUT, assume that the length is the syscall's - return value. Otherwise, assume that the length of the block - is in the next syscall argument. */ - int max_string = trussinfo->strsize; - char tmp2[max_string+1], *tmp3; - int len; - int truncated = 0; +print_arg(struct syscall_args *sc, unsigned long *args, long retval, struct trussinfo *trussinfo) +{ + char *tmp = NULL; + int pid = trussinfo->pid; - if (sc->type & OUT) - len = retval; - else - len = args[sc->offset + 1]; + switch (sc->type & ARG_MASK) { + case Hex: + asprintf(&tmp, "0x%x", (int)args[sc->offset]); + break; + case Octal: + asprintf(&tmp, "0%o", (int)args[sc->offset]); + break; + case Int: + asprintf(&tmp, "%d", (int)args[sc->offset]); + break; + case Name: { + /* NULL-terminated string. */ + char *tmp2; + tmp2 = get_string(pid, (void*)args[sc->offset], 0); + asprintf(&tmp, "\"%s\"", tmp2); + free(tmp2); + break; + } + case BinString: { + /* Binary block of data that might have printable characters. + XXX If type|OUT, assume that the length is the syscall's + return value. Otherwise, assume that the length of the block + is in the next syscall argument. */ + int max_string = trussinfo->strsize; + char tmp2[max_string+1], *tmp3; + int len; + int truncated = 0; - /* Don't print more than max_string characters, to avoid word - wrap. If we have to truncate put some ... after the string. - */ - if (len > max_string) { - len = max_string; - truncated = 1; - } - if (len && get_struct(pid, (void*)args[sc->offset], &tmp2, len) != -1) { - tmp3 = malloc(len * 4 + 1); - while (len) { - if (strvisx(tmp3, tmp2, len, VIS_CSTYLE|VIS_TAB|VIS_NL) <= max_string) - break; - len--; - truncated = 1; - }; - asprintf(&tmp, "\"%s\"%s", tmp3, truncated?"...":""); - free(tmp3); - } else - asprintf(&tmp, "0x%lx", args[sc->offset]); - } - break; - case StringArray: - { - int num, size, i; - char *tmp2; - char *string; - char *strarray[100]; /* XXX This is ugly. */ + if (sc->type & OUT) + len = retval; + else + len = args[sc->offset + 1]; - if (get_struct(pid, (void *)args[sc->offset], (void *)&strarray, - sizeof(strarray)) == -1) { - err(1, "get_struct %p", (void *)args[sc->offset]); - } - num = 0; - size = 0; + /* Don't print more than max_string characters, to avoid word + wrap. If we have to truncate put some ... after the string. + */ + if (len > max_string) { + len = max_string; + truncated = 1; + } + if (len && get_struct(pid, (void*)args[sc->offset], &tmp2, len) != -1) { + tmp3 = malloc(len * 4 + 1); + while (len) { + if (strvisx(tmp3, tmp2, len, VIS_CSTYLE|VIS_TAB|VIS_NL) <= max_string) + break; + len--; + truncated = 1; + }; + asprintf(&tmp, "\"%s\"%s", tmp3, truncated?"...":""); + free(tmp3); + } else { + asprintf(&tmp, "0x%lx", args[sc->offset]); + } + break; + } + case StringArray: { + int num, size, i; + char *tmp2; + char *string; + char *strarray[100]; /* XXX This is ugly. */ - /* Find out how large of a buffer we'll need. */ - while (strarray[num] != NULL) { - string = get_string(pid, (void*)strarray[num], 0); - size += strlen(string); - free(string); - num++; - } - size += 4 + (num * 4); - tmp = (char *)malloc(size); - tmp2 = tmp; + if (get_struct(pid, (void *)args[sc->offset], (void *)&strarray, + sizeof(strarray)) == -1) { + err(1, "get_struct %p", (void *)args[sc->offset]); + } + num = 0; + size = 0; - tmp2 += sprintf(tmp2, " ["); - for (i = 0; i < num; i++) { - string = get_string(pid, (void*)strarray[i], 0); - tmp2 += sprintf(tmp2, " \"%s\"%c", string, (i+1 == num) ? ' ' : ','); - free(string); - } - tmp2 += sprintf(tmp2, "]"); - } - break; + /* Find out how large of a buffer we'll need. */ + while (strarray[num] != NULL) { + string = get_string(pid, (void*)strarray[num], 0); + size += strlen(string); + free(string); + num++; + } + size += 4 + (num * 4); + tmp = (char *)malloc(size); + tmp2 = tmp; + + tmp2 += sprintf(tmp2, " ["); + for (i = 0; i < num; i++) { + string = get_string(pid, (void*)strarray[i], 0); + tmp2 += sprintf(tmp2, " \"%s\"%c", string, (i+1 == num) ? ' ' : ','); + free(string); + } + tmp2 += sprintf(tmp2, "]"); + break; + } #ifdef __LP64__ - case Quad: - asprintf(&tmp, "0x%lx", args[sc->offset]); - break; + case Quad: + asprintf(&tmp, "0x%lx", args[sc->offset]); + break; #else - case Quad: - { - unsigned long long ll; - ll = *(unsigned long long *)(args + sc->offset); - asprintf(&tmp, "0x%llx", ll); - break; - } + case Quad: { + unsigned long long ll; + ll = *(unsigned long long *)(args + sc->offset); + asprintf(&tmp, "0x%llx", ll); + break; + } #endif - case Ptr: - asprintf(&tmp, "0x%lx", args[sc->offset]); - break; - case Readlinkres: - { - char *tmp2; - if (retval == -1) { - tmp = strdup(""); - break; - } - tmp2 = get_string(pid, (void*)args[sc->offset], retval); - asprintf(&tmp, "\"%s\"", tmp2); - free(tmp2); - } - break; - case Ioctl: - { - const char *temp = ioctlname(args[sc->offset]); - if (temp) - tmp = strdup(temp); - else - { - unsigned long arg = args[sc->offset]; - asprintf(&tmp, "0x%lx { IO%s%s 0x%lx('%c'), %lu, %lu}", arg, - arg&IOC_OUT?"R":"", arg&IOC_IN?"W":"", - IOCGROUP(arg), isprint(IOCGROUP(arg))?(char)IOCGROUP(arg):'?', - arg & 0xFF, IOCPARM_LEN(arg)); - } - } - break; - case Umtx: - { - struct umtx umtx; - if (get_struct(pid, (void *)args[sc->offset], &umtx, sizeof(umtx)) != -1) - asprintf(&tmp, "{0x%lx}", (long)umtx.u_owner); - else - asprintf(&tmp, "0x%lx", args[sc->offset]); - } - break; - case Timespec: - { - struct timespec ts; - if (get_struct(pid, (void *)args[sc->offset], &ts, sizeof(ts)) != -1) - asprintf(&tmp, "{%ld.%09ld}", (long)ts.tv_sec, ts.tv_nsec); - else - asprintf(&tmp, "0x%lx", args[sc->offset]); - } - break; - case Timeval: - { - struct timeval tv; - if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv)) != -1) - asprintf(&tmp, "{%ld.%06ld}", (long)tv.tv_sec, tv.tv_usec); - else - asprintf(&tmp, "0x%lx", args[sc->offset]); - } - break; - case Timeval2: - { - struct timeval tv[2]; - if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv)) != -1) - asprintf(&tmp, "{%ld.%06ld, %ld.%06ld}", - (long)tv[0].tv_sec, tv[0].tv_usec, - (long)tv[1].tv_sec, tv[1].tv_usec); - else - asprintf(&tmp, "0x%lx", args[sc->offset]); - } - break; - case Itimerval: - { - struct itimerval itv; - if (get_struct(pid, (void *)args[sc->offset], &itv, sizeof(itv)) != -1) - asprintf(&tmp, "{%ld.%06ld, %ld.%06ld}", - (long)itv.it_interval.tv_sec, - itv.it_interval.tv_usec, - (long)itv.it_value.tv_sec, - 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(pid, (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++) { - - u = snprintf(tmp + used, per_fd, - "%s%d/%s", - i > 0 ? " " : "", - pfd[i].fd, - xlookup_bits(poll_flags, pfd[i].events) ); - if (u > 0) - used += u < per_fd ? u : per_fd; + case Ptr: + asprintf(&tmp, "0x%lx", args[sc->offset]); + break; + case Readlinkres: { + char *tmp2; + if (retval == -1) { + tmp = strdup(""); + break; + } + tmp2 = get_string(pid, (void*)args[sc->offset], retval); + asprintf(&tmp, "\"%s\"", tmp2); + free(tmp2); + break; } - 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(pid, (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; - } + case Ioctl: { + const char *temp = ioctlname(args[sc->offset]); + if (temp) { + tmp = strdup(temp); + } else { + unsigned long arg = args[sc->offset]; + asprintf(&tmp, "0x%lx { IO%s%s 0x%lx('%c'), %lu, %lu }", arg, + arg&IOC_OUT?"R":"", arg&IOC_IN?"W":"", + IOCGROUP(arg), isprint(IOCGROUP(arg))?(char)IOCGROUP(arg):'?', + arg & 0xFF, IOCPARM_LEN(arg)); + } + break; } - 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; + case Umtx: { + struct umtx umtx; + if (get_struct(pid, (void *)args[sc->offset], &umtx, sizeof(umtx)) != -1) + asprintf(&tmp, "{ 0x%lx }", (long)umtx.u_owner); + else + asprintf(&tmp, "0x%lx", args[sc->offset]); + break; + } + case Timespec: { + struct timespec ts; + if (get_struct(pid, (void *)args[sc->offset], &ts, sizeof(ts)) != -1) + asprintf(&tmp, "{%ld.%09ld }", (long)ts.tv_sec, ts.tv_nsec); + else + asprintf(&tmp, "0x%lx", args[sc->offset]); + break; + } + case Timeval: { + struct timeval tv; + if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv)) != -1) + asprintf(&tmp, "{%ld.%06ld }", (long)tv.tv_sec, tv.tv_usec); + else + asprintf(&tmp, "0x%lx", args[sc->offset]); + break; + } + case Timeval2: { + struct timeval tv[2]; + if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv)) != -1) + asprintf(&tmp, "{%ld.%06ld, %ld.%06ld }", + (long)tv[0].tv_sec, tv[0].tv_usec, + (long)tv[1].tv_sec, tv[1].tv_usec); + else + asprintf(&tmp, "0x%lx", args[sc->offset]); + break; + } + case Itimerval: { + struct itimerval itv; + if (get_struct(pid, (void *)args[sc->offset], &itv, sizeof(itv)) != -1) + asprintf(&tmp, "{%ld.%06ld, %ld.%06ld }", + (long)itv.it_interval.tv_sec, + itv.it_interval.tv_usec, + (long)itv.it_value.tv_sec, + 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; - sig = args[sc->offset]; - tmp = strsig(sig); - if (tmp == NULL) - asprintf(&tmp, "%ld", sig); - } - break; - case Sigset: - { - long sig; - sigset_t ss; - int i, used; + if ((pfd = malloc(bytes)) == NULL) + err(1, "Cannot malloc %d bytes for pollfd array", bytes); + if (get_struct(pid, (void *)args[sc->offset], pfd, bytes) != -1) { - sig = args[sc->offset]; - if (get_struct(pid, (void *)args[sc->offset], (void *)&ss, - sizeof(ss)) == -1) - { - asprintf(&tmp, "0x%lx", args[sc->offset]); - break; - } - tmp = malloc(sys_nsig * 8); /* 7 bytes avg per signal name */ - used = 0; - for (i = 1; i < sys_nsig; i++) - { - if (sigismember(&ss, i)) - { - used += sprintf(tmp + used, "%s|", strsig(i)); - } - } - if(used) - tmp[used-1] = 0; - else - strcpy(tmp, "0x0"); - } - break; - case Sigprocmask: - { - switch (args[sc->offset]) { + 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++) { + + u = snprintf(tmp + used, per_fd, + "%s%d/%s", + i > 0 ? " " : "", + pfd[i].fd, + xlookup_bits(poll_flags, pfd[i].events) ); + 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(pid, (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; + + sig = args[sc->offset]; + tmp = strsig(sig); + if (tmp == NULL) + asprintf(&tmp, "%ld", sig); + break; + } + case Sigset: { + long sig; + sigset_t ss; + int i, used; + + sig = args[sc->offset]; + if (get_struct(pid, (void *)args[sc->offset], (void *)&ss, sizeof(ss)) == -1) { + asprintf(&tmp, "0x%lx", args[sc->offset]); + break; + } + tmp = malloc(sys_nsig * 8); /* 7 bytes avg per signal name */ + used = 0; + for (i = 1; i < sys_nsig; i++) { + if (sigismember(&ss, i)) { + used += sprintf(tmp + used, "%s|", strsig(i)); + } + } + if (used) + tmp[used-1] = 0; + else + strcpy(tmp, "0x0"); + break; + } + case Sigprocmask: { + switch (args[sc->offset]) { #define S(a) case a: tmp = strdup(#a); break; - S(SIG_BLOCK); - S(SIG_UNBLOCK); - S(SIG_SETMASK); + S(SIG_BLOCK); + S(SIG_UNBLOCK); + S(SIG_SETMASK); #undef S + } + if (tmp == NULL) + asprintf(&tmp, "0x%lx", args[sc->offset]); + break; } - if (tmp == NULL) - asprintf(&tmp, "0x%lx", args[sc->offset]); - } - break; - - case Fcntlflag: - { - /* XXX output depends on the value of the previous argument */ - switch (args[sc->offset-1]) { - case F_SETFD: - tmp = strdup(xlookup_bits(fcntlfd_arg, args[sc->offset])); - break; - case F_SETFL: - tmp = strdup(xlookup_bits(fcntlfl_arg, args[sc->offset])); - break; - case F_GETFD: - case F_GETFL: - case F_GETOWN: - tmp = strdup(""); - break; - default: - asprintf(&tmp, "0x%lx", args[sc->offset]); - break; - } - } - break; - case Open: - tmp = strdup(xlookup_bits(open_flags, args[sc->offset])); - break; - case Fcntl: - tmp = strdup(xlookup(fcntl_arg, args[sc->offset])); - break; - case Mprot: - tmp = strdup(xlookup_bits(mprot_flags, args[sc->offset])); - break; - case Mmapflags: - tmp = strdup(xlookup_bits(mmap_flags, args[sc->offset])); - break; - case Whence: - tmp = strdup(xlookup(whence_arg, args[sc->offset])); - break; - case Sockdomain: - tmp = strdup(xlookup(sockdomain_arg, args[sc->offset])); - break; - case Socktype: - tmp = strdup(xlookup(socktype_arg, args[sc->offset])); - break; - case Shutdown: - tmp = strdup(xlookup(shutdown_arg, args[sc->offset])); - break; - case Resource: - tmp = strdup(xlookup(resource_arg, args[sc->offset])); - break; - case Pathconf: - tmp = strdup(xlookup(pathconf_arg, args[sc->offset])); - break; - case Sockaddr: - { - struct sockaddr_storage ss; - char addr[64]; - struct sockaddr_in *lsin; - struct sockaddr_in6 *lsin6; - struct sockaddr_un *sun; - struct sockaddr *sa; - char *p; - u_char *q; - int i; - - if (args[sc->offset] == 0) { - asprintf(&tmp, "NULL"); - break; - } - - /* yuck: get ss_len */ - if (get_struct(pid, (void *)args[sc->offset], (void *)&ss, - sizeof(ss.ss_len) + sizeof(ss.ss_family)) == -1) - err(1, "get_struct %p", (void *)args[sc->offset]); - /* - * If ss_len is 0, then try to guess from the sockaddr type. - * AF_UNIX may be initialized incorrectly, so always frob - * it by using the "right" size. - */ - if (ss.ss_len == 0 || ss.ss_family == AF_UNIX) { - switch (ss.ss_family) { - case AF_INET: - ss.ss_len = sizeof(*lsin); - break; - case AF_UNIX: - ss.ss_len = sizeof(*sun); - break; - default: - /* hurrrr */ - break; - } - } - if (get_struct(pid, (void *)args[sc->offset], (void *)&ss, ss.ss_len) - == -1) { - err(2, "get_struct %p", (void *)args[sc->offset]); - } - - switch (ss.ss_family) { - case AF_INET: - lsin = (struct sockaddr_in *)&ss; - inet_ntop(AF_INET, &lsin->sin_addr, addr, sizeof addr); - asprintf(&tmp, "{ AF_INET %s:%d }", addr, htons(lsin->sin_port)); - break; - case AF_INET6: - lsin6 = (struct sockaddr_in6 *)&ss; - inet_ntop(AF_INET6, &lsin6->sin6_addr, addr, sizeof addr); - asprintf(&tmp, "{ AF_INET6 [%s]:%d }", addr, htons(lsin6->sin6_port)); - break; - case AF_UNIX: - sun = (struct sockaddr_un *)&ss; - asprintf(&tmp, "{ AF_UNIX \"%s\" }", sun->sun_path); - break; - default: - sa = (struct sockaddr *)&ss; - asprintf(&tmp, "{ sa_len = %d, sa_family = %d, sa_data = {%n%*s } }", - (int)sa->sa_len, (int)sa->sa_family, &i, - 6 * (int)(sa->sa_len - ((char *)&sa->sa_data - (char *)sa)), ""); - if (tmp != NULL) { - p = tmp + i; - for (q = (u_char *)&sa->sa_data; q < (u_char *)sa + sa->sa_len; q++) - p += sprintf(p, " %#02x,", *q); + case Fcntlflag: { + /* XXX output depends on the value of the previous argument */ + switch (args[sc->offset-1]) { + case F_SETFD: + tmp = strdup(xlookup_bits(fcntlfd_arg, args[sc->offset])); + break; + case F_SETFL: + tmp = strdup(xlookup_bits(fcntlfl_arg, args[sc->offset])); + break; + case F_GETFD: + case F_GETFL: + case F_GETOWN: + tmp = strdup(""); + break; + default: + asprintf(&tmp, "0x%lx", args[sc->offset]); + break; + } + break; } - } - } - break; - case Sigaction: - { - struct sigaction sa; - char *hand; - const char *h; + case Open: + tmp = strdup(xlookup_bits(open_flags, args[sc->offset])); + break; + case Fcntl: + tmp = strdup(xlookup(fcntl_arg, args[sc->offset])); + break; + case Mprot: + tmp = strdup(xlookup_bits(mprot_flags, args[sc->offset])); + break; + case Mmapflags: + tmp = strdup(xlookup_bits(mmap_flags, args[sc->offset])); + break; + case Whence: + tmp = strdup(xlookup(whence_arg, args[sc->offset])); + break; + case Sockdomain: + tmp = strdup(xlookup(sockdomain_arg, args[sc->offset])); + break; + case Socktype: + tmp = strdup(xlookup(socktype_arg, args[sc->offset])); + break; + case Shutdown: + tmp = strdup(xlookup(shutdown_arg, args[sc->offset])); + break; + case Resource: + tmp = strdup(xlookup(resource_arg, args[sc->offset])); + break; + case Pathconf: + tmp = strdup(xlookup(pathconf_arg, args[sc->offset])); + break; + case Sockaddr: { + struct sockaddr_storage ss; + char addr[64]; + struct sockaddr_in *lsin; + struct sockaddr_in6 *lsin6; + struct sockaddr_un *sun; + struct sockaddr *sa; + char *p; + u_char *q; + int i; - if (get_struct(pid, (void *)args[sc->offset], &sa, sizeof(sa)) != -1) { + if (args[sc->offset] == 0) { + asprintf(&tmp, "NULL"); + break; + } - 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; + /* yuck: get ss_len */ + if (get_struct(pid, (void *)args[sc->offset], (void *)&ss, + sizeof(ss.ss_len) + sizeof(ss.ss_family)) == -1) + err(1, "get_struct %p", (void *)args[sc->offset]); + /* + * If ss_len is 0, then try to guess from the sockaddr type. + * AF_UNIX may be initialized incorrectly, so always frob + * it by using the "right" size. + */ + if (ss.ss_len == 0 || ss.ss_family == AF_UNIX) { + switch (ss.ss_family) { + case AF_INET: + ss.ss_len = sizeof(*lsin); + break; + case AF_UNIX: + ss.ss_len = sizeof(*sun); + break; + default: + /* hurrrr */ + break; + } + } + if (get_struct(pid, (void *)args[sc->offset], (void *)&ss, ss.ss_len) + == -1) { + err(2, "get_struct %p", (void *)args[sc->offset]); + } - asprintf(&tmp, "{ %s %s ss_t }", - h, - xlookup_bits(sigaction_flags, sa.sa_flags)); - free(hand); - } else - asprintf(&tmp, "0x%lx", args[sc->offset]); - - } - break; - case Kevent: - { - /* - * XXX XXX: the size of the array is determined by either the - * next syscall argument, or by the syscall returnvalue, - * depending on which argument number we are. This matches the - * kevent syscall, but luckily that's the only syscall that uses - * them. - */ - struct kevent *ke; - int numevents = -1; - int bytes = 0; - int i, tmpsize, u, used; - const int per_ke = 100; - - if (sc->offset == 1) - numevents = args[sc->offset+1]; - else if (sc->offset == 3 && retval != -1) - numevents = retval; - - if (numevents >= 0) - bytes = sizeof(struct kevent) * numevents; - if ((ke = malloc(bytes)) == NULL) - err(1, "Cannot malloc %d bytes for kevent array", bytes); - if (numevents >= 0 && get_struct(pid, (void *)args[sc->offset], ke, bytes) != -1) { - used = 0; - tmpsize = 1 + per_ke * numevents + 2; - if ((tmp = malloc(tmpsize)) == NULL) - err(1, "Cannot alloc %d bytes for kevent output", tmpsize); - - tmp[used++] = '{'; - for (i = 0; i < numevents; i++) { - u = snprintf(tmp + used, per_ke, - "%s%p,%s,%s,%d,%p,%p", - i > 0 ? " " : "", - (void *)ke[i].ident, - xlookup(kevent_filters, ke[i].filter), - xlookup_bits(kevent_flags, ke[i].flags), - ke[i].fflags, - (void *)ke[i].data, - (void *)ke[i].udata); - if (u > 0) - used += u < per_ke ? u : per_ke; + switch (ss.ss_family) { + case AF_INET: + lsin = (struct sockaddr_in *)&ss; + inet_ntop(AF_INET, &lsin->sin_addr, addr, sizeof addr); + asprintf(&tmp, "{ AF_INET %s:%d }", addr, htons(lsin->sin_port)); + break; + case AF_INET6: + lsin6 = (struct sockaddr_in6 *)&ss; + inet_ntop(AF_INET6, &lsin6->sin6_addr, addr, sizeof addr); + asprintf(&tmp, "{ AF_INET6 [%s]:%d }", addr, htons(lsin6->sin6_port)); + break; + case AF_UNIX: + sun = (struct sockaddr_un *)&ss; + asprintf(&tmp, "{ AF_UNIX \"%s\" }", sun->sun_path); + break; + default: + sa = (struct sockaddr *)&ss; + asprintf(&tmp, "{ sa_len = %d, sa_family = %d, sa_data = {%n%*s } }", + (int)sa->sa_len, (int)sa->sa_family, &i, + 6 * (int)(sa->sa_len - ((char *)&sa->sa_data - (char *)sa)), ""); + if (tmp != NULL) { + p = tmp + i; + for (q = (u_char *)&sa->sa_data; q < (u_char *)sa + sa->sa_len; q++) + p += sprintf(p, " %#02x,", *q); + } + } + break; } - tmp[used++] = '}'; - tmp[used++] = '\0'; - } else - asprintf(&tmp, "0x%lx", args[sc->offset]); - free(ke); - } - break; - case Stat: - { - struct stat st; - if (get_struct(pid, (void *)args[sc->offset], &st, sizeof(st)) != -1) { - char mode[12]; - strmode(st.st_mode, mode); - asprintf(&tmp, "{mode=%s,inode=%jd,size=%jd,blksize=%ld}", - mode, - (intmax_t)st.st_ino,(intmax_t)st.st_size,(long)st.st_blksize); - } else - asprintf(&tmp, "0x%lx", args[sc->offset]); - } - break; - case Rusage: - { - struct rusage ru; - if (get_struct(pid, (void *)args[sc->offset], &ru, sizeof(ru)) != -1) - asprintf(&tmp, "{u=%ld.%06ld,s=%ld.%06ld,in=%ld,out=%ld}", - (long)ru.ru_utime.tv_sec, ru.ru_utime.tv_usec, - (long)ru.ru_stime.tv_sec, ru.ru_stime.tv_usec, - ru.ru_inblock, ru.ru_oublock); - else - asprintf(&tmp, "0x%lx", args[sc->offset]); - } - break; - case Rlimit: - { - struct rlimit rl; - if (get_struct(pid, (void *)args[sc->offset], &rl, sizeof(rl)) != -1) - asprintf(&tmp, "{cur=%ju,max=%ju}", - rl.rlim_cur, rl.rlim_max); - else - asprintf(&tmp, "0x%lx", args[sc->offset]); - } - break; - default: - errx(1, "Invalid argument type %d\n", sc->type & ARG_MASK); - } - return tmp; + case Sigaction: { + struct sigaction sa; + char *hand; + const char *h; + + if (get_struct(pid, (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 %s ss_t }", + h, + xlookup_bits(sigaction_flags, sa.sa_flags)); + free(hand); + } else { + asprintf(&tmp, "0x%lx", args[sc->offset]); + } + break; + } + case Kevent: { + /* + * XXX XXX: the size of the array is determined by either the + * next syscall argument, or by the syscall returnvalue, + * depending on which argument number we are. This matches the + * kevent syscall, but luckily that's the only syscall that uses + * them. + */ + struct kevent *ke; + int numevents = -1; + int bytes = 0; + int i, tmpsize, u, used; + const int per_ke = 100; + + if (sc->offset == 1) + numevents = args[sc->offset+1]; + else if (sc->offset == 3 && retval != -1) + numevents = retval; + + if (numevents >= 0) + bytes = sizeof(struct kevent) * numevents; + if ((ke = malloc(bytes)) == NULL) + err(1, "Cannot malloc %d bytes for kevent array", bytes); + if (numevents >= 0 && get_struct(pid, (void *)args[sc->offset], ke, bytes) != -1) { + used = 0; + tmpsize = 1 + per_ke * numevents + 2; + if ((tmp = malloc(tmpsize)) == NULL) + err(1, "Cannot alloc %d bytes for kevent output", tmpsize); + + tmp[used++] = '{'; + for (i = 0; i < numevents; i++) { + u = snprintf(tmp + used, per_ke, + "%s%p,%s,%s,%d,%p,%p", + i > 0 ? " " : "", + (void *)ke[i].ident, + xlookup(kevent_filters, ke[i].filter), + xlookup_bits(kevent_flags, ke[i].flags), + ke[i].fflags, + (void *)ke[i].data, + (void *)ke[i].udata); + if (u > 0) + used += u < per_ke ? u : per_ke; + } + tmp[used++] = '}'; + tmp[used++] = '\0'; + } else { + asprintf(&tmp, "0x%lx", args[sc->offset]); + } + free(ke); + break; + } + case Stat: { + struct stat st; + if (get_struct(pid, (void *)args[sc->offset], &st, sizeof(st)) != -1) { + char mode[12]; + strmode(st.st_mode, mode); + asprintf(&tmp, "{ mode=%s,inode=%jd,size=%jd,blksize=%ld }", + mode, + (intmax_t)st.st_ino,(intmax_t)st.st_size,(long)st.st_blksize); + } else { + asprintf(&tmp, "0x%lx", args[sc->offset]); + } + break; + } + case Rusage: { + struct rusage ru; + if (get_struct(pid, (void *)args[sc->offset], &ru, sizeof(ru)) != -1) { + asprintf(&tmp, "{ u=%ld.%06ld,s=%ld.%06ld,in=%ld,out=%ld }", + (long)ru.ru_utime.tv_sec, ru.ru_utime.tv_usec, + (long)ru.ru_stime.tv_sec, ru.ru_stime.tv_usec, + ru.ru_inblock, ru.ru_oublock); + } else { + asprintf(&tmp, "0x%lx", args[sc->offset]); + } + break; + } + case Rlimit: { + struct rlimit rl; + if (get_struct(pid, (void *)args[sc->offset], &rl, sizeof(rl)) != -1) { + asprintf(&tmp, "{ cur=%ju,max=%ju }", + rl.rlim_cur, rl.rlim_max); + } else { + asprintf(&tmp, "0x%lx", args[sc->offset]); + } + break; + } + default: + errx(1, "Invalid argument type %d\n", sc->type & ARG_MASK); + } + return (tmp); } - /* * print_syscall * Print (to outfile) the system call and its arguments. Note that @@ -1055,53 +1036,55 @@ print_arg(struct syscall_args *sc, unsigned long *args, long retval, struct trus */ void -print_syscall(struct trussinfo *trussinfo, const char *name, int nargs, char **s_args) { - int i; - int len = 0; - struct timespec timediff; +print_syscall(struct trussinfo *trussinfo, const char *name, int nargs, char **s_args) +{ + int i; + int len = 0; + struct timespec timediff; - if (trussinfo->flags & FOLLOWFORKS) - len += fprintf(trussinfo->outfile, "%5d: ", trussinfo->pid); + if (trussinfo->flags & FOLLOWFORKS) + len += fprintf(trussinfo->outfile, "%5d: ", trussinfo->pid); - if (name != NULL && (!strcmp(name, "execve") || !strcmp(name, "exit"))) { - clock_gettime(CLOCK_REALTIME, &trussinfo->after); - } + if (name != NULL && (!strcmp(name, "execve") || !strcmp(name, "exit"))) { + clock_gettime(CLOCK_REALTIME, &trussinfo->after); + } - if (trussinfo->flags & ABSOLUTETIMESTAMPS) { - timespecsubt(&trussinfo->after, &trussinfo->start_time, &timediff); - len += fprintf(trussinfo->outfile, "%ld.%09ld ", - (long)timediff.tv_sec, timediff.tv_nsec); - } + if (trussinfo->flags & ABSOLUTETIMESTAMPS) { + timespecsubt(&trussinfo->after, &trussinfo->start_time, &timediff); + len += fprintf(trussinfo->outfile, "%ld.%09ld ", + (long)timediff.tv_sec, timediff.tv_nsec); + } - if (trussinfo->flags & RELATIVETIMESTAMPS) { - timespecsubt(&trussinfo->after, &trussinfo->before, &timediff); - len += fprintf(trussinfo->outfile, "%ld.%09ld ", - (long)timediff.tv_sec, timediff.tv_nsec); - } + if (trussinfo->flags & RELATIVETIMESTAMPS) { + timespecsubt(&trussinfo->after, &trussinfo->before, &timediff); + len += fprintf(trussinfo->outfile, "%ld.%09ld ", + (long)timediff.tv_sec, timediff.tv_nsec); + } - len += fprintf(trussinfo->outfile, "%s(", name); + len += fprintf(trussinfo->outfile, "%s(", name); - for (i = 0; i < nargs; i++) { - if (s_args[i]) - len += fprintf(trussinfo->outfile, "%s", s_args[i]); - else - len += fprintf(trussinfo->outfile, ""); - len += fprintf(trussinfo->outfile, "%s", i < (nargs - 1) ? "," : ""); - } - len += fprintf(trussinfo->outfile, ")"); - for (i = 0; i < 6 - (len / 8); i++) - fprintf(trussinfo->outfile, "\t"); + for (i = 0; i < nargs; i++) { + if (s_args[i]) + len += fprintf(trussinfo->outfile, "%s", s_args[i]); + else + len += fprintf(trussinfo->outfile, ""); + len += fprintf(trussinfo->outfile, "%s", i < (nargs - 1) ? "," : ""); + } + len += fprintf(trussinfo->outfile, ")"); + for (i = 0; i < 6 - (len / 8); i++) + fprintf(trussinfo->outfile, "\t"); } void print_syscall_ret(struct trussinfo *trussinfo, const char *name, int nargs, char **s_args, int errorp, long retval) { - print_syscall(trussinfo, name, nargs, s_args); - fflush(trussinfo->outfile); - if (errorp) { - fprintf(trussinfo->outfile, " ERR#%ld '%s'\n", retval, strerror(retval)); - } else { - fprintf(trussinfo->outfile, " = %ld (0x%lx)\n", retval, retval); - } + + print_syscall(trussinfo, name, nargs, s_args); + fflush(trussinfo->outfile); + if (errorp) { + fprintf(trussinfo->outfile, " ERR#%ld '%s'\n", retval, strerror(retval)); + } else { + fprintf(trussinfo->outfile, " = %ld (0x%lx)\n", retval, retval); + } }