From owner-freebsd-bugs Fri Oct 19 1:50:28 2001 Delivered-To: freebsd-bugs@hub.freebsd.org Received: from freefall.freebsd.org (freefall.FreeBSD.org [216.136.204.21]) by hub.freebsd.org (Postfix) with ESMTP id 1676937B408 for ; Fri, 19 Oct 2001 01:50:01 -0700 (PDT) Received: (from gnats@localhost) by freefall.freebsd.org (8.11.4/8.11.4) id f9J8o1g14194; Fri, 19 Oct 2001 01:50:01 -0700 (PDT) (envelope-from gnats) Date: Fri, 19 Oct 2001 01:50:01 -0700 (PDT) Message-Id: <200110190850.f9J8o1g14194@freefall.freebsd.org> To: freebsd-bugs@FreeBSD.org Cc: From: Thomas Quinot Subject: Re: bin/25587: truss -f patch updated for -CURRENT 20011017 Reply-To: Thomas Quinot Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.org The following reply was made to PR bin/25587; it has been noted by GNATS. From: Thomas Quinot To: "Matthew N. Dodd" 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 #include #include +#include + +#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