Allow tracking fork()ed children.

PR:		 bin/25587 (in part)
MFC after:	3 weeks
This commit is contained in:
Matthew N. Dodd 2002-08-04 01:02:52 +00:00
parent ec0bed25ba
commit c03bfcc871
11 changed files with 80 additions and 10 deletions

View File

@ -155,6 +155,14 @@ alpha_syscall_entry(struct trussinfo *trussinfo, int nargs) {
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"))))
{
trussinfo->in_fork = 1;
}
if (nargs == 0)
return;

View File

@ -160,6 +160,14 @@ i386_syscall_entry(struct trussinfo *trussinfo, int nargs) {
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"))))
{
trussinfo->in_fork = 1;
}
if (nargs == 0)
return;

View File

@ -120,6 +120,13 @@ i386_linux_syscall_entry(struct trussinfo *trussinfo, int nargs) {
fprintf(trussinfo->outfile, "-- UNKNOWN SYSCALL %d\n", syscall);
}
if (lsc.name && (trussinfo->flags & FOLLOWFORKS)
&& ((!strcmp(lsc.name, "linux_fork")
|| !strcmp(lsc.name, "linux_vfork"))))
{
trussinfo->in_fork = 1;
}
if (nargs == 0)
return;

View File

@ -32,7 +32,7 @@
*/
extern int setup_and_wait(char **);
extern int start_tracing(int, int);
extern int start_tracing(int, int, int);
extern void restore_proc(int);
extern const char *ioctlname(register_t val);
#ifdef __alpha__

View File

@ -160,6 +160,14 @@ i386_syscall_entry(struct trussinfo *trussinfo, int nargs) {
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"))))
{
trussinfo->in_fork = 1;
}
if (nargs == 0)
return;

View File

@ -120,6 +120,13 @@ i386_linux_syscall_entry(struct trussinfo *trussinfo, int nargs) {
fprintf(trussinfo->outfile, "-- UNKNOWN SYSCALL %d\n", syscall);
}
if (lsc.name && (trussinfo->flags & FOLLOWFORKS)
&& ((!strcmp(lsc.name, "linux_fork")
|| !strcmp(lsc.name, "linux_vfork"))))
{
trussinfo->in_fork = 1;
}
if (nargs == 0)
return;

View File

@ -67,8 +67,8 @@ 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 [-fS] [-o file] -p pid",
" truss [-fS] [-o file] command [args]");
exit(1);
}
@ -145,11 +145,14 @@ main(int ac, char **av) {
bzero(trussinfo, sizeof(struct trussinfo));
trussinfo->outfile = stderr;
while ((c = getopt(ac, av, "p:o:S")) != -1) {
while ((c = getopt(ac, av, "p:o:fS")) != -1) {
switch (c) {
case 'p': /* specified pid */
trussinfo->pid = atoi(optarg);
break;
case 'f': /* Follow fork()'s */
trussinfo->flags |= FOLLOWFORKS;
break;
case 'o': /* Specified output file */
fname = optarg;
break;
@ -195,9 +198,11 @@ main(int ac, char **av) {
* be woken up, either in exit() or in execve().
*/
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 & NOSIGS) ? 0 : S_SIG),
((trussinfo->flags & FOLLOWFORKS) ? PF_FORK : 0));
if (Procfd == -1)
return 0;
@ -232,6 +237,23 @@ main(int ac, char **av) {
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:

View File

@ -130,7 +130,7 @@ setup_and_wait(char *command[]) {
*/
int
start_tracing(int pid, int flags) {
start_tracing(int pid, int eventflags, int flags) {
int fd;
char buf[32];
struct procfs_status tmp;
@ -153,7 +153,7 @@ start_tracing(int pid, int flags) {
}
evflags = tmp.events;
if (ioctl(fd, PIOCBIS, flags) == -1)
if (ioctl(fd, PIOCBIS, eventflags) == -1)
err(9, "cannot set procfs event bit mask");
/*
@ -162,7 +162,7 @@ start_tracing(int pid, int flags) {
* 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;

View File

@ -357,7 +357,12 @@ void
print_syscall(struct trussinfo *trussinfo, const char *name, int nargs, char **s_args) {
int i;
int len = 0;
if (trussinfo->flags & FOLLOWFORKS)
len += fprintf(trussinfo->outfile, "%5d: ", trussinfo->pid);
len += fprintf(trussinfo->outfile, "%s(", name);
for (i = 0; i < nargs; i++) {
if (s_args[i])
len += fprintf(trussinfo->outfile, "%s", s_args[i]);

View File

@ -8,11 +8,11 @@
.Nd trace system calls
.Sh SYNOPSIS
.Nm
.Op Fl S
.Op Fl fS
.Op Fl o Ar file
.Fl p Ar pid
.Nm
.Op Fl S
.Op Fl fS
.Op Fl o Ar file
command
.Op args
@ -26,6 +26,9 @@ It does this by stopping and restarting the process being monitored via
.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 S
Do not display information about signals received by the process.
(Normally,

View File

@ -25,11 +25,13 @@
* $FreeBSD$
*/
#define FOLLOWFORKS 0x00000001
#define NOSIGS 0x00000008
struct trussinfo
{
int pid;
int flags;
int in_fork;
FILE *outfile;
};