*BSD News Article 84055


Return to BSD News archive

Newsgroups: comp.unix.bsd.freebsd.misc
Path: euryale.cc.adfa.oz.au!newshost.carno.net.au!harbinger.cc.monash.edu.au!nntp.coast.net!howland.erols.net!news.mathworks.com!uunet!in1.uu.net!205.179.156.40!kithrup.com!sef
From: sef@kithrup.com (Sean Eric Fagan)
Subject: Re: strace or truss for FreeBSD
Organization: Kithrup Enterprises, Ltd.
Message-ID: <E1rzME.2s4@kithrup.com>
References: <32A13666.41C67EA6@bis.co.il> <57sg1d$gcv@uriah.heep.sax.de> <57tv56$aue$1@gail.ripco.com>
Date: Mon, 2 Dec 1996 07:32:38 GMT
Lines: 104

In article <57tv56$aue$1@gail.ripco.com>, David Richards <dr@ripco.com> wrote:
>Among other features, root can attach to any running process, follow
>a process and all it's children (great for watching inetd launched handlers)
>choose which system calls to follow, watch the input/output on some/all
>file descriptors, etc.

Well... ktrace can attach to running processes.  Following children is hard,
as ktrace dumps to a specific file.

On the other hand, here is (most of) a small and simple truss clone that I
wrote one day.  It was mostly done as a proof-of-concept thing, and I needed
it to test some changes to procfs (which, of course, are not checked in).
But you can see the basic idea.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>

#include <sys/ioctl.h>
#include <sys/procfs.h>

/* These are defined in a header file somewhere, I just don't feel like
   including <sys/pioctl.h>. */

#define S_EXEC	0x0001	/* stop-on-exec */
#define S_SIG	0x0002	 /* stop-on-signal */
#define S_SCE	0x0004	/* stop-on-syscall-entry */
#define S_SCX	0x0008	/* stop-on-syscall-exit */
#define S_CORE	0x0010	/* stop-on-core-dump */
#define S_EXIT	0x0020	/* stop-on-exit */

main() {
	int pid;
	int fd;
	char buf[255];
	struct procfs_status ps;

	if ((pid = vfork()) == -1) {
		perror ("vfork");
		exit (1);
	}

	if (pid == 0) {	/* child */
		int i = S_EXEC;
		sprintf (buf, "/proc/curproc/mem");
		if ((fd = open (buf, O_RDONLY)) == -1) {
			perror ("open");
			exit (1);
		}
		if (ioctl (fd, PIOCEVBIS, &i) == -1) {
			perror ("child ioctl");
			exit (1);
		}
		execl ("/bin/echo", "echo", "hello world", 0);
		exit (1);
	} else {
		int i = S_EXEC | S_SCE | S_SCX | S_EXIT;
		int why = 0;
		int signo = 0;

		sprintf (buf, "/proc/%d/mem", pid);

		if ((fd = open (buf, O_RDONLY)) == -1) {
			perror ("parent open");
			exit (1);
		}

		printf ("doing a PIOCWAIT\n");
		if (ioctl (fd, PIOCWAIT, &ps) == -1) {
			perror ("PIOCWAIT");
			exit (1);
		}

		if (ioctl (fd, PIOCEVBIS, &i) == -1) {
			unsigned int j = ~0;
			perror ("PIOCEVBIS in parent");
			ioctl (fd, PIOCEVBIC, &j);
			exit (1);
		}

		do {
			int val;
			why = 0;
			ioctl (fd, PIOCCONT, &signo);
			val = ioctl (fd, PIOCWAIT, &ps);
			why = ps.why;
			val = ps.val;
			printf ("why = 0x%x, val = 0x%x\n", why, val);
			switch (why) {
			case S_SCE:	/* syscall entry */
				print_syscall_entry (pid, val);
				break;
			case S_SCX:	/* syscall exit */
				print_syscall_exit (pid, val);
				break;
			}
		} while (!(why & S_EXIT));
		ioctl (fd, PIOCCONT, &signo);
	}
	return 0;
}