From 2a326134d0e35fa054037847b1446e8c4b4d61df Mon Sep 17 00:00:00 2001 From: brian Date: Mon, 2 Jan 2006 08:36:25 +0000 Subject: Add a -s flag for the same functionality as strace. Introduce a Name type which is a String type that has no -s limitations applied to it. Change most Strings in the code to Names and add a few extra syscalls, namely munmap, read, rename and symlink. This was enough to facilitate following file descriptor allocations in the code more easily and getting a hint at what's being read/written from/to files. More syscalls should really be added. While here, fix an off-by-one bug in the buffer truncation code and add a fflush so that truss's output reflects the syscall that the program is stuck in. Sponsored by: Sophos/Activestate MFC after: 2 weeks --- usr.bin/truss/alpha-fbsd.c | 4 +- usr.bin/truss/amd64-fbsd.c | 4 +- usr.bin/truss/amd64-fbsd32.c | 4 +- usr.bin/truss/amd64-linux32.c | 4 +- usr.bin/truss/i386-fbsd.c | 4 +- usr.bin/truss/i386-linux.c | 4 +- usr.bin/truss/ia64-fbsd.c | 4 +- usr.bin/truss/main.c | 10 +++-- usr.bin/truss/sparc64-fbsd.c | 4 +- usr.bin/truss/syscall.h | 4 +- usr.bin/truss/syscalls.c | 86 ++++++++++++++++++++++++++----------------- usr.bin/truss/truss.1 | 12 ++++++ usr.bin/truss/truss.h | 1 + 13 files changed, 91 insertions(+), 54 deletions(-) (limited to 'usr.bin/truss') diff --git a/usr.bin/truss/alpha-fbsd.c b/usr.bin/truss/alpha-fbsd.c index 5e7fa99..7afcaa8 100644 --- a/usr.bin/truss/alpha-fbsd.c +++ b/usr.bin/truss/alpha-fbsd.c @@ -238,7 +238,7 @@ alpha_syscall_entry(struct trussinfo *trussinfo, int nargs) { i < (fsc.nargs - 1) ? "," : ""); #endif if (sc && !(sc->args[i].type & OUT)) { - fsc.s_args[i] = print_arg(Procfd, &sc->args[i], fsc.args, 0); + fsc.s_args[i] = print_arg(Procfd, &sc->args[i], fsc.args, 0, trussinfo); } } #if DEBUG @@ -342,7 +342,7 @@ alpha_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused) if (errorp) asprintf(&temp, "0x%lx", fsc.args[sc->args[i].offset]); else - temp = print_arg(Procfd, &sc->args[i], fsc.args, retval); + temp = print_arg(Procfd, &sc->args[i], fsc.args, retval, trussinfo); fsc.s_args[i] = temp; } } diff --git a/usr.bin/truss/amd64-fbsd.c b/usr.bin/truss/amd64-fbsd.c index 7fb5d26..701813b 100644 --- a/usr.bin/truss/amd64-fbsd.c +++ b/usr.bin/truss/amd64-fbsd.c @@ -223,7 +223,7 @@ amd64_syscall_entry(struct trussinfo *trussinfo, int nargs) { i < (fsc.nargs - 1) ? "," : ""); #endif if (sc && !(sc->args[i].type & OUT)) { - fsc.s_args[i] = print_arg(Procfd, &sc->args[i], fsc.args, 0); + fsc.s_args[i] = print_arg(Procfd, &sc->args[i], fsc.args, 0, trussinfo); } } #if DEBUG @@ -327,7 +327,7 @@ amd64_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused) if (errorp) asprintf(&temp, "0x%lx", fsc.args[sc->args[i].offset]); else - temp = print_arg(Procfd, &sc->args[i], fsc.args, retval); + temp = print_arg(Procfd, &sc->args[i], fsc.args, retval, trussinfo); fsc.s_args[i] = temp; } } diff --git a/usr.bin/truss/amd64-fbsd32.c b/usr.bin/truss/amd64-fbsd32.c index 45da1cd..d9ee202 100644 --- a/usr.bin/truss/amd64-fbsd32.c +++ b/usr.bin/truss/amd64-fbsd32.c @@ -217,7 +217,7 @@ i386_syscall_entry(struct trussinfo *trussinfo, int nargs) { i < (fsc.nargs - 1) ? "," : ""); #endif if (sc && !(sc->args[i].type & OUT)) { - fsc.s_args[i] = print_arg(Procfd, &sc->args[i], fsc.args, 0); + fsc.s_args[i] = print_arg(Procfd, &sc->args[i], fsc.args, 0, trussinfo); } } #if DEBUG @@ -322,7 +322,7 @@ i386_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused) if (errorp) asprintf(&temp, "0x%lx", fsc.args[sc->args[i].offset]); else - temp = print_arg(Procfd, &sc->args[i], fsc.args, retval); + temp = print_arg(Procfd, &sc->args[i], fsc.args, retval, trussinfo); fsc.s_args[i] = temp; } } diff --git a/usr.bin/truss/amd64-linux32.c b/usr.bin/truss/amd64-linux32.c index 01703b5..9833829 100644 --- a/usr.bin/truss/amd64-linux32.c +++ b/usr.bin/truss/amd64-linux32.c @@ -200,7 +200,7 @@ i386_linux_syscall_entry(struct trussinfo *trussinfo, int nargs) { i < (fsc.nargs - 1) ? "," : ""); #endif if (sc && !(sc->args[i].type & OUT)) { - fsc.s_args[i] = print_arg(Procfd, &sc->args[i], fsc.args, 0); + fsc.s_args[i] = print_arg(Procfd, &sc->args[i], fsc.args, 0, trussinfo); } } #if DEBUG @@ -312,7 +312,7 @@ i386_linux_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused) if (errorp) asprintf(&temp, "0x%lx", fsc.args[sc->args[i].offset]); else - temp = print_arg(Procfd, &sc->args[i], fsc.args, retval); + temp = print_arg(Procfd, &sc->args[i], fsc.args, retval, trussinfo); fsc.s_args[i] = temp; } } diff --git a/usr.bin/truss/i386-fbsd.c b/usr.bin/truss/i386-fbsd.c index 45da1cd..d9ee202 100644 --- a/usr.bin/truss/i386-fbsd.c +++ b/usr.bin/truss/i386-fbsd.c @@ -217,7 +217,7 @@ i386_syscall_entry(struct trussinfo *trussinfo, int nargs) { i < (fsc.nargs - 1) ? "," : ""); #endif if (sc && !(sc->args[i].type & OUT)) { - fsc.s_args[i] = print_arg(Procfd, &sc->args[i], fsc.args, 0); + fsc.s_args[i] = print_arg(Procfd, &sc->args[i], fsc.args, 0, trussinfo); } } #if DEBUG @@ -322,7 +322,7 @@ i386_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused) if (errorp) asprintf(&temp, "0x%lx", fsc.args[sc->args[i].offset]); else - temp = print_arg(Procfd, &sc->args[i], fsc.args, retval); + temp = print_arg(Procfd, &sc->args[i], fsc.args, retval, trussinfo); fsc.s_args[i] = temp; } } diff --git a/usr.bin/truss/i386-linux.c b/usr.bin/truss/i386-linux.c index 01703b5..9833829 100644 --- a/usr.bin/truss/i386-linux.c +++ b/usr.bin/truss/i386-linux.c @@ -200,7 +200,7 @@ i386_linux_syscall_entry(struct trussinfo *trussinfo, int nargs) { i < (fsc.nargs - 1) ? "," : ""); #endif if (sc && !(sc->args[i].type & OUT)) { - fsc.s_args[i] = print_arg(Procfd, &sc->args[i], fsc.args, 0); + fsc.s_args[i] = print_arg(Procfd, &sc->args[i], fsc.args, 0, trussinfo); } } #if DEBUG @@ -312,7 +312,7 @@ i386_linux_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused) if (errorp) asprintf(&temp, "0x%lx", fsc.args[sc->args[i].offset]); else - temp = print_arg(Procfd, &sc->args[i], fsc.args, retval); + temp = print_arg(Procfd, &sc->args[i], fsc.args, retval, trussinfo); fsc.s_args[i] = temp; } } diff --git a/usr.bin/truss/ia64-fbsd.c b/usr.bin/truss/ia64-fbsd.c index 7ca6d7f..10fcd62 100644 --- a/usr.bin/truss/ia64-fbsd.c +++ b/usr.bin/truss/ia64-fbsd.c @@ -204,7 +204,7 @@ ia64_syscall_entry(struct trussinfo *trussinfo, int nargs) { i < (fsc.nargs - 1) ? "," : ""); #endif if (sc && !(sc->args[i].type & OUT)) { - fsc.s_args[i] = print_arg(Procfd, &sc->args[i], fsc.args, 0); + fsc.s_args[i] = print_arg(Procfd, &sc->args[i], fsc.args, 0, trussinfo); } } #if DEBUG @@ -308,7 +308,7 @@ ia64_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused) if (errorp) asprintf(&temp, "0x%lx", fsc.args[sc->args[i].offset]); else - temp = print_arg(Procfd, &sc->args[i], fsc.args, retval); + temp = print_arg(Procfd, &sc->args[i], fsc.args, retval, trussinfo); fsc.s_args[i] = temp; } } diff --git a/usr.bin/truss/main.c b/usr.bin/truss/main.c index 9d289a7..6866e71 100644 --- a/usr.bin/truss/main.c +++ b/usr.bin/truss/main.c @@ -70,8 +70,8 @@ static void usage(void) { fprintf(stderr, "%s\n%s\n", - "usage: truss [-faedDS] [-o file] -p pid", - " truss [-faedDS] [-o file] command [args]"); + "usage: truss [-faedDS] [-o file] [-s strsize] -p pid", + " truss [-faedDS] [-o file] [-s strsize] command [args]"); exit(1); } @@ -181,8 +181,9 @@ main(int ac, char **av) errx(1, "malloc() failed"); bzero(trussinfo, sizeof(struct trussinfo)); trussinfo->outfile = stderr; + trussinfo->strsize = 32; - while ((c = getopt(ac, av, "p:o:faedDS")) != -1) { + while ((c = getopt(ac, av, "p:o:faedDs:S")) != -1) { switch (c) { case 'p': /* specified pid */ trussinfo->pid = atoi(optarg); @@ -205,6 +206,9 @@ main(int ac, char **av) case 'o': /* Specified output file */ fname = optarg; break; + case 's': /* Specified string size */ + trussinfo->strsize = atoi(optarg); + break; case 'S': /* Don't trace signals */ trussinfo->flags |= NOSIGS; break; diff --git a/usr.bin/truss/sparc64-fbsd.c b/usr.bin/truss/sparc64-fbsd.c index 375e1fa..d30dc23 100644 --- a/usr.bin/truss/sparc64-fbsd.c +++ b/usr.bin/truss/sparc64-fbsd.c @@ -240,7 +240,7 @@ sparc64_syscall_entry(struct trussinfo *trussinfo, int nargs) { i < (fsc.nargs - 1) ? "," : ""); #endif if (sc && !(sc->args[i].type & OUT)) { - fsc.s_args[i] = print_arg(Procfd, &sc->args[i], fsc.args, 0); + fsc.s_args[i] = print_arg(Procfd, &sc->args[i], fsc.args, 0, trussinfo); } } #if DEBUG @@ -343,7 +343,7 @@ sparc64_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused) { if (errorp) asprintf(&temp, "0x%lx", fsc.args[sc->args[i].offset]); else - temp = print_arg(Procfd, &sc->args[i], fsc.args, retval); + temp = print_arg(Procfd, &sc->args[i], fsc.args, retval, trussinfo); fsc.s_args[i] = temp; } } diff --git a/usr.bin/truss/syscall.h b/usr.bin/truss/syscall.h index 838dfe2..2783486 100644 --- a/usr.bin/truss/syscall.h +++ b/usr.bin/truss/syscall.h @@ -30,7 +30,7 @@ * $FreeBSD$ */ -enum Argtype { None = 1, Hex, Octal, Int, String, Ptr, Stat, Ioctl, Quad, +enum Argtype { None = 1, Hex, Octal, Int, Name, String, Ptr, Stat, Ioctl, Quad, Signal, Sockaddr, StringArray, Timespec, Timeval, Itimerval, Pollfd, Fd_set, Sigaction, Fcntl, Mprot, Mmapflags, Whence, Readlinkres }; @@ -53,7 +53,7 @@ struct syscall { struct syscall *get_syscall(const char*); char *get_string(int, void*, int); -char *print_arg(int, struct syscall_args *, unsigned long*, long); +char *print_arg(int, struct syscall_args *, unsigned long*, long, struct trussinfo *); void print_syscall(struct trussinfo *, const char *, int, char **); void print_syscall_ret(struct trussinfo *, const char *, int, char **, int, long); diff --git a/usr.bin/truss/syscalls.c b/usr.bin/truss/syscalls.c index 52d7885..b94df2d 100644 --- a/usr.bin/truss/syscalls.c +++ b/usr.bin/truss/syscalls.c @@ -71,7 +71,7 @@ struct syscall syscalls[] = { { "fcntl", 1, 3, { { Int, 0 } , { Fcntl, 1 }, { Hex, 2 }}}, { "readlink", 1, 3, - { { String, 0 } , { Readlinkres | OUT, 1 }, { Int, 2 }}}, + { { Name, 0 } , { Readlinkres | OUT, 1 }, { Int, 2 }}}, { "lseek", 2, 3, #ifdef __LP64__ { { Int, 0 }, {Quad, 2 }, { Whence, 3 }}}, @@ -89,48 +89,48 @@ struct syscall syscalls[] = { { "mprotect", 1, 3, { { Ptr, 0 }, {Int, 1}, {Mprot, 2}}}, { "open", 1, 3, - { { String | IN, 0} , { Hex, 1}, {Octal, 2}}}, + { { Name | IN, 0} , { Hex, 1}, {Octal, 2}}}, { "mkdir", 1, 2, - { { String, 0} , {Octal, 1}}}, + { { Name, 0} , {Octal, 1}}}, { "linux_open", 1, 3, - { { String, 0 }, { Hex, 1}, { Octal, 2 }}}, + { { Name, 0 }, { Hex, 1}, { Octal, 2 }}}, { "close", 1, 1, { { Int, 0 } } }, { "link", 0, 2, - { { String, 0 }, { String, 1 }}}, + { { Name, 0 }, { Name, 1 }}}, { "unlink", 0, 1, - { { String, 0 }}}, + { { Name, 0 }}}, { "chdir", 0, 1, - { { String, 0 }}}, + { { Name, 0 }}}, { "chroot", 0, 1, - { { String, 0 }}}, + { { Name, 0 }}}, { "mknod", 0, 3, - { { String, 0 }, { Octal, 1 }, { Int, 3 }}}, + { { Name, 0 }, { Octal, 1 }, { Int, 3 }}}, { "chmod", 0, 2, - { { String, 0 }, { Octal, 1 }}}, + { { Name, 0 }, { Octal, 1 }}}, { "chown", 0, 3, - { { String, 0 }, { Int, 1 }, { Int, 2 }}}, + { { Name, 0 }, { Int, 1 }, { Int, 2 }}}, { "mount", 0, 4, - { { String, 0 }, { String, 1 }, { Int, 2 }, { Ptr, 3 }}}, + { { Name, 0 }, { Name, 1 }, { Int, 2 }, { Ptr, 3 }}}, { "umount", 0, 2, - { { String, 0 }, { Int, 2 }}}, + { { Name, 0 }, { Int, 2 }}}, { "fstat", 1, 2, { { Int, 0}, {Ptr | OUT , 1 }}}, { "stat", 1, 2, - { { String | IN, 0 }, { Ptr | OUT, 1 }}}, + { { Name | IN, 0 }, { Ptr | OUT, 1 }}}, { "lstat", 1, 2, - { { String | IN, 0 }, { Ptr | OUT, 1 }}}, + { { Name | IN, 0 }, { Ptr | OUT, 1 }}}, { "linux_newstat", 1, 2, - { { String | IN, 0 }, { Ptr | OUT, 1 }}}, + { { Name | IN, 0 }, { Ptr | OUT, 1 }}}, { "linux_newfstat", 1, 2, { { Int, 0 }, { Ptr | OUT, 1 }}}, { "write", 1, 3, - { { Int, 0 }, { Ptr | IN, 1 }, { Int, 2 }}}, + { { Int, 0 }, { String | IN, 1 }, { Int, 2 }}}, { "ioctl", 1, 3, { { Int, 0 }, { Ioctl, 1 }, { Hex, 2 }}}, { "break", 1, 1, { { Hex, 0 }}}, { "exit", 0, 1, { { Hex, 0 }}}, - { "access", 1, 2, { { String | IN, 0 }, { Int, 1 }}}, + { "access", 1, 2, { { Name | IN, 0 }, { Int, 1 }}}, { "sigaction", 1, 3, { { Signal, 0 }, { Sigaction | IN, 1 }, { Sigaction | OUT, 2 }}}, { "accept", 1, 3, @@ -148,12 +148,12 @@ struct syscall syscalls[] = { { "sendto", 1, 6, { { Hex, 0 }, { Ptr | IN, 1 }, { Int, 3 }, { Hex, 3 }, { Sockaddr | IN, 4 }, { Ptr | IN, 5 } } }, { "execve", 1, 3, - { { String | IN, 0 }, { StringArray | IN, 1 }, { StringArray | IN, 2 } } }, + { { Name | IN, 0 }, { StringArray | IN, 1 }, { StringArray | IN, 2 } } }, { "linux_execve", 1, 3, - { { String | IN, 0 }, { StringArray | IN, 1 }, { StringArray | IN, 2 } } }, - { "kldload", 0, 1, { { String | IN, 0 }}}, + { { Name | IN, 0 }, { StringArray | IN, 1 }, { StringArray | IN, 2 } } }, + { "kldload", 0, 1, { { Name | IN, 0 }}}, { "kldunload", 0, 1, { { Int, 0 }}}, - { "kldfind", 0, 1, { { String | IN, 0 }}}, + { "kldfind", 0, 1, { { Name | IN, 0 }}}, { "kldnext", 0, 1, { { Int, 0 }}}, { "kldstat", 0, 2, { { Int, 0 }, { Ptr, 1 }}}, { "kldfirstmod", 0, 1, { { Int, 0 }}}, @@ -166,15 +166,23 @@ struct syscall syscalls[] = { { "getitimer", 1, 2, { { Int, 0 }, { Itimerval | OUT, 2 }}}, { "setitimer", 1, 3, { { Int, 0 }, { Itimerval, 1} , { Itimerval | OUT, 2 }}}, { "utimes", 1, 2, - { { String | IN, 0 }, { Timeval | IN, 1 }}}, + { { Name | IN, 0 }, { Timeval | IN, 1 }}}, { "lutimes", 1, 2, - { { String | IN, 0 }, { Timeval | IN, 1 }}}, + { { Name | IN, 0 }, { Timeval | IN, 1 }}}, { "futimes", 1, 2, { { Int, 0 }, { Timeval | IN, 1 }}}, { "chflags", 1, 2, - { { String | IN, 0 }, { Hex, 1 }}}, + { { Name | IN, 0 }, { Hex, 1 }}}, { "lchflags", 1, 2, - { { String | IN, 0 }, { Hex, 1 }}}, + { { Name | IN, 0 }, { Hex, 1 }}}, + { "munmap", 1, 2, + { { Ptr, 0 }, { Int, 1 }}}, + { "read", 1, 3, + { { Int, 0}, { String | OUT, 1}, { Int, 2}}}, + { "rename", 1, 2, + { { Name , 0} , { Name, 1}}}, + { "symlink", 1, 2, + { { Name , 0} , { Name, 1}}}, { 0, 0, 0, { { 0, 0 }}}, }; @@ -228,16 +236,14 @@ get_string(int procfd, void *offset, int max) { err(1, "dup"); if ((p = fdopen(fd, "r")) == NULL) err(1, "fdopen"); - buf = malloc( size = (max ? max : 64 ) ); + buf = malloc( size = (max ? max + 1 : 64 ) ); len = 0; buf[0] = 0; if (fseeko(p, (uintptr_t)offset, SEEK_SET) == 0) { while ((c = fgetc(p)) != EOF) { buf[len++] = c; - if (c == 0 || len == max) { - buf[len] = 0; + if (c == 0 || len == max) break; - } if (len == size) { char *tmp; tmp = realloc(buf, size+64); @@ -249,6 +255,7 @@ get_string(int procfd, void *offset, int max) { buf = tmp; } } + buf[len] = 0; } fclose(p); return (buf); @@ -279,8 +286,10 @@ remove_trailing_or(char *str) */ char * -print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval) { +print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, struct trussinfo *trussinfo) { char *tmp = NULL; + int max = 0; + switch (sc->type & ARG_MASK) { case Hex: asprintf(&tmp, "0x%lx", args[sc->offset]); @@ -292,10 +301,20 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval) { asprintf(&tmp, "%ld", args[sc->offset]); break; case String: + max = trussinfo->strsize; + if (max == 0) + { + asprintf(&tmp, "0x%lx", args[sc->offset]); + break; + } + case Name: { char *tmp2; - tmp2 = get_string(fd, (void*)args[sc->offset], 0); - asprintf(&tmp, "\"%s\"", tmp2); + tmp2 = get_string(fd, (void*)args[sc->offset], max ? max + 1 : 0); + if (max && memchr(tmp2, '\0', max + 1) == NULL) + asprintf(&tmp, "\"%.*s...\"", max, tmp2); + else + asprintf(&tmp, "\"%s\"", tmp2); free(tmp2); } break; @@ -729,6 +748,7 @@ 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 { diff --git a/usr.bin/truss/truss.1 b/usr.bin/truss/truss.1 index 6b975ba..3efa65f 100644 --- a/usr.bin/truss/truss.1 +++ b/usr.bin/truss/truss.1 @@ -10,10 +10,12 @@ .Nm .Op Fl faedDS .Op Fl o Ar file +.Op Fl s Ar strsize .Fl p Ar pid .Nm .Op Fl faedDS .Op Fl o Ar file +.Op Fl s Ar strsize command .Op args .Sh DESCRIPTION @@ -54,6 +56,16 @@ displays signal as well as system call events.) Print the output to the specified .Ar file instead of standard error. +.It Fl s Ar strsize +Display strings using at most +.Ar strsize +characters. +If the buffer is larger, +.Qq ... +will be displayed at the end of the string. +The default +.Ar strsize +is 32. .It Fl p Ar pid Follow the process specified by .Ar pid diff --git a/usr.bin/truss/truss.h b/usr.bin/truss/truss.h index 00df4d6..24558ba 100644 --- a/usr.bin/truss/truss.h +++ b/usr.bin/truss/truss.h @@ -37,6 +37,7 @@ struct trussinfo int pid; int flags; int in_fork; + int strsize; FILE *outfile; struct timespec start_time; -- cgit v1.1