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