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
This commit is contained in:
Brian Somers 2006-01-02 08:36:25 +00:00
parent 91dda5000a
commit 0cf21b4f58
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=153963
13 changed files with 91 additions and 54 deletions

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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 {

View File

@ -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

View File

@ -37,6 +37,7 @@ struct trussinfo
int pid;
int flags;
int in_fork;
int strsize;
FILE *outfile;
struct timespec start_time;