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>
