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;
}