diff --git a/usr.bin/truss/main.c b/usr.bin/truss/main.c index d1a236a7992a..0a31993fa1e6 100644 --- a/usr.bin/truss/main.c +++ b/usr.bin/truss/main.c @@ -67,8 +67,8 @@ static __inline void usage(void) { fprintf(stderr, "%s\n%s\n", - "usage: truss [-fS] [-o file] -p pid", - " truss [-fS] [-o file] command [args]"); + "usage: truss [-fdDS] [-o file] -p pid", + " truss [-fdDS] [-o file] command [args]"); exit(1); } @@ -145,7 +145,7 @@ main(int ac, char **av) { bzero(trussinfo, sizeof(struct trussinfo)); trussinfo->outfile = stderr; - while ((c = getopt(ac, av, "p:o:fS")) != -1) { + while ((c = getopt(ac, av, "p:o:fdDS")) != -1) { switch (c) { case 'p': /* specified pid */ trussinfo->pid = atoi(optarg); @@ -153,6 +153,12 @@ main(int ac, char **av) { case 'f': /* Follow fork()'s */ trussinfo->flags |= FOLLOWFORKS; break; + case 'd': /* Absolute timestamps */ + trussinfo->flags |= ABSOLUTETIMESTAMPS; + break; + case 'D': /* Relative timestamps */ + trussinfo->flags |= RELATIVETIMESTAMPS; + break; case 'o': /* Specified output file */ fname = optarg; break; @@ -215,6 +221,8 @@ START_TRACE: * All of the grunt work is done in the support routines. */ + gettimeofday(&trussinfo->start_time, (struct timezone *)NULL); + do { int val = 0; @@ -224,8 +232,10 @@ START_TRACE: switch(i = pfs.why) { case S_SCE: funcs->enter_syscall(trussinfo, pfs.val); + gettimeofday(&trussinfo->before, (struct timezone *)NULL); break; case S_SCX: + gettimeofday(&trussinfo->after, (struct timezone *)NULL); /* * This is so we don't get two messages for an exec -- one * for the S_EXEC, and one for the syscall exit. It also, diff --git a/usr.bin/truss/syscalls.c b/usr.bin/truss/syscalls.c index 8056aa122270..1ad7fe1b14f7 100644 --- a/usr.bin/truss/syscalls.c +++ b/usr.bin/truss/syscalls.c @@ -40,6 +40,7 @@ static const char rcsid[] = */ #include +#include #include #include #include @@ -358,9 +359,27 @@ print_syscall(struct trussinfo *trussinfo, const char *name, int nargs, char **s int i; int len = 0; + struct timeval timediff; + if (trussinfo->flags & FOLLOWFORKS) len += fprintf(trussinfo->outfile, "%5d: ", trussinfo->pid); + if (!strcmp(name, "execve") || !strcmp(name, "exit")) { + gettimeofday(&trussinfo->after, (struct timezone *)NULL); + } + + if (trussinfo->flags & ABSOLUTETIMESTAMPS) { + timersub(&trussinfo->after, &trussinfo->start_time, &timediff); + len += fprintf(trussinfo->outfile, "%d.%0.7d ", + timediff.tv_sec, timediff.tv_usec); + } + + if (trussinfo->flags & RELATIVETIMESTAMPS) { + timersub(&trussinfo->after, &trussinfo->before, &timediff); + len += fprintf(trussinfo->outfile, "%d.%0.7d ", + timediff.tv_sec, timediff.tv_usec); + } + len += fprintf(trussinfo->outfile, "%s(", name); for (i = 0; i < nargs; i++) { diff --git a/usr.bin/truss/truss.1 b/usr.bin/truss/truss.1 index 58f9ac53d820..d4cbb6acfd30 100644 --- a/usr.bin/truss/truss.1 +++ b/usr.bin/truss/truss.1 @@ -8,11 +8,11 @@ .Nd trace system calls .Sh SYNOPSIS .Nm -.Op Fl fS +.Op Fl fdDS .Op Fl o Ar file .Fl p Ar pid .Nm -.Op Fl fS +.Op Fl fdDS .Op Fl o Ar file command .Op args @@ -29,6 +29,12 @@ The options are as follows: .It Fl f Trace decendants of the original traced process created by fork(), vfork, etc. +.It Fl d +Include timestamps in the output showing the time elapsed +since the trace was started. +.It Fl D +Include timestamps in the output showing the time elapsed +since the last recorded event. .It Fl S Do not display information about signals received by the process. (Normally, diff --git a/usr.bin/truss/truss.h b/usr.bin/truss/truss.h index f77202aec264..2bb5c8566e09 100644 --- a/usr.bin/truss/truss.h +++ b/usr.bin/truss/truss.h @@ -26,6 +26,8 @@ */ #define FOLLOWFORKS 0x00000001 +#define RELATIVETIMESTAMPS 0x00000002 +#define ABSOLUTETIMESTAMPS 0x00000004 #define NOSIGS 0x00000008 struct trussinfo @@ -34,4 +36,8 @@ struct trussinfo int flags; int in_fork; FILE *outfile; + + struct timeval start_time; + struct timeval before; + struct timeval after; };