Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 19 Oct 2001 01:50:01 -0700 (PDT)
From:      Thomas Quinot <quinot@inf.enst.fr>
To:        freebsd-bugs@FreeBSD.org
Subject:   Re: bin/25587: truss -f patch updated for -CURRENT 20011017
Message-ID:  <200110190850.f9J8o1g14194@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: "Matthew N. Dodd" <winter@jurai.net>
Cc: freebsd-gnats-submit@freebsd.org
Subject: Re: bin/25587: truss -f patch updated for -CURRENT 20011017
Date: Fri, 19 Oct 2001 10:45:04 +0200

 Le 2001-10-19, Matthew N. Dodd écrivait :
 
 > The patches to main.c don't apply cleanly.
 
 Strange. OK, I got a new, fresh copy of main.c 1.16 and diffed against
 that. Please let me know if this new diff applies correctly for you.
 
 Thanks,
 Thomas.
 
 --- main.c.dist	Fri Oct 19 10:42:29 2001
 +++ main.c	Fri Oct 19 10:42:35 2001
 @@ -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 +182,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 +197,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 +216,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 +243,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?200110190850.f9J8o1g14194>