Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 18 Oct 2001 02:50:01 -0700 (PDT)
From:      Thomas Quinot <quinot@inf.enst.fr>
To:        freebsd-bugs@FreeBSD.org
Subject:   bin/25587: truss -f patch updated for -CURRENT 20011017
Message-ID:  <200110180950.f9I9o1n39783@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR bin/25587; it has been noted by GNATS.

From: Thomas Quinot <quinot@inf.enst.fr>
To: freebsd-gnats-submit@freebsd.org
Cc: winter@jurai.net
Subject: bin/25587: truss -f patch updated for -CURRENT 20011017
Date: Thu, 18 Oct 2001 11:48:59 +0200

 Hi,
 
 Having sent a PR suggesting the same functionality enhancement (31285)
 I was pointed to this one, which already had a patch available.
 I updated the patch for -CURRENT as of yesterday.
 
 Matthew, could you have a look at the updated diff?
 
 Thanks,
 Thomas.
 
 --- sys/kern/kern_fork.c.orig	Wed Oct 10 14:58:20 2001
 +++ sys/kern/kern_fork.c	Wed Oct 17 18:40:14 2001
 @@ -51,6 +51,7 @@
  #include <sys/malloc.h>
  #include <sys/mutex.h>
  #include <sys/proc.h>
 +#include <sys/pioctl.h>
  #include <sys/resourcevar.h>
  #include <sys/syscall.h>
  #include <sys/vnode.h>
 @@ -682,6 +683,16 @@
  	while (p2->p_flag & P_PPWAIT)
  		msleep(p1, &p2->p_mtx, PWAIT, "ppwait", 0);
  	PROC_UNLOCK(p2);
 +
 +	/*
 +	 * If PF_FORK is set, the child process inherits the
 +	 * procfs ioctl flags from its parent.
 +	 */
 +	if (p1->p_pfsflags & PF_FORK)
 +	{
 +		p2->p_stops = p1->p_stops;
 +		p2->p_pfsflags = p1->p_pfsflags;
 +	}
  
  	/*
  	 * Return child proc pointer to parent.
 --- sys/sys/pioctl.h.orig	Sat Aug 28 02:51:55 1999
 +++ sys/sys/pioctl.h	Wed Oct 17 18:40:22 2001
 @@ -74,4 +74,5 @@
  
  # define PF_LINGER	0x01	/* Keep stops around after last close */
  # define PF_ISUGID	0x02	/* Ignore UID/GID changes */
 +# define PF_FORK	0x04	/* Retain settings on fork() */
  #endif 
 --- usr.bin/truss/truss.h.orig	Wed Oct 17 18:51:31 2001
 +++ usr.bin/truss/truss.h	Wed Oct 17 18:47:46 2001
 @@ -0,0 +1,41 @@
 +/*
 + * Copryight 2001 Jamey Wood
 + *
 + * Redistribution and use in source and binary forms, with or without
 + * modification, are permitted provided that the following conditions
 + * are met:
 + * 1. Redistributions of source code must retain the above copyright
 + *    notice, this list of conditions and the following disclaimer.
 + * 2. Redistributions in binary form must reproduce the above copyright
 + *    notice, this list of conditions and the following disclaimer in the
 + *    documentation and/or other materials provided with the distribution.
 + *
 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 + * SUCH DAMAGE.
 + */
 +
 +#define FOLLOWFORKS        0x00000001
 +#define RELATIVETIMESTAMPS 0x00000002
 +#define ABSOLUTETIMESTAMPS 0x00000004
 +#define NOSIGS             0x00000008
 +
 +struct trussinfo
 +{
 +	int pid;
 +	int flags;
 +	int in_fork;
 +	FILE *outfile;
 +
 +	struct timeval start_time;
 +	struct timeval before;
 +	struct timeval after;
 +};
 --- usr.bin/truss/alpha-fbsd.c.orig	Sat Mar 18 09:49:40 2000
 +++ usr.bin/truss/alpha-fbsd.c	Wed Oct 17 18:40:46 2001
 @@ -58,13 +58,13 @@
  #include <machine/psl.h>
  #include <sys/syscall.h>
  
 +#include "truss.h"
  #include "syscall.h"
  
  static int fd = -1;
  static int cpid = -1;
  extern int Procfd;
  
 -extern FILE *outfile;
  #include "syscalls.h"
  
  static int nsyscalls = sizeof(syscallnames) / sizeof(syscallnames[0]);
 @@ -111,7 +111,7 @@
   */
  
  void
 -alpha_syscall_entry(int pid, int nargs) {
 +alpha_syscall_entry(struct trussinfo *trussinfo, int nargs) {
    char buf[32];
    struct reg regs = { { 0 } };
    int syscall;
 @@ -120,14 +120,14 @@
    struct syscall *sc;
    int indir = 0;	/* indirect system call */
  
 -  if (fd == -1 || pid != cpid) {
 -    sprintf(buf, "/proc/%d/regs", pid);
 +  if (fd == -1 || trussinfo->pid != cpid) {
 +    sprintf(buf, "/proc/%d/regs", trussinfo->pid);
      fd = open(buf, O_RDWR);
      if (fd == -1) {
 -      fprintf(outfile, "-- CANNOT READ REGISTERS --\n");
 +      fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
        return;
      }
 -    cpid = pid;
 +    cpid = trussinfo->pid;
    }
  
    clear_fsc();
 @@ -150,7 +150,15 @@
    fsc.name =
      (syscall < 0 || syscall > nsyscalls) ? NULL : syscallnames[syscall];
    if (!fsc.name) {
 -    fprintf(outfile, "-- UNKNOWN SYSCALL %d --\n", syscall);
 +    fprintf(trussinfo->outfile, "-- UNKNOWN SYSCALL %d --\n", syscall);
 +  }
 +
 +  if (fsc.name
 +   && ((!strcmp(fsc.name, "fork")
 +    || !strcmp(fsc.name, "rfork")
 +    || !strcmp(fsc.name, "vfork"))))
 +  {
 +    trussinfo->in_fork = 1;
    }
  
    if (nargs == 0)
 @@ -192,7 +200,7 @@
      fsc.nargs = sc->nargs;
    } else {
  #if DEBUG
 -    fprintf(outfile, "unknown syscall %s -- setting args to %d\n",
 +    fprintf(trussinfo->outfile, "unknown syscall %s -- setting args to %d\n",
  	   fsc.name, nargs);
  #endif
      fsc.nargs = nargs;
 @@ -233,7 +241,7 @@
    }
  
  #if DEBUG
 -  fprintf(outfile, "\n");
 +  fprintf(trussinfo->outfile, "\n");
  #endif
  
    /*
 @@ -244,7 +252,7 @@
     */
  
    if (!strcmp(fsc.name, "execve") || !strcmp(fsc.name, "exit")) {
 -    print_syscall(outfile, fsc.name, fsc.nargs, fsc.s_args);
 +    print_syscall(trussinfo, fsc.name, fsc.nargs, fsc.s_args);
    }
  
    return;
 @@ -257,8 +265,8 @@
   * the sytem call number instead of, say, an error status).
   */
  
 -void
 -alpha_syscall_exit(int pid, int syscall) {
 +int
 +alpha_syscall_exit(struct trussinfo *trussinfo, int syscall) {
    char buf[32];
    struct reg regs;
    int retval;
 @@ -266,14 +274,14 @@
    int errorp;
    struct syscall *sc;
  
 -  if (fd == -1 || pid != cpid) {
 -    sprintf(buf, "/proc/%d/regs", pid);
 +  if (fd == -1 || trussinfo->pid != cpid) {
 +    sprintf(buf, "/proc/%d/regs", trussinfo->pid);
      fd = open(buf, O_RDONLY);
      if (fd == -1) {
 -      fprintf(outfile, "-- CANNOT READ REGISTERS --\n");
 +      fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
        return;
      }
 -    cpid = pid;
 +    cpid = trussinfo->pid;
    }
  
    lseek(fd, 0L, 0);
 @@ -321,8 +329,8 @@
     * but that complicates things considerably.
     */
  
 -  print_syscall_ret(outfile, fsc.name, fsc.nargs, fsc.s_args, errorp, retval);
 +  print_syscall_ret(trussinfo, fsc.name, fsc.nargs, fsc.s_args, errorp, retval);
    clear_fsc();
  
 -  return;
 +  return retval;
  }
 --- usr.bin/truss/i386-fbsd.c.orig	Sat Mar 18 09:49:40 2000
 +++ usr.bin/truss/i386-fbsd.c	Wed Oct 17 18:40:46 2001
 @@ -55,13 +55,13 @@
  #include <machine/psl.h>
  #include <sys/syscall.h>
  
 +#include "truss.h"
  #include "syscall.h"
  
  static int fd = -1;
  static int cpid = -1;
  extern int Procfd;
  
 -extern FILE *outfile;
  #include "syscalls.h"
  
  static int nsyscalls = sizeof(syscallnames) / sizeof(syscallnames[0]);
 @@ -108,7 +108,7 @@
   */
  
  void
 -i386_syscall_entry(int pid, int nargs) {
 +i386_syscall_entry(struct trussinfo *trussinfo, int nargs) {
    char buf[32];
    struct reg regs = { 0 };
    int syscall;
 @@ -116,14 +116,14 @@
    unsigned int parm_offset;
    struct syscall *sc;
  
 -  if (fd == -1 || pid != cpid) {
 -    sprintf(buf, "/proc/%d/regs", pid);
 +  if (fd == -1 || trussinfo->pid != cpid) {
 +    sprintf(buf, "/proc/%d/regs", trussinfo->pid);
      fd = open(buf, O_RDWR);
      if (fd == -1) {
 -      fprintf(outfile, "-- CANNOT READ REGISTERS --\n");
 +      fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
        return;
      }
 -    cpid = pid;
 +    cpid = trussinfo->pid;
    }
  
    clear_fsc();
 @@ -154,7 +154,16 @@
    fsc.name =
      (syscall < 0 || syscall > nsyscalls) ? NULL : syscallnames[syscall];
    if (!fsc.name) {
 -    fprintf(outfile, "-- UNKNOWN SYSCALL %d --\n", syscall);
 +    fprintf(trussinfo->outfile, "-- UNKNOWN SYSCALL %d --\n", syscall);
 +  }
 +
 +  if (fsc.name && (trussinfo->flags & FOLLOWFORKS)
 +   && ((!strcmp(fsc.name, "fork")
 +    || !strcmp(fsc.name, "rfork")
 +    || !strcmp(fsc.name, "vfork"))))
 +  {
 +    fprintf(stderr, "setting trussinfo->in_fork = 1\n");
 +    trussinfo->in_fork = 1;
    }
  
    if (nargs == 0)
 @@ -170,7 +179,7 @@
      fsc.nargs = sc->nargs;
    } else {
  #if DEBUG
 -    fprintf(outfile, "unknown syscall %s -- setting args to %d\n",
 +    fprintf(trussinfo->outfile, "unknown syscall %s -- setting args to %d\n",
  	   fsc.name, nargs);
  #endif
      fsc.nargs = nargs;
 @@ -211,7 +220,7 @@
    }
  
  #if DEBUG
 -  fprintf(outfile, "\n");
 +  fprintf(trussinfo->outfile, "\n");
  #endif
  
    /*
 @@ -222,7 +231,7 @@
     */
  
    if (!strcmp(fsc.name, "execve") || !strcmp(fsc.name, "exit")) {
 -    print_syscall(outfile, fsc.name, fsc.nargs, fsc.s_args);
 +    print_syscall(trussinfo, fsc.name, fsc.nargs, fsc.s_args);
    }
  
    return;
 @@ -235,8 +244,8 @@
   * the sytem call number instead of, say, an error status).
   */
  
 -void
 -i386_syscall_exit(int pid, int syscall) {
 +int
 +i386_syscall_exit(struct trussinfo *trussinfo, int syscall) {
    char buf[32];
    struct reg regs;
    int retval;
 @@ -244,14 +253,14 @@
    int errorp;
    struct syscall *sc;
  
 -  if (fd == -1 || pid != cpid) {
 -    sprintf(buf, "/proc/%d/regs", pid);
 +  if (fd == -1 || trussinfo->pid != cpid) {
 +    sprintf(buf, "/proc/%d/regs", trussinfo->pid);
      fd = open(buf, O_RDONLY);
      if (fd == -1) {
 -      fprintf(outfile, "-- CANNOT READ REGISTERS --\n");
 +      fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
        return;
      }
 -    cpid = pid;
 +    cpid = trussinfo->pid;
    }
  
    lseek(fd, 0L, 0);
 @@ -299,8 +308,8 @@
     * but that complicates things considerably.
     */
  
 -  print_syscall_ret(outfile, fsc.name, fsc.nargs, fsc.s_args, errorp, retval);
 +  print_syscall_ret(trussinfo, fsc.name, fsc.nargs, fsc.s_args, errorp, retval);
    clear_fsc();
  
 -  return;
 +  return retval;
  }
 --- usr.bin/truss/i386-linux.c.orig	Sat Mar 18 09:49:40 2000
 +++ usr.bin/truss/i386-linux.c	Wed Oct 17 18:40:46 2001
 @@ -52,13 +52,13 @@
  #include <machine/reg.h>
  #include <machine/psl.h>
  
 +#include "truss.h"
  #include "syscall.h"
  
  static int fd = -1;
  static int cpid = -1;
  extern int Procfd;
  
 -extern FILE *outfile;
  #include "linux_syscalls.h"
  
  static int nsyscalls =
 @@ -87,21 +87,21 @@
  }
  
  void
 -i386_linux_syscall_entry(int pid, int nargs) {
 +i386_linux_syscall_entry(struct trussinfo *trussinfo, int nargs) {
    char buf[32];
    struct reg regs = { 0 };
    int syscall;
    int i;
    struct syscall *sc;
  
 -  if (fd == -1 || pid != cpid) {
 -    sprintf(buf, "/proc/%d/regs", pid);
 +  if (fd == -1 || trussinfo->pid != cpid) {
 +    sprintf(buf, "/proc/%d/regs", trussinfo->pid);
      fd = open(buf, O_RDWR);
      if (fd == -1) {
 -      fprintf(outfile, "-- CANNOT READ REGISTERS --\n");
 +      fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
        return;
      }
 -    cpid = pid;
 +    cpid = trussinfo->pid;
    }
  
    clear_lsc();
 @@ -113,7 +113,14 @@
    lsc.name =
      (syscall < 0 || syscall > nsyscalls) ? NULL : linux_syscallnames[syscall];
    if (!lsc.name) {
 -    fprintf (outfile, "-- UNKNOWN SYSCALL %d\n", syscall);
 +    fprintf(trussinfo->outfile, "-- UNKNOWN SYSCALL %d\n", syscall);
 +  }
 +
 +  if (lsc.name
 +   && ((!strcmp(lsc.name, "linux_fork")
 +    || !strcmp(lsc.name, "linux_vfork"))))
 +  {
 +    trussinfo->in_fork = 1;
    }
  
    if (nargs == 0)
 @@ -138,7 +145,7 @@
      lsc.nargs = sc->nargs;
    } else {
  #ifdef DEBUG
 -    fprintf(outfile, "unknown syscall %s -- setting args to %d\n",
 +    fprintf(trussinfo->outfile, "unknown syscall %s -- setting args to %d\n",
  	    lsc.name, nargs);
  #endif
      lsc.nargs = nargs;
 @@ -171,7 +178,7 @@
    }
  
    if (!strcmp(lsc.name, "linux_execve") || !strcmp(lsc.name, "exit")) {
 -    print_syscall(outfile, lsc.name, lsc.nargs, lsc.s_args);
 +    print_syscall(trussinfo, lsc.name, lsc.nargs, lsc.s_args);
    }
  
    return;
 @@ -192,8 +199,8 @@
    	-6, 
  };
  
 -void
 -i386_linux_syscall_exit(int pid, int syscall) {
 +int
 +i386_linux_syscall_exit(struct trussinfo *trussinfo, int syscall) {
    char buf[32];
    struct reg regs;
    int retval;
 @@ -201,14 +208,14 @@
    int errorp;
    struct syscall *sc;
  
 -  if (fd == -1 || pid != cpid) {
 -    sprintf(buf, "/proc/%d/regs", pid);
 +  if (fd == -1 || trussinfo->pid != cpid) {
 +    sprintf(buf, "/proc/%d/regs", trussinfo->pid);
      fd = open(buf, O_RDONLY);
      if (fd == -1) {
 -      fprintf(outfile, "-- CANNOT READ REGISTERS --\n");
 +      fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
        return;
      }
 -    cpid = pid;
 +    cpid = trussinfo->pid;
    }
  
    lseek(fd, 0L, 0);
 @@ -243,7 +250,7 @@
        if (retval == bsd_to_linux_errno[i])
        break;
    }
 -  print_syscall_ret(outfile, lsc.name, lsc.nargs, lsc.s_args, errorp, i);
 +  print_syscall_ret(trussinfo, lsc.name, lsc.nargs, lsc.s_args, errorp, i);
    clear_lsc();
 -  return;
 +  return retval;
  }
 --- usr.bin/truss/setup.c.orig	Mon Jan 10 05:09:05 2000
 +++ usr.bin/truss/setup.c	Wed Oct 17 18:40:46 2001
 @@ -126,7 +126,7 @@
   */
  
  int
 -start_tracing(int pid, int flags) {
 +start_tracing(int pid, int eventflags, int flags) {
    int fd;
    char buf[32];
    struct procfs_status tmp;
 @@ -149,7 +149,7 @@
    }
    evflags = tmp.events;
  
 -  if (ioctl(fd, PIOCBIS, flags) == -1)
 +  if (ioctl(fd, PIOCBIS, eventflags) == -1)
      err(9, "cannot set procfs event bit mask");
  
    /*
 @@ -158,7 +158,7 @@
     * needs to be woken up via procctl.
     */
  
 -  if (ioctl(fd, PIOCSFL, 0) == -1)
 +  if (ioctl(fd, PIOCSFL, flags) == -1)
      warn("cannot clear PF_LINGER");
  
    return fd;
 --- usr.bin/truss/syscall.h.orig	Sat Mar 18 09:49:41 2000
 +++ usr.bin/truss/syscall.h	Wed Oct 17 18:40:46 2001
 @@ -44,5 +44,5 @@
  struct syscall *get_syscall(const char*);
  char *get_string(int, void*, int);
  char *print_arg(int, struct syscall_args *, unsigned long*);
 -void print_syscall(FILE *, const char *, int, char **);
 -void print_syscall_ret(FILE *, const char *, int, char **, int, int);
 +void print_syscall(struct trussinfo *, const char *, int, char **);
 +void print_syscall_ret(struct trussinfo *, const char *, int, char **, int, int);
 --- usr.bin/truss/syscalls.c.orig	Mon Sep  3 17:23:53 2001
 +++ usr.bin/truss/syscalls.c	Wed Oct 17 18:40:46 2001
 @@ -46,8 +46,15 @@
  #include <unistd.h>
  #include <sys/types.h>
  #include <signal.h>
 +#include <sys/time.h>
 +
 +#include "truss.h"
  #include "syscall.h"
  
 +extern int followforks;
 +extern int relativetimestamps;
 +extern int absolutetimestamps;
 +
  /*
   * This should probably be in its own file.
   */
 @@ -255,28 +262,60 @@
   */
  
  void
 -print_syscall(FILE *outfile, const char *name, int nargs, char **s_args) {
 +print_syscall(struct trussinfo *trussinfo, const char *name, int nargs, char **s_args) {
    int i;
    int len = 0;
 -  len += fprintf(outfile, "%s(", name);
 +
 +  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)
 +  {
 +    timediff.tv_sec = trussinfo->after.tv_sec - trussinfo->start_time.tv_sec;
 +    timediff.tv_usec = trussinfo->after.tv_usec - trussinfo->start_time.tv_usec;
 +    if (timediff.tv_usec < 0)
 +      timediff.tv_sec--, timediff.tv_usec += 10000000;
 +
 +    len += fprintf(trussinfo->outfile, "%d.%0.7d ", timediff.tv_sec, timediff.tv_usec);
 +  }
 +
 +  if (trussinfo->flags & RELATIVETIMESTAMPS)
 +  {
 +    timediff.tv_sec = trussinfo->after.tv_sec - trussinfo->before.tv_sec;
 +    timediff.tv_usec = trussinfo->after.tv_usec - trussinfo->before.tv_usec;
 +    if (timediff.tv_usec < 0)
 +      timediff.tv_sec--, timediff.tv_usec += 10000000;
 +
 +    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++) {
      if (s_args[i])
 -      len += fprintf(outfile, "%s", s_args[i]);
 +      len += fprintf(trussinfo->outfile, "%s", s_args[i]);
      else
 -      len += fprintf(outfile, "<missing argument>");
 -    len += fprintf(outfile, "%s", i < (nargs - 1) ? "," : "");
 +      len += fprintf(trussinfo->outfile, "<missing argument>");
 +    len += fprintf(trussinfo->outfile, "%s", i < (nargs - 1) ? "," : "");
    }
 -  len += fprintf(outfile, ")");
 +  len += fprintf(trussinfo->outfile, ")");
    for (i = 0; i < 6 - (len / 8); i++)
 -	fprintf(outfile, "\t");
 +	fprintf(trussinfo->outfile, "\t");
  }
  
  void
 -print_syscall_ret(FILE *outfile, const char *name, int nargs, char **s_args, int errorp, int retval) {
 -  print_syscall(outfile, name, nargs, s_args);
 +print_syscall_ret(struct trussinfo *trussinfo, const char *name, int nargs, char **s_args, int errorp, int retval) {
 +  print_syscall(trussinfo, name, nargs, s_args);
    if (errorp) {
 -    fprintf(outfile, " ERR#%d '%s'\n", retval, strerror(retval));
 +    fprintf(trussinfo->outfile, " ERR#%d '%s'\n", retval, strerror(retval));
    } else {
 -    fprintf(outfile, " = %d (0x%x)\n", retval, retval);
 +    fprintf(trussinfo->outfile, " = %d (0x%x)\n", retval, retval);
    }
  }
 --- usr.bin/truss/truss.1.orig	Mon Jul 16 10:44:19 2001
 +++ usr.bin/truss/truss.1	Wed Oct 17 18:40:46 2001
 @@ -8,11 +8,11 @@
  .Nd trace system calls
  .Sh SYNOPSIS
  .Nm
 -.Op Fl S
 +.Op Fl fdDS
  .Op Fl o Ar file
  .Fl p Ar pid
  .Nm
 -.Op Fl S
 +.Op Fl fdDS
  .Op Fl o Ar file
  command
  .Op args
 @@ -25,6 +25,15 @@
  .Pp
  The options are as follows:
  .Bl -tag -width indent
 +.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,
 --- usr.bin/truss/main.c.orig	Wed Oct 17 18:56:38 2001
 +++ usr.bin/truss/main.c	Wed Oct 17 18:47:22 2001
 @@ -11,7 +11,7 @@
   *    documentation and/or other materials provided with the distribution.
   * 3. All advertising materials mentioning features or use of this software
   *    must display the following acknowledgement:
 - *      This product includes software developed by Sean Eric Fagan
 + *	This product includes software developed by Sean Eric Fagan
   * 4. Neither the name of the author may be used to endorse or promote
   *    products derived from this software without specific prior written
   *    permission.
 @@ -50,37 +50,36 @@
  #include <unistd.h>
  #include <sys/ioctl.h>
  #include <sys/pioctl.h>
 +#include <sys/time.h>
 +
 +#include "truss.h"
  
  extern int setup_and_wait(char **);
 -extern int start_tracing(int, int);
 +extern int start_tracing(int, int, int);
  #ifdef __alpha__
 -extern void alpha_syscall_entry(int, int);
 -extern void alpha_syscall_exit(int, int);
 +extern void alpha_syscall_entry(struct trussinfo *, int);
 +extern void alpha_syscall_exit(struct trussinfo *, int);
  #endif
  #ifdef __i386__
 -extern void i386_syscall_entry(int, int);
 -extern void i386_syscall_exit(int, int);
 -extern void i386_linux_syscall_entry(int, int);
 -extern void i386_linux_syscall_exit(int, int);
 +extern void i386_syscall_entry(struct trussinfo *, int);
 +extern void i386_syscall_exit(struct trussinfo *, int);
 +extern void i386_linux_syscall_entry(struct trussinfo *, int);
 +extern void i386_linux_syscall_exit(struct trussinfo *, int);
  #endif
  
  /*
 - * These should really be parameterized -- I don't like having globals,
 - * but this is the easiest way, right now, to deal with them.
 + * It's difficult to parameterize this because it must be
 + * accessible in a signal handler.
   */
  
 -int pid = 0;
 -int nosigs = 0;
 -FILE *outfile;
  int Procfd;
 -char progtype[50];      /* OS and type of executable */
  
  static inline void
  usage(void)
  {
    fprintf(stderr, "%s\n%s\n",
 -        "usage: truss [-S] [-o file] -p pid",
 -        "       truss [-S] [-o file] command [args]");
 +	"usage: truss [-fdDS] [-o file] -p pid",
 +	"       truss [-fdDS] [-o file] command [args]");
    exit(1);
  }
  
 @@ -90,8 +89,8 @@
   */
  struct ex_types {
    char *type;
 -  void (*enter_syscall)(int, int);
 -  void (*exit_syscall)(int, int);
 +  void (*enter_syscall)(struct trussinfo *, int);
 +  int (*exit_syscall)(struct trussinfo *, int);
  } ex_types[] = {
  #ifdef __alpha__
    { "FreeBSD ELF", alpha_syscall_entry, alpha_syscall_exit },
 @@ -111,13 +110,13 @@
   */
  
  static struct ex_types *
 -set_etype() {
 +set_etype(struct trussinfo *trussinfo) {
    struct ex_types *funcs;
    char etype[24];
    char progtype[32];
    int fd;
  
 -  sprintf(etype, "/proc/%d/etype", pid);
 +  sprintf(etype, "/proc/%d/etype", trussinfo->pid);
    if ((fd = open(etype, O_RDONLY)) == -1) {
      strcpy(progtype, "FreeBSD a.out");
    } else {
 @@ -148,18 +147,34 @@
    int in_exec = 0;
    char *fname = NULL;
    int sigexit = 0;
 +  struct trussinfo *trussinfo;
 +
 +  /* Initialize the trussinfo struct */
 +  if ((trussinfo = (struct trussinfo *)malloc(sizeof(struct trussinfo)))
 +      == NULL)
 +    errx(1, "malloc() failed");
 +  bzero(trussinfo, sizeof(struct trussinfo));
 +  trussinfo->outfile = stderr;
  
 -  outfile = stdout;
 -  while ((c = getopt(ac, av, "p:o:S")) != -1) {
 +  while ((c = getopt(ac, av, "p:o:fdDS")) != -1) {
      switch (c) {
 -    case 'p':   /* specified pid */
 -      pid = atoi(optarg);
 +    case 'p':	/* specified pid */
 +      trussinfo->pid = atoi(optarg);
 +      break;
 +    case 'f': /* Follow fork()'s */
 +      trussinfo->flags |= FOLLOWFORKS;
 +      break;
 +    case 'd': /* Absolute timestamps */
 +      trussinfo->flags |= ABSOLUTETIMESTAMPS;
        break;
 -    case 'o':   /* Specified output file */
 +    case 'D': /* Relative timestamps */
 +      trussinfo->flags |= RELATIVETIMESTAMPS;
 +      break;
 +    case 'o':	/* Specified output file */
        fname = optarg;
        break;
 -    case 'S':   /* Don't trace signals */ 
 -      nosigs = 1;
 +    case 'S':	/* Don't trace signals */ 
 +      trussinfo->flags |= NOSIGS;
        break;
      default:
        usage();
 @@ -167,11 +183,11 @@
    }
  
    ac -= optind; av += optind;
 -  if ((pid == 0 && ac == 0) || (pid != 0 && ac != 0))
 +  if ((trussinfo->pid == 0 && ac == 0) || (trussinfo->pid != 0 && ac != 0))
      usage();
  
    if (fname != NULL) { /* Use output file */
 -    if ((outfile = fopen(fname, "w")) == NULL)
 +    if ((trussinfo->outfile = fopen(fname, "w")) == NULL)
        errx(1, "cannot open %s", fname);
    }
  
 @@ -182,9 +198,9 @@
     * then we restore the event mask on these same signals.
     */
  
 -  if (pid == 0) {       /* Start a command ourselves */
 +  if (trussinfo->pid == 0) {	/* Start a command ourselves */
      command = av;
 -    pid = setup_and_wait(command);
 +    trussinfo->pid = setup_and_wait(command);
      signal(SIGINT, SIG_IGN);
      signal(SIGTERM, SIG_IGN);
      signal(SIGQUIT, SIG_IGN);
 @@ -201,20 +217,25 @@
     * be woken up, either in exit() or in execve().
     */
  
 -  Procfd = start_tracing(pid, S_EXEC | S_SCE | S_SCX | S_CORE | S_EXIT |
 -                     (nosigs ? 0 : S_SIG));
 +START_TRACE:
 +  Procfd = start_tracing(
 +		trussinfo->pid, S_EXEC | S_SCE | S_SCX | S_CORE | S_EXIT |
 +		((trussinfo->flags & NOSIGS) ? 0 : S_SIG),
 +		((trussinfo->flags & FOLLOWFORKS) ? PF_FORK : 0));
    if (Procfd == -1)
      return 0;
  
    pfs.why = 0;
  
 -  funcs = set_etype();
 +  funcs = set_etype(trussinfo);
    /*
     * At this point, it's a simple loop, waiting for the process to
     * stop, finding out why, printing out why, and then continuing it.
     * All of the grunt work is done in the support routines.
     */
  
 +  gettimeofday(&trussinfo->start_time, (struct timezone *)NULL);
 +
    do {
      int val = 0;
  
 @@ -223,46 +244,68 @@
      else {
        switch(i = pfs.why) {
        case S_SCE:
 -        funcs->enter_syscall(pid, pfs.val);
 -        break;
 +	funcs->enter_syscall(trussinfo, pfs.val);
 +	gettimeofday(&trussinfo->before, (struct timezone *)NULL);
 +	break;
        case S_SCX:
 -        /*
 -         * 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,
 -         * conveniently, ensures that the first message printed out
 -         * isn't the return-from-syscall used to create the process.
 -         */
 -
 -        if (in_exec) {
 -          in_exec = 0;
 -          break;
 -        }
 -        funcs->exit_syscall(pid, pfs.val);
 -        break;
 +	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,
 +	 * conveniently, ensures that the first message printed out
 +	 * isn't the return-from-syscall used to create the process.
 +	 */
 +
 +	if (in_exec) {
 +	  in_exec = 0;
 +	  break;
 +	}
 +
 +	if (trussinfo->in_fork && (trussinfo->flags & FOLLOWFORKS))
 +	{
 +	  int childpid;
 +
 +          trussinfo->in_fork = 0;
 +	  childpid = funcs->exit_syscall(trussinfo, pfs.val);
 +
 +	  /*
 +	   * Fork a new copy of ourself to trace the child of the
 +	   * original traced process.
 +	   */
 +	  if (fork() == 0)
 +	  {
 +	    trussinfo->pid = childpid;
 +	    goto START_TRACE;
 +	  }
 +	  break;
 +	}
 +	funcs->exit_syscall(trussinfo, pfs.val);
 +	break;
        case S_SIG:
 -        fprintf(outfile, "SIGNAL %lu\n", pfs.val);
 -        sigexit = pfs.val;
 -        break;
 +	fprintf(trussinfo->outfile, "SIGNAL %lu\n", pfs.val);
 +	sigexit = pfs.val;
 +	break;
        case S_EXIT:
 -        fprintf (outfile, "process exit, rval = %lu\n", pfs.val);
 -        break;
 +	fprintf (trussinfo->outfile, "process exit, rval = %lu\n", pfs.val);
 +	break;
        case S_EXEC:
 -        funcs = set_etype();
 -        in_exec = 1;
 -        break;
 +	funcs = set_etype(trussinfo);
 +	in_exec = 1;
 +	break;
        default:
 -        fprintf (outfile, "Process stopped because of:  %d\n", i);
 -        break;
 +	fprintf (trussinfo->outfile, "Process stopped because of:  %d\n", i);
 +	break;
        }
      }
      if (ioctl(Procfd, PIOCCONT, val) == -1) {
 -      if (kill(pid, 0) == -1 && errno == ESRCH)
 -        break;
 +      if (kill(trussinfo->pid, 0) == -1 && errno == ESRCH)
 +	break;
        else
 -        warn("PIOCCONT");
 +	warn("PIOCCONT");
      }
    } while (pfs.why != S_EXIT);
 -  fflush(outfile);
 +  fflush(trussinfo->outfile);
    if (sigexit) {
      if (sigexit == SIGQUIT)
        exit(sigexit);
 
 -- 
 Thomas Quinot ** Département Informatique & Réseaux ** quinot@inf.enst.fr
               ENST   //   46 rue Barrault   //   75634 PARIS CEDEX 13 

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200110180950.f9I9o1n39783>