From owner-freebsd-current@FreeBSD.ORG Fri Apr 6 12:59:40 2007 Return-Path: X-Original-To: current@freebsd.org Delivered-To: freebsd-current@FreeBSD.ORG Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id BCC1716A401; Fri, 6 Apr 2007 12:59:40 +0000 (UTC) (envelope-from bright@elvis.mu.org) Received: from elvis.mu.org (elvis.mu.org [192.203.228.196]) by mx1.freebsd.org (Postfix) with ESMTP id A86D913C43E; Fri, 6 Apr 2007 12:59:40 +0000 (UTC) (envelope-from bright@elvis.mu.org) Received: by elvis.mu.org (Postfix, from userid 1192) id 019451A3C1C; Fri, 6 Apr 2007 05:59:41 -0700 (PDT) Date: Fri, 6 Apr 2007 05:59:40 -0700 From: Alfred Perlstein To: Howard Su Message-ID: <20070406125940.GN2382@elvis.mu.org> References: Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.4.2.2i Cc: Robert Watson , current@freebsd.org Subject: Re: [Review] Remove procfs dependency of truss X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 06 Apr 2007 12:59:40 -0000 * Howard Su [070406 01:04] wrote: > Thanks to Robert to point out that my original patch didn't work > against a threaded application. I fixed that. Please try the new > patch. > > I tested this patch under i386 box only with libthr and libpthread. Ok, one nit and one potential issue I'd like to know about. nit: you have new functions like this "void fun(args)", they should be in the form of "void\nfun(args)" (newline after return type) possible issue: is get_string equivelant to the procfs version? meaning, if there's a string that ends at a strange place in the address space will it work any differently? note how the procfs version does a fgetc(3) over and over and stops reading if it hits \0, while the version you have tried to read the entire buf. Can that cause issues? > > Howard > > On 4/4/07, Howard Su wrote: > >Following the suggestion in idea page, I proposed the attached patch. > >I didn't change any kernel part because I think PTRACE(2) is > >functional although man page didn't document it. > > > >I tested the patch under i386 and amd64 box. The help on testing and > >code review will be appreciated. > > > >To test, please try the following commands: > >1. truss ps > >basic stuff > >2. truss -o output ps > >output the result to file > >3. truss -f -o output sh -c "ps" > >test follow fork > >4. start TOP(1) in another session, the > >truss -p > > > >-- > >-Howard > > > > > > > -- > -Howard > ==== //depot/vendor/freebsd/src/usr.bin/truss/Makefile#9 (text+ko) - //depot/user/howardsu/truss/usr.bin/truss/Makefile#1 (text+ko) ==== identical > ==== //depot/vendor/freebsd/src/usr.bin/truss/amd64-fbsd.c#6 (text+ko) - //depot/user/howardsu/truss/usr.bin/truss/amd64-fbsd.c#5 (text+ko) ==== content > @@ -43,8 +43,7 @@ > */ > > #include > -#include > -#include > +#include > #include > > #include > @@ -63,7 +62,6 @@ > #include "syscall.h" > #include "extern.h" > > -static int fd = -1; > static int cpid = -1; > > #include "syscalls.h" > @@ -113,25 +111,16 @@ > > void > amd64_syscall_entry(struct trussinfo *trussinfo, int nargs) { > - char buf[32]; > struct reg regs; > int syscall_num; > int i, reg; > struct syscall *sc; > > - if (fd == -1 || trussinfo->pid != cpid) { > - sprintf(buf, "/proc/%d/regs", trussinfo->pid); > - fd = open(buf, O_RDWR); > - if (fd == -1) { > - fprintf(trussinfo->outfile, "-- CANNOT OPEN REGISTERS --\n"); > - return; > - } > - cpid = trussinfo->pid; > - } > + cpid = trussinfo->curthread->tid; > > clear_fsc(); > - lseek(fd, 0L, 0); > - if (read(fd, ®s, sizeof(regs)) != sizeof(regs)) { > + if (ptrace(PT_GETREGS, cpid, (caddr_t)®s, 0) < 0) > + { > fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); > return; > } > @@ -163,7 +152,7 @@ > || !strcmp(fsc.name, "rfork") > || !strcmp(fsc.name, "vfork")))) > { > - trussinfo->in_fork = 1; > + trussinfo->curthread->in_fork = 1; > } > > if (nargs == 0) > @@ -181,8 +170,13 @@ > } > } > if (nargs > i) { > - lseek(Procfd, regs.r_rsp + sizeof(register_t), SEEK_SET); > - if (read(Procfd, &fsc.args[i], (nargs-i) * sizeof(register_t)) == -1) > + struct ptrace_io_desc iorequest; > + iorequest.piod_op = PIOD_READ_D; > + iorequest.piod_offs = (void *)(regs.r_rsp + sizeof(register_t)); > + iorequest.piod_addr = &fsc.args[i]; > + iorequest.piod_len = (nargs - i) * sizeof(register_t); > + ptrace(PT_IO, cpid, (caddr_t)&iorequest, 0); > + if (iorequest.piod_len == 0) > return; > } > > @@ -223,7 +217,7 @@ > i < (fsc.nargs - 1) ? "," : ""); > #endif > if (sc && !(sc->args[i].type & OUT)) { > - fsc.s_args[i] = print_arg(Procfd, &sc->args[i], fsc.args, 0, trussinfo); > + fsc.s_args[i] = print_arg(&sc->args[i], fsc.args, 0, trussinfo); > } > } > #if DEBUG > @@ -279,25 +273,16 @@ > long > amd64_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused) > { > - char buf[32]; > struct reg regs; > long retval; > int i; > int errorp; > struct syscall *sc; > > - if (fd == -1 || trussinfo->pid != cpid) { > - sprintf(buf, "/proc/%d/regs", trussinfo->pid); > - fd = open(buf, O_RDONLY); > - if (fd == -1) { > - fprintf(trussinfo->outfile, "-- CANNOT OPEN REGISTERS --\n"); > - return (-1); > - } > - cpid = trussinfo->pid; > - } > + cpid = trussinfo->curthread->tid; > > - lseek(fd, 0L, 0); > - if (read(fd, ®s, sizeof(regs)) != sizeof(regs)) { > + if (ptrace(PT_GETREGS, cpid, (caddr_t)®s, 0) < 0) > + { > fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); > return (-1); > } > @@ -328,7 +313,7 @@ > if (errorp) > asprintf(&temp, "0x%lx", fsc.args[sc->args[i].offset]); > else > - temp = print_arg(Procfd, &sc->args[i], fsc.args, retval, trussinfo); > + temp = print_arg(&sc->args[i], fsc.args, retval, trussinfo); > fsc.s_args[i] = temp; > } > } > ==== //depot/vendor/freebsd/src/usr.bin/truss/extern.h#10 (text+ko) - //depot/user/howardsu/truss/usr.bin/truss/extern.h#3 (text+ko) ==== content > @@ -32,8 +32,9 @@ > */ > > extern int setup_and_wait(char **); > -extern int start_tracing(int, int, int, int); > +extern int start_tracing(int); > extern void restore_proc(int); > +extern void waitevent(struct trussinfo *); > extern const char *ioctlname(register_t val); > extern char *strsig(int sig); > #ifdef __alpha__ > @@ -63,4 +64,3 @@ > extern long sparc64_syscall_exit(struct trussinfo *, int); > #endif > > -extern int Procfd; > ==== //depot/vendor/freebsd/src/usr.bin/truss/i386-fbsd.c#17 (text+ko) - //depot/user/howardsu/truss/usr.bin/truss/i386-fbsd.c#4 (text+ko) ==== content > @@ -43,9 +43,8 @@ > */ > > #include > -#include > -#include > #include > +#include > > #include > #include > @@ -63,7 +62,6 @@ > #include "syscall.h" > #include "extern.h" > > -static int fd = -1; > static int cpid = -1; > > #include "syscalls.h" > @@ -113,26 +111,18 @@ > > void > i386_syscall_entry(struct trussinfo *trussinfo, int nargs) { > - char buf[32]; > struct reg regs; > int syscall_num; > int i; > unsigned int parm_offset; > struct syscall *sc = NULL; > + struct ptrace_io_desc iorequest; > + cpid = trussinfo->curthread->tid; > > - if (fd == -1 || trussinfo->pid != cpid) { > - sprintf(buf, "/proc/%d/regs", trussinfo->pid); > - fd = open(buf, O_RDWR); > - if (fd == -1) { > - fprintf(trussinfo->outfile, "-- CANNOT OPEN REGISTERS --\n"); > - return; > - } > - cpid = trussinfo->pid; > - } > - > clear_fsc(); > - lseek(fd, 0L, 0); > - if (read(fd, ®s, sizeof(regs)) != sizeof(regs)) { > + > + if (ptrace(PT_GETREGS, cpid, (caddr_t)®s, 0) < 0) > + { > fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); > return; > } > @@ -146,13 +136,11 @@ > syscall_num = regs.r_eax; > switch (syscall_num) { > case SYS_syscall: > - lseek(Procfd, parm_offset, SEEK_SET); > - read(Procfd, &syscall_num, sizeof(int)); > + syscall_num = ptrace(PT_READ_D, cpid, (caddr_t)parm_offset, 0); > parm_offset += sizeof(int); > break; > case SYS___syscall: > - lseek(Procfd, parm_offset, SEEK_SET); > - read(Procfd, &syscall_num, sizeof(int)); > + syscall_num = ptrace(PT_READ_D, cpid, (caddr_t)parm_offset, 0); > parm_offset += sizeof(quad_t); > break; > } > @@ -169,15 +157,19 @@ > || !strcmp(fsc.name, "rfork") > || !strcmp(fsc.name, "vfork")))) > { > - trussinfo->in_fork = 1; > + trussinfo->curthread->in_fork = 1; > } > > if (nargs == 0) > return; > > fsc.args = malloc((1+nargs) * sizeof(unsigned long)); > - lseek(Procfd, parm_offset, SEEK_SET); > - if (read(Procfd, fsc.args, nargs * sizeof(unsigned long)) == -1) > + iorequest.piod_op = PIOD_READ_D; > + iorequest.piod_offs = (void *)parm_offset; > + iorequest.piod_addr = fsc.args; > + iorequest.piod_len = nargs * sizeof(unsigned long); > + ptrace(PT_IO, cpid, (caddr_t)&iorequest, 0); > + if (iorequest.piod_len == 0) > return; > > if (fsc.name) > @@ -218,7 +210,7 @@ > i < (fsc.nargs - 1) ? "," : ""); > #endif > if (sc && !(sc->args[i].type & OUT)) { > - fsc.s_args[i] = print_arg(Procfd, &sc->args[i], fsc.args, 0, trussinfo); > + fsc.s_args[i] = print_arg(&sc->args[i], fsc.args, 0, trussinfo); > } > } > #if DEBUG > @@ -274,28 +266,20 @@ > long > i386_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused) > { > - char buf[32]; > struct reg regs; > long retval; > int i; > int errorp; > struct syscall *sc; > > - if (fd == -1 || trussinfo->pid != cpid) { > - sprintf(buf, "/proc/%d/regs", trussinfo->pid); > - fd = open(buf, O_RDONLY); > - if (fd == -1) { > - fprintf(trussinfo->outfile, "-- CANNOT OPEN REGISTERS --\n"); > - return (-1); > - } > - cpid = trussinfo->pid; > - } > + cpid = trussinfo->curthread->tid; > > - lseek(fd, 0L, 0); > - if (read(fd, ®s, sizeof(regs)) != sizeof(regs)) { > + if (ptrace(PT_GETREGS, cpid, (caddr_t)®s, 0) < 0) > + { > fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); > return (-1); > } > + > retval = regs.r_eax; > errorp = !!(regs.r_eflags & PSL_C); > > @@ -323,7 +307,7 @@ > if (errorp) > asprintf(&temp, "0x%lx", fsc.args[sc->args[i].offset]); > else > - temp = print_arg(Procfd, &sc->args[i], fsc.args, retval, trussinfo); > + temp = print_arg(&sc->args[i], fsc.args, retval, trussinfo); > fsc.s_args[i] = temp; > } > } > ==== //depot/vendor/freebsd/src/usr.bin/truss/i386-linux.c#16 (text+ko) - //depot/user/howardsu/truss/usr.bin/truss/i386-linux.c#4 (text+ko) ==== content > @@ -41,8 +41,7 @@ > */ > > #include > -#include > -#include > +#include > > #include > #include > @@ -60,7 +59,6 @@ > #include "syscall.h" > #include "extern.h" > > -static int fd = -1; > static int cpid = -1; > > #include "linux_syscalls.h" > @@ -108,28 +106,20 @@ > > void > i386_linux_syscall_entry(struct trussinfo *trussinfo, int nargs) { > - char buf[32]; > struct reg regs; > int syscall_num; > int i; > struct syscall *sc; > > - if (fd == -1 || trussinfo->pid != cpid) { > - sprintf(buf, "/proc/%d/regs", trussinfo->pid); > - fd = open(buf, O_RDWR); > - if (fd == -1) { > - fprintf(trussinfo->outfile, "-- CANNOT OPEN REGISTERS --\n"); > - return; > - } > - cpid = trussinfo->pid; > - } > + cpid = trussinfo->curthread->tid; > > clear_fsc(); > - lseek(fd, 0L, 0); > - if (read(fd, ®s, sizeof(regs)) != sizeof(regs)) { > + > + if (ptrace(PT_GETREGS, cpid, (caddr_t)®s, 0) < 0) > + { > fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); > return; > - } > + } > syscall_num = regs.r_eax; > > fsc.number = syscall_num; > @@ -143,7 +133,7 @@ > && ((!strcmp(fsc.name, "linux_fork") > || !strcmp(fsc.name, "linux_vfork")))) > { > - trussinfo->in_fork = 1; > + trussinfo->curthread->in_fork = 1; > } > > if (nargs == 0) > @@ -200,7 +190,7 @@ > i < (fsc.nargs - 1) ? "," : ""); > #endif > if (sc && !(sc->args[i].type & OUT)) { > - fsc.s_args[i] = print_arg(Procfd, &sc->args[i], fsc.args, 0, trussinfo); > + fsc.s_args[i] = print_arg(&sc->args[i], fsc.args, 0, trussinfo); > } > } > #if DEBUG > @@ -264,28 +254,19 @@ > long > i386_linux_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused) > { > - char buf[32]; > struct reg regs; > long retval; > int i; > int errorp; > struct syscall *sc; > > - if (fd == -1 || trussinfo->pid != cpid) { > - sprintf(buf, "/proc/%d/regs", trussinfo->pid); > - fd = open(buf, O_RDONLY); > - if (fd == -1) { > - fprintf(trussinfo->outfile, "-- CANNOT OPEN REGISTERS --\n"); > - return (-1); > - } > - cpid = trussinfo->pid; > + cpid = trussinfo->curthread->tid; > + if (ptrace(PT_GETREGS, cpid, (caddr_t)®s, 0) < 0) > + { > + fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); > + return (-1); > } > > - lseek(fd, 0L, 0); > - if (read(fd, ®s, sizeof(regs)) != sizeof(regs)) { > - fprintf(trussinfo->outfile, "\n"); > - return (-1); > - } > retval = regs.r_eax; > errorp = !!(regs.r_eflags & PSL_C); > > @@ -313,7 +294,7 @@ > if (errorp) > asprintf(&temp, "0x%lx", fsc.args[sc->args[i].offset]); > else > - temp = print_arg(Procfd, &sc->args[i], fsc.args, retval, trussinfo); > + temp = print_arg(&sc->args[i], fsc.args, retval, trussinfo); > fsc.s_args[i] = temp; > } > } > ==== //depot/vendor/freebsd/src/usr.bin/truss/i386.conf#1 (text+ko) - //depot/user/howardsu/truss/usr.bin/truss/i386.conf#1 (text+ko) ==== identical > ==== //depot/vendor/freebsd/src/usr.bin/truss/i386linux.conf#1 (text+ko) - //depot/user/howardsu/truss/usr.bin/truss/i386linux.conf#1 (text+ko) ==== identical > ==== //depot/vendor/freebsd/src/usr.bin/truss/ia64-fbsd.c#9 (text+ko) - //depot/user/howardsu/truss/usr.bin/truss/ia64-fbsd.c#3 (text+ko) ==== content > @@ -43,8 +43,7 @@ > */ > > #include > -#include > -#include > +#include > #include > > #include > @@ -62,7 +61,6 @@ > #include "syscall.h" > #include "extern.h" > > -static int fd = -1; > static int cpid = -1; > > #include "syscalls.h" > @@ -112,26 +110,16 @@ > > void > ia64_syscall_entry(struct trussinfo *trussinfo, int nargs) { > - char buf[32]; > struct reg regs; > int syscall_num; > int i; > unsigned long *parm_offset; > struct syscall *sc; > > - if (fd == -1 || trussinfo->pid != cpid) { > - sprintf(buf, "/proc/%d/regs", trussinfo->pid); > - fd = open(buf, O_RDWR); > - if (fd == -1) { > - fprintf(trussinfo->outfile, "-- CANNOT OPEN REGISTERS --\n"); > - return; > - } > - cpid = trussinfo->pid; > - } > + cpid = trussinfo->curthread->id; > > clear_fsc(); > - lseek(fd, 0L, 0); > - if (read(fd, ®s, sizeof(regs)) != sizeof(regs)) { > + if (ptrace(PT_GETREGS, cpid, (caddr_t)®s, 0) < 0) { > fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); > return; > } > @@ -158,7 +146,7 @@ > || !strcmp(fsc.name, "rfork") > || !strcmp(fsc.name, "vfork")))) > { > - trussinfo->in_fork = 1; > + trussinfo->curthread->in_fork = 1; > } > > if (nargs == 0) > @@ -204,7 +192,7 @@ > i < (fsc.nargs - 1) ? "," : ""); > #endif > if (sc && !(sc->args[i].type & OUT)) { > - fsc.s_args[i] = print_arg(Procfd, &sc->args[i], fsc.args, 0, trussinfo); > + fsc.s_args[i] = print_arg(&sc->args[i], fsc.args, 0, trussinfo); > } > } > #if DEBUG > @@ -260,25 +248,15 @@ > long > ia64_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused) > { > - char buf[32]; > struct reg regs; > long retval; > int i; > int errorp; > struct syscall *sc; > > - if (fd == -1 || trussinfo->pid != cpid) { > - sprintf(buf, "/proc/%d/regs", trussinfo->pid); > - fd = open(buf, O_RDONLY); > - if (fd == -1) { > - fprintf(trussinfo->outfile, "-- CANNOT OPEN REGISTERS --\n"); > - return (-1); > - } > - cpid = trussinfo->pid; > - } > + cpid = trussinfo->curthread->tid; > > - lseek(fd, 0L, 0); > - if (read(fd, ®s, sizeof(regs)) != sizeof(regs)) { > + if (ptrace(PT_GETREGS, cpid, (caddr_t)®s, 0) < 0) { > fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); > return (-1); > } > @@ -309,7 +287,7 @@ > if (errorp) > asprintf(&temp, "0x%lx", fsc.args[sc->args[i].offset]); > else > - temp = print_arg(Procfd, &sc->args[i], fsc.args, retval, trussinfo); > + temp = print_arg(&sc->args[i], fsc.args, retval, trussinfo); > fsc.s_args[i] = temp; > } > } > ==== //depot/vendor/freebsd/src/usr.bin/truss/main.c#24 (text+ko) - //depot/user/howardsu/truss/usr.bin/truss/main.c#6 (text+ko) ==== content > @@ -39,11 +39,10 @@ > */ > > #include > -#include > -#include > #include > #include > #include > +#include > > #include > #include > @@ -59,13 +58,8 @@ > #include "truss.h" > #include "extern.h" > > -/* > - * It's difficult to parameterize this because it must be > - * accessible in a signal handler. > - */ > +#define MAXARGS 5 > > -int Procfd; > - > static void > usage(void) > { > @@ -119,18 +113,19 @@ > set_etype(struct trussinfo *trussinfo) > { > struct ex_types *funcs; > - char etype[24]; > char progt[32]; > - int fd; > + > + size_t len = sizeof(progt); > + int mib[4]; > + int error; > > - sprintf(etype, "/proc/%d/etype", trussinfo->pid); > - if ((fd = open(etype, O_RDONLY)) == -1) { > - strcpy(progt, "FreeBSD a.out"); > - } else { > - int len = read(fd, progt, sizeof(progt)); > - progt[len-1] = '\0'; > - close(fd); > - } > + mib[0] = CTL_KERN; > + mib[1] = KERN_PROC; > + mib[2] = KERN_PROC_SV_NAME; > + mib[3] = trussinfo->pid; > + error = sysctl(mib, 4, progt, &len, NULL, 0); > + if (error != 0) > + err(2, "can not get etype"); > > for (funcs = ex_types; funcs->type; funcs++) > if (!strcmp(funcs->type, progt)) > @@ -167,14 +162,12 @@ > int c; > int i; > char **command; > - struct procfs_status pfs; > struct ex_types *funcs; > - int in_exec, sigexit, initial_open; > + int sigexit, initial_open; > char *fname; > struct trussinfo *trussinfo; > char *signame; > > - in_exec = 0; > sigexit = 0; > fname = NULL; > initial_open = 1; > @@ -184,9 +177,12 @@ > if (trussinfo == NULL) > errx(1, "malloc() failed"); > bzero(trussinfo, sizeof(struct trussinfo)); > + > trussinfo->outfile = stderr; > trussinfo->strsize = 32; > - > + trussinfo->pr_why = S_NONE; > + trussinfo->curthread = NULL; > + SLIST_INIT(&trussinfo->threadlist); > while ((c = getopt(ac, av, "p:o:faedDs:S")) != -1) { > switch (c) { > case 'p': /* specified pid */ > @@ -245,6 +241,7 @@ > signal(SIGTERM, SIG_IGN); > signal(SIGQUIT, SIG_IGN); > } else { > + start_tracing(trussinfo->pid); > signal(SIGINT, restore_proc); > signal(SIGTERM, restore_proc); > signal(SIGQUIT, restore_proc); > @@ -257,18 +254,9 @@ > */ > > START_TRACE: > - Procfd = start_tracing( > - trussinfo->pid, initial_open, > - S_EXEC | S_SCE | S_SCX | S_CORE | S_EXIT | > - ((trussinfo->flags & NOSIGS) ? 0 : S_SIG), > - ((trussinfo->flags & FOLLOWFORKS) ? PF_FORK : 0)); > + funcs = set_etype(trussinfo); > + > initial_open = 0; > - if (Procfd == -1) > - return (0); > - > - pfs.why = 0; > - > - 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. > @@ -278,118 +266,92 @@ > clock_gettime(CLOCK_REALTIME, &trussinfo->start_time); > > do { > - int val = 0; > struct timespec timediff; > + waitevent(trussinfo); > > - if (ioctl(Procfd, PIOCWAIT, &pfs) == -1) > - warn("PIOCWAIT top of loop"); > - else { > - switch(i = pfs.why) { > - case S_SCE: > - funcs->enter_syscall(trussinfo, pfs.val); > - clock_gettime(CLOCK_REALTIME, > - &trussinfo->before); > - break; > - case S_SCX: > - clock_gettime(CLOCK_REALTIME, > - &trussinfo->after); > - /* > - * 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; > - } > + switch(i = trussinfo->pr_why) { > + case S_SCE: > + funcs->enter_syscall(trussinfo, MAXARGS); > + clock_gettime(CLOCK_REALTIME, > + &trussinfo->before); > + break; > + case S_SCX: > + clock_gettime(CLOCK_REALTIME, > + &trussinfo->after); > > - if (trussinfo->in_fork && > - (trussinfo->flags & FOLLOWFORKS)) { > - int childpid; > + if (trussinfo->curthread->in_fork && > + (trussinfo->flags & FOLLOWFORKS)) { > + int childpid; > > - trussinfo->in_fork = 0; > - childpid = > - funcs->exit_syscall(trussinfo, > - pfs.val); > + trussinfo->curthread->in_fork = 0; > + childpid = > + funcs->exit_syscall(trussinfo, > + trussinfo->pr_data); > > - /* > - * 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; > + /* > + * Fork a new copy of ourself to trace > + * the child of the original traced > + * process. > + */ > + if (fork() == 0) { > + trussinfo->pid = childpid; > + start_tracing(trussinfo->pid); > + goto START_TRACE; > } > - funcs->exit_syscall(trussinfo, pfs.val); > break; > - case S_SIG: > - if (trussinfo->flags & FOLLOWFORKS) > - fprintf(trussinfo->outfile, "%5d: ", > - trussinfo->pid); > - if (trussinfo->flags & ABSOLUTETIMESTAMPS) { > - timespecsubt(&trussinfo->after, > - &trussinfo->start_time, &timediff); > - fprintf(trussinfo->outfile, "%ld.%09ld ", > - (long)timediff.tv_sec, > - timediff.tv_nsec); > - } > - if (trussinfo->flags & RELATIVETIMESTAMPS) { > - timespecsubt(&trussinfo->after, > - &trussinfo->before, &timediff); > - fprintf(trussinfo->outfile, "%ld.%09ld ", > - (long)timediff.tv_sec, > - timediff.tv_nsec); > - } > - signame = strsig(pfs.val); > - fprintf(trussinfo->outfile, > - "SIGNAL %lu (%s)\n", pfs.val, > - signame == NULL ? "?" : signame); > - free(signame); > - sigexit = pfs.val; > + } > + funcs->exit_syscall(trussinfo, MAXARGS); > + break; > + case S_SIG: > + if (trussinfo->flags & NOSIGS) > break; > - case S_EXIT: > - if (trussinfo->flags & FOLLOWFORKS) > - fprintf(trussinfo->outfile, "%5d: ", > - trussinfo->pid); > - if (trussinfo->flags & ABSOLUTETIMESTAMPS) { > - timespecsubt(&trussinfo->after, > - &trussinfo->start_time, &timediff); > - fprintf(trussinfo->outfile, "%ld.%09ld ", > - (long)timediff.tv_sec, > - timediff.tv_nsec); > - } > - if (trussinfo->flags & RELATIVETIMESTAMPS) { > - timespecsubt(&trussinfo->after, > - &trussinfo->before, &timediff); > - fprintf(trussinfo->outfile, "%ld.%09ld ", > - (long)timediff.tv_sec, timediff.tv_nsec); > - } > - fprintf(trussinfo->outfile, > - "process exit, rval = %lu\n", pfs.val); > - break; > - case S_EXEC: > - funcs = set_etype(trussinfo); > - in_exec = 1; > - break; > - default: > - fprintf(trussinfo->outfile, > - "Process stopped because of: %d\n", i); > - break; > + if (trussinfo->flags & FOLLOWFORKS) > + fprintf(trussinfo->outfile, "%5d: ", > + trussinfo->pid); > + if (trussinfo->flags & ABSOLUTETIMESTAMPS) { > + timespecsubt(&trussinfo->after, > + &trussinfo->start_time, &timediff); > + fprintf(trussinfo->outfile, "%ld.%09ld ", > + (long)timediff.tv_sec, > + timediff.tv_nsec); > + } > + if (trussinfo->flags & RELATIVETIMESTAMPS) { > + timespecsubt(&trussinfo->after, > + &trussinfo->before, &timediff); > + fprintf(trussinfo->outfile, "%ld.%09ld ", > + (long)timediff.tv_sec, > + timediff.tv_nsec); > + } > + signame = strsig(trussinfo->pr_data); > + fprintf(trussinfo->outfile, > + "SIGNAL %u (%s)\n", trussinfo->pr_data, > + signame == NULL ? "?" : signame); > + free(signame); > + break; > + case S_EXIT: > + if (trussinfo->flags & FOLLOWFORKS) > + fprintf(trussinfo->outfile, "%5d: ", > + trussinfo->pid); > + if (trussinfo->flags & ABSOLUTETIMESTAMPS) { > + timespecsubt(&trussinfo->after, > + &trussinfo->start_time, &timediff); > + fprintf(trussinfo->outfile, "%ld.%09ld ", > + (long)timediff.tv_sec, > + timediff.tv_nsec); > + } > + if (trussinfo->flags & RELATIVETIMESTAMPS) { > + timespecsubt(&trussinfo->after, > + &trussinfo->before, &timediff); > + fprintf(trussinfo->outfile, "%ld.%09ld ", > + (long)timediff.tv_sec, timediff.tv_nsec); > } > + fprintf(trussinfo->outfile, > + "process exit, rval = %u\n", trussinfo->pr_data); > + break; > + default: > + break; > } > - if (ioctl(Procfd, PIOCCONT, val) == -1) { > - if (kill(trussinfo->pid, 0) == -1 && errno == ESRCH) > - break; > - else > - warn("PIOCCONT"); > - } > - } while (pfs.why != S_EXIT); > + } while (trussinfo->pr_why != S_EXIT); > fflush(trussinfo->outfile); > if (sigexit) { > struct rlimit rlp; > @@ -400,5 +362,6 @@ > (void) signal(sigexit, SIG_DFL); > (void) kill(getpid(), sigexit); > } > + > return (0); > } > ==== //depot/vendor/freebsd/src/usr.bin/truss/powerpc-fbsd.c#1 (text+ko) - //depot/user/howardsu/truss/usr.bin/truss/powerpc-fbsd.c#4 (text+ko) ==== content > @@ -41,8 +41,7 @@ > */ > > #include > -#include > -#include > +#include > #include > > #include > @@ -62,7 +61,6 @@ > #include "syscall.h" > #include "extern.h" > > -static int fd = -1; > static int cpid = -1; > > #include "syscalls.h" > @@ -120,19 +118,10 @@ > unsigned int regargs; > struct syscall *sc; > > - if (fd == -1 || trussinfo->pid != cpid) { > - sprintf(buf, "/proc/%d/regs", trussinfo->pid); > - fd = open(buf, O_RDWR); > - if (fd == -1) { > - fprintf(trussinfo->outfile, "-- CANNOT OPEN REGISTERS --\n"); > - return; > - } > - cpid = trussinfo->pid; > - } > + cpid = trussinfo->curthread->tid; > > clear_fsc(); > - lseek(fd, 0L, 0); > - if (read(fd, ®s, sizeof(regs)) != sizeof(regs)) { > + if (ptrace(PT_GETREGS, cpid, (caddr_t)®s, 0) < 0) { > fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); > return; > } > @@ -167,7 +156,7 @@ > || !strcmp(fsc.name, "rfork") > || !strcmp(fsc.name, "vfork")))) > { > - trussinfo->in_fork = 1; > + trussinfo->curthread->in_fork = 1; > } > > if (nargs == 0) > @@ -176,9 +165,16 @@ > fsc.args = malloc((1+nargs) * sizeof(unsigned long)); > > if (nargs > regargs) { > + struct ptrace_io_desc iorequest; > memmove(&fsc.args[0], args, regargs * sizeof(fsc.args[0])); > - lseek(Procfd, regs.fixreg[1] + 8, SEEK_SET); > - read(Procfd, &fsc.args[regargs], (nargs - regargs) * sizeof(fsc.args[0])); > + > + iorequest.piod_op = PIOD_READ_D; > + iorequest.piod_offs = (void *)(regs.fixreg[1] + 8); > + iorequest.piod_addr = &fsc.args[regargs]; > + iorequest.piod_len = (nargs - regargs) * sizeof(fsc.args[0]); > + ptrace(PT_IO, cpid, (caddr_t)&iorequest, 0); > + if (iorequest.piod_len == 0) > + return; > } else { > memmove(&fsc.args[0], args, nargs * sizeof(fsc.args[0])); > } > @@ -220,7 +216,7 @@ > i < (fsc.nargs - 1) ? "," : ""); > #endif > if (sc && !(sc->args[i].type & OUT)) { > - fsc.s_args[i] = print_arg(Procfd, &sc->args[i], fsc.args, 0, trussinfo); > + fsc.s_args[i] = print_arg(&sc->args[i], fsc.args, 0, trussinfo); > } > } > #if DEBUG > @@ -275,25 +271,15 @@ > long > powerpc_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused) > { > - char buf[32]; > struct reg regs; > long retval; > int i; > int errorp; > struct syscall *sc; > > - if (fd == -1 || trussinfo->pid != cpid) { > - sprintf(buf, "/proc/%d/regs", trussinfo->pid); > - fd = open(buf, O_RDONLY); > - if (fd == -1) { > - fprintf(trussinfo->outfile, "-- CANNOT OPEN REGISTERS --\n"); > - return (-1); > - } > - cpid = trussinfo->pid; > - } > + cpid = trussinfo->curthread->tid; > > - lseek(fd, 0L, 0); > - if (read(fd, ®s, sizeof(regs)) != sizeof(regs)) { > + if (ptrace(PT_GETREGS, cpid, (caddr_t)®s, 0) < 0) { > fprintf(trussinfo->outfile, "\n"); > return (-1); > } > @@ -332,7 +318,7 @@ > if (errorp) > asprintf(&temp, "0x%lx", fsc.args[sc->args[i].offset]); > else > - temp = print_arg(Procfd, &sc->args[i], fsc.args, retval, trussinfo); > + temp = print_arg(&sc->args[i], fsc.args, retval, trussinfo); > fsc.s_args[i] = temp; > } > } > ==== //depot/vendor/freebsd/src/usr.bin/truss/setup.c#11 (text+ko) - //depot/user/howardsu/truss/usr.bin/truss/setup.c#7 (text+ko) ==== content > @@ -38,11 +38,12 @@ > */ > > #include > -#include > -#include > +#include > +#include > #include > > #include > +#include > #include > #include > #include > @@ -51,10 +52,12 @@ > #include > #include > > +#include > + > #include "truss.h" > #include "extern.h" > > -static int evflags = 0; > +static int child_pid; > > /* > * setup_and_wait() is called to start a process. All it really does > @@ -66,75 +69,28 @@ > int > setup_and_wait(char *command[]) > { > - struct procfs_status pfs; > - char buf[32]; > - int fd; > int pid; > - int flags; > - int loop; > + int waitval; > > - pid = fork(); > + pid = vfork(); > if (pid == -1) { > err(1, "fork failed"); > } > if (pid == 0) { /* Child */ > - int mask = S_EXEC | S_EXIT; > - fd = open("/proc/curproc/mem", O_WRONLY); > - if (fd == -1) > - err(2, "cannot open /proc/curproc/mem"); > - fcntl(fd, F_SETFD, 1); > - if (ioctl(fd, PIOCBIS, mask) == -1) > - err(3, "PIOCBIS"); > - flags = PF_LINGER; > - /* > - * The PF_LINGER flag tells procfs not to wake up the > - * process on last close; normally, this is the behaviour > - * we want. > - */ > - if (ioctl(fd, PIOCSFL, flags) == -1) > - warn("cannot set PF_LINGER"); > + ptrace(PT_TRACE_ME, 0, 0, 0); > + setpgid (0, 0); > execvp(command[0], command); > - mask = ~0; > - ioctl(fd, PIOCBIC, ~0); > - err(4, "execvp %s", command[0]); > + err(1, "execvp %s", command[0]); > } > + > /* Only in the parent here */ > - > - if (waitpid(pid, NULL, WNOHANG) != 0) { > - /* > - * Process exited before it got to us -- meaning the exec failed > - * miserably -- so we just quietly exit. > - */ > - exit(1); > + if (waitpid(pid, &waitval, 0) < -1) { > + err(1, "unexpect stop in waitpid"); > + return 0; > } > > - sprintf(buf, "/proc/%d/mem", pid); > - > - /* Try 6 times to trace our child, waiting 1/2 second each time */ > - for (loop=6 ;; loop--) { > - if (loop != 6) > - usleep(500000); > - if ((fd = open(buf, O_RDWR)) == -1) { > - if (loop > 0) > - continue; > - else > - err(5, "cannot open1 %s", buf); > - } > - if (ioctl(fd, PIOCWAIT, &pfs) == -1) { > - if (loop >= 0) > - continue; > - else > - err(6, "PIOCWAIT"); > - } > - if (pfs.why == S_EXIT) { > - warnx("process exited before exec'ing"); > - ioctl(fd, PIOCCONT, 0); > - wait(0); > - exit(7); > - } else > - break; > - } > - close(fd); > + child_pid = pid; > + > return (pid); > } > > @@ -145,45 +101,24 @@ > */ > > int > -start_tracing(int pid, int failisfatal, int eventflags, int flags) > +start_tracing(int pid) > { > - int fd; > - char buf[32]; > - struct procfs_status tmp; > + int waitval; > + int ret; > + int retry = 10; > > - sprintf(buf, "/proc/%d/mem", pid); > - /* usleep(500000); */ > + do { > + ret = ptrace(PT_ATTACH, pid, NULL, 0); > + usleep(200); > + } while(ret && retry-- > 0); > + if (ret) > + err(1, "can not attach to target process"); > > - fd = open(buf, O_RDWR); > - if (fd == -1) { > - /* > - * The process may have run away before we could start -- this > - * happens with SUGID programs. So we need to see if it still > - * exists before we complain bitterly. > - */ > - if (!failisfatal && kill(pid, 0) == -1) > - return (-1); > - err(8, "cannot open2 %s", buf); > - } > + child_pid = pid; > + if (waitpid(pid, &waitval, 0) < -1) > + err(1, "Unexpect stop in waitpid"); > > - if (ioctl(fd, PIOCSTATUS, &tmp) == -1) { > - err(10, "cannot get procfs status struct"); > - } > - evflags = tmp.events; > - > - if (ioctl(fd, PIOCBIS, eventflags) == -1) > - err(9, "cannot set procfs event bit mask"); > - > - /* > - * This clears the PF_LINGER set above in setup_and_wait(); > - * if truss happens to die before this, then the process > - * needs to be woken up via procctl. > - */ > - > - if (ioctl(fd, PIOCSFL, flags) == -1) > - warn("cannot clear PF_LINGER"); > - > - return (fd); > + return (0); > } > > /* > @@ -193,10 +128,74 @@ > * process. > */ > void > -restore_proc(int signo __unused) { > +restore_proc(int signo __unused) > +{ > + int waitval; > + > + kill(child_pid, SIGSTOP); > + if (waitpid(child_pid, &waitval, 0) < -1) > + err(1, "Unexpected stop in waitpid"); > > - ioctl(Procfd, PIOCBIC, ~0); > - if (evflags) > - ioctl(Procfd, PIOCBIS, evflags); > + if (ptrace(PT_DETACH, child_pid, (caddr_t)1, 0) < 0) > + err(1, "Can not detach the process"); > + > + kill(child_pid, SIGCONT); > exit(0); > } > + > +void find_thread(struct trussinfo *info, lwpid_t lwpid) > +{ > + info->curthread = NULL; > + struct threadinfo *np; > + SLIST_FOREACH(np, &info->threadlist, entries) { > + if (np->tid == lwpid) { > + info->curthread = np; > + return; > + } > + } > + > + np = (struct threadinfo *)malloc(sizeof(struct threadinfo)); > + if (np == NULL) > + errx(1, "malloc() failed"); > + np->tid = lwpid; > + np->in_fork = 0; > + np->in_syscall = 0; > + SLIST_INSERT_HEAD(&info->threadlist, np, entries); > + info->curthread = np; > +} > + > +void waitevent(struct trussinfo *info) > +{ > + int waitval; > + > + ptrace(PT_SYSCALL, info->pid, (caddr_t)1, 0); > + > + if (waitpid(info->pid, &waitval, 0) < -1) { > + err(1, "Unexpected stop in waitpid"); > + } > + > + if (WIFCONTINUED(waitval)) { > + info->pr_why = S_NONE; > + return; > + } > + if (WIFEXITED(waitval)) { > + info->pr_why = S_EXIT; > + info->pr_data = WEXITSTATUS(waitval); > + return; > + } > + if (WIFSTOPPED(waitval) || (WIFSIGNALED(waitval))) { > + struct ptrace_lwpinfo lwpinfo; > + ptrace(PT_LWPINFO, info->pid, (caddr_t)&lwpinfo, sizeof(lwpinfo)); > + find_thread(info, lwpinfo.pl_lwpid); > + switch(WSTOPSIG(waitval)) { > + case SIGTRAP: > + info->pr_why = info->curthread->in_syscall?S_SCX:S_SCE; > + info->curthread->in_syscall = 1 - info->curthread->in_syscall; > + break; > + default: > + info->pr_why = S_SIG; > + info->pr_data = WSTOPSIG(waitval); > + break; > + } > + } > +} > ==== //depot/vendor/freebsd/src/usr.bin/truss/sparc64-fbsd.c#9 (text+ko) - //depot/user/howardsu/truss/usr.bin/truss/sparc64-fbsd.c#3 (text+ko) ==== content > @@ -45,8 +45,7 @@ > */ > > #include > -#include > -#include > +#include > #include > > #include > @@ -68,7 +67,6 @@ > #include "syscall.h" > #include "extern.h" > > -static int fd = -1; > static int cpid = -1; > > #include "syscalls.h" > @@ -118,26 +116,18 @@ > > void > sparc64_syscall_entry(struct trussinfo *trussinfo, int nargs) { > - char buf[32]; > struct reg regs; > int syscall_num; > int i; > struct syscall *sc; > int indir = 0; /* indirect system call */ > + struct ptrace_io_desc iorequest; > > - if (fd == -1 || trussinfo->pid != cpid) { > - sprintf(buf, "/proc/%d/regs", trussinfo->pid); > - fd = open(buf, O_RDWR); > - if (fd == -1) { > - fprintf(trussinfo->outfile, "-- CANNOT OPEN REGISTERS --\n"); > - return; > - } > - cpid = trussinfo->pid; > - } > + cpid = trussinfo->curthread->tid; > > clear_fsc(); > - lseek(fd, 0L, 0); > - if (read(fd, ®s, sizeof(regs)) != sizeof(regs)) { > + > + if (ptrace(PT_GETREGS, cpid, (caddr_t)®s, 0) < 0) { > fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); > return; > } > @@ -165,7 +155,7 @@ > || !strcmp(fsc.name, "rfork") > || !strcmp(fsc.name, "vfork")))) > { > - trussinfo->in_fork = 1; > + trussinfo->curthread->in_fork = 1; > } > > if (nargs == 0) > @@ -186,9 +176,14 @@ > * on the stack, as is normal for other processors. > * The fall-through for all of these is deliberate!!! > */ > - lseek(Procfd, regs.r_out[6] + SPOFF + > - offsetof(struct frame, fr_pad[6]), SEEK_SET); > - read(fd, &fsc.args[6], (nargs - 6) * sizeof(fsc.args[0])); > + iorequest.piod_op = PIOD_READ_D; > + iorequest.piod_offs = (void *)(regs.r_out[6] + SPOFF + > + offsetof(struct frame, fr_pad[6]); > + iorequest.piod_addr = &fsc.args[6]; > + iorequest.piod_len = (nargs - 6) * sizeof(fsc.args[0]); > + ptrace(PT_IO, cpid, (caddr_t)&iorequest, 0); > + if (iorequest.piod_len == 0) return; > + > case 6: fsc.args[5] = regs.r_out[5]; > case 5: fsc.args[4] = regs.r_out[4]; > case 4: fsc.args[3] = regs.r_out[3]; > @@ -240,7 +235,7 @@ > i < (fsc.nargs - 1) ? "," : ""); > #endif > if (sc && !(sc->args[i].type & OUT)) { > - fsc.s_args[i] = print_arg(Procfd, &sc->args[i], fsc.args, 0, trussinfo); > + fsc.s_args[i] = print_arg(&sc->args[i], fsc.args, 0, trussinfo); > } > } > #if DEBUG > @@ -302,18 +297,9 @@ > int errorp; > struct syscall *sc; > > - if (fd == -1 || trussinfo->pid != cpid) { > - sprintf(buf, "/proc/%d/regs", trussinfo->pid); > - fd = open(buf, O_RDONLY); > - if (fd == -1) { > - fprintf(trussinfo->outfile, "-- CANNOT OPEN REGISTERS --\n"); > - return (-1); > - } > - cpid = trussinfo->pid; > - } > + cpid = trussinfo->curthread->tid; > > - lseek(fd, 0L, 0); > - if (read(fd, ®s, sizeof(regs)) != sizeof(regs)) { > + if (ptrace(PT_GETREGS, cpid, (caddr_t)®s, 0) < 0) { > fprintf(trussinfo->outfile, "\n"); > return (-1); > } > @@ -344,7 +330,7 @@ > if (errorp) > asprintf(&temp, "0x%lx", fsc.args[sc->args[i].offset]); > else > - temp = print_arg(Procfd, &sc->args[i], fsc.args, retval, trussinfo); > + temp = print_arg(&sc->args[i], fsc.args, retval, trussinfo); > fsc.s_args[i] = temp; > } > } > ==== //depot/vendor/freebsd/src/usr.bin/truss/syscall.h#12 (text+ko) - //depot/user/howardsu/truss/usr.bin/truss/syscall.h#2 (text+ko) ==== content > @@ -61,7 +61,7 @@ > > struct syscall *get_syscall(const char*); > char *get_string(int, void*, int); > -char *print_arg(int, struct syscall_args *, unsigned long*, long, struct trussinfo *); > +char *print_arg(struct syscall_args *, unsigned long*, long, struct trussinfo *); > void print_syscall(struct trussinfo *, const char *, int, char **); > void print_syscall_ret(struct trussinfo *, const char *, int, char **, int, > long); > ==== //depot/vendor/freebsd/src/usr.bin/truss/syscalls.c#38 (text+ko) - //depot/user/howardsu/truss/usr.bin/truss/syscalls.c#2 (text+ko) ==== content > @@ -41,6 +41,7 @@ > > #include > #include > +#include > #include > #include > #include > @@ -408,9 +409,13 @@ > */ > > static int > -get_struct(int procfd, void *offset, void *buf, int len) { > - > - if (pread(procfd, buf, len, (uintptr_t)offset) != len) > +get_struct(int pid, void *offset, void *buf, int len) { > + struct ptrace_io_desc iorequest; > + iorequest.piod_op = PIOD_READ_D; > + iorequest.piod_offs = offset; > + iorequest.piod_addr = buf; > + iorequest.piod_len = len; > + if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) != len) > return -1; > return 0; > } > @@ -423,37 +428,21 @@ > */ > > char * > -get_string(int procfd, void *offset, int max) { > +get_string(int pid, void *offset, int max) { > char *buf; > - int size, len, c, fd; > - FILE *p; > + struct ptrace_io_desc iorequest; > + if (max > 1024 || max <= 0) > + max = 1024; > + > + buf = malloc(max); > + if (buf == NULL) return NULL; > + iorequest.piod_op = PIOD_READ_D; > + iorequest.piod_offs = offset; > + iorequest.piod_addr = buf; > + iorequest.piod_len = max; > + ptrace(PT_IO, pid, (caddr_t)&iorequest, 0); > + buf[max - 1] = '\0'; > > - if ((fd = dup(procfd)) == -1) > - err(1, "dup"); > - if ((p = fdopen(fd, "r")) == NULL) > - err(1, "fdopen"); > - buf = malloc( size = (max ? max + 1 : 64 ) ); > - len = 0; > - buf[0] = 0; > - if (fseeko(p, (uintptr_t)offset, SEEK_SET) == 0) { > - while ((c = fgetc(p)) != EOF) { > - buf[len++] = c; > - if (c == 0 || len == max) > - break; > - if (len == size) { > - char *tmp; > - tmp = realloc(buf, size+64); > - if (tmp == NULL) { > - buf[len] = 0; > - break; > - } > - size += 64; > - buf = tmp; > - } > - } > - buf[len] = 0; > - } > - fclose(p); > return (buf); > } > > @@ -469,9 +458,9 @@ > */ > > char * > -print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, struct trussinfo *trussinfo) { > +print_arg(struct syscall_args *sc, unsigned long *args, long retval, struct trussinfo *trussinfo) { > char *tmp = NULL; > - > + int pid = trussinfo->pid; > switch (sc->type & ARG_MASK) { > case Hex: > asprintf(&tmp, "0x%lx", args[sc->offset]); > @@ -486,7 +475,7 @@ > { > /* NULL-terminated string. */ > char *tmp2; > - tmp2 = get_string(fd, (void*)args[sc->offset], 0); > + tmp2 = get_string(pid, (void*)args[sc->offset], 0); > asprintf(&tmp, "\"%s\"", tmp2); > free(tmp2); > } > @@ -514,7 +503,7 @@ > len = max_string; > truncated = 1; > } > - if (len && get_struct(fd, (void*)args[sc->offset], &tmp2, len) != -1) { > + if (len && get_struct(pid, (void*)args[sc->offset], &tmp2, len) != -1) { > tmp3 = malloc(len * 4 + 1); > while (len) { > if (strvisx(tmp3, tmp2, len, VIS_CSTYLE|VIS_TAB|VIS_NL) <= max_string) > @@ -535,7 +524,7 @@ > char *string; > char *strarray[100]; /* XXX This is ugly. */ > > - if (get_struct(fd, (void *)args[sc->offset], (void *)&strarray, > + if (get_struct(pid, (void *)args[sc->offset], (void *)&strarray, > sizeof(strarray)) == -1) { > err(1, "get_struct %p", (void *)args[sc->offset]); > } > @@ -544,7 +533,7 @@ > > /* Find out how large of a buffer we'll need. */ > while (strarray[num] != NULL) { > - string = get_string(fd, (void*)strarray[num], 0); > + string = get_string(pid, (void*)strarray[num], 0); > size += strlen(string); > free(string); > num++; > @@ -555,7 +544,7 @@ > > tmp2 += sprintf(tmp2, " ["); > for (i = 0; i < num; i++) { > - string = get_string(fd, (void*)strarray[i], 0); > + string = get_string(pid, (void*)strarray[i], 0); > tmp2 += sprintf(tmp2, " \"%s\"%c", string, (i+1 == num) ? ' ' : ','); > free(string); > } > @@ -585,7 +574,7 @@ > tmp = strdup(""); > break; > } > - tmp2 = get_string(fd, (void*)args[sc->offset], retval); > + tmp2 = get_string(pid, (void*)args[sc->offset], retval); > asprintf(&tmp, "\"%s\"", tmp2); > free(tmp2); > } > @@ -608,7 +597,7 @@ > case Umtx: > { > struct umtx umtx; > - if (get_struct(fd, (void *)args[sc->offset], &umtx, sizeof(umtx)) != -1) > + if (get_struct(pid, (void *)args[sc->offset], &umtx, sizeof(umtx)) != -1) > asprintf(&tmp, "{0x%lx}", (long)umtx.u_owner); > else > asprintf(&tmp, "0x%lx", args[sc->offset]); > @@ -617,7 +606,7 @@ > case Timespec: > { > struct timespec ts; > - if (get_struct(fd, (void *)args[sc->offset], &ts, sizeof(ts)) != -1) > + if (get_struct(pid, (void *)args[sc->offset], &ts, sizeof(ts)) != -1) > asprintf(&tmp, "{%ld.%09ld}", (long)ts.tv_sec, ts.tv_nsec); > else > asprintf(&tmp, "0x%lx", args[sc->offset]); > @@ -626,7 +615,7 @@ > case Timeval: > { > struct timeval tv; > - if (get_struct(fd, (void *)args[sc->offset], &tv, sizeof(tv)) != -1) > + if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv)) != -1) > asprintf(&tmp, "{%ld.%06ld}", (long)tv.tv_sec, tv.tv_usec); > else > asprintf(&tmp, "0x%lx", args[sc->offset]); > @@ -635,7 +624,7 @@ > case Timeval2: > { > struct timeval tv[2]; > - if (get_struct(fd, (void *)args[sc->offset], &tv, sizeof(tv)) != -1) > + if (get_struct(pid, (void *)args[sc->offset], &tv, sizeof(tv)) != -1) > asprintf(&tmp, "{%ld.%06ld, %ld.%06ld}", > (long)tv[0].tv_sec, tv[0].tv_usec, > (long)tv[1].tv_sec, tv[1].tv_usec); > @@ -646,7 +635,7 @@ > case Itimerval: > { > struct itimerval itv; > - if (get_struct(fd, (void *)args[sc->offset], &itv, sizeof(itv)) != -1) > + if (get_struct(pid, (void *)args[sc->offset], &itv, sizeof(itv)) != -1) > asprintf(&tmp, "{%ld.%06ld, %ld.%06ld}", > (long)itv.it_interval.tv_sec, > itv.it_interval.tv_usec, > @@ -670,7 +659,7 @@ > > if ((pfd = malloc(bytes)) == NULL) > err(1, "Cannot malloc %d bytes for pollfd array", bytes); > - if (get_struct(fd, (void *)args[sc->offset], pfd, bytes) != -1) { > + if (get_struct(pid, (void *)args[sc->offset], pfd, bytes) != -1) { > > used = 0; > tmpsize = 1 + per_fd * numfds + 2; > @@ -709,7 +698,7 @@ > > if ((fds = malloc(bytes)) == NULL) > err(1, "Cannot malloc %d bytes for fd_set array", bytes); > - if (get_struct(fd, (void *)args[sc->offset], fds, bytes) != -1) { > + if (get_struct(pid, (void *)args[sc->offset], fds, bytes) != -1) { > used = 0; > tmpsize = 1 + numfds * per_fd + 2; > if ((tmp = malloc(tmpsize)) == NULL) > @@ -749,7 +738,7 @@ > int i, used; > > sig = args[sc->offset]; > - if (get_struct(fd, (void *)args[sc->offset], (void *)&ss, > + if (get_struct(pid, (void *)args[sc->offset], (void *)&ss, > sizeof(ss)) == -1) > { > asprintf(&tmp, "0x%lx", args[sc->offset]); > @@ -853,7 +842,7 @@ > } > > /* yuck: get ss_len */ > - if (get_struct(fd, (void *)args[sc->offset], (void *)&ss, > + if (get_struct(pid, (void *)args[sc->offset], (void *)&ss, > sizeof(ss.ss_len) + sizeof(ss.ss_family)) == -1) > err(1, "get_struct %p", (void *)args[sc->offset]); > /* > @@ -874,7 +863,7 @@ > break; > } > } > - if (get_struct(fd, (void *)args[sc->offset], (void *)&ss, ss.ss_len) > + if (get_struct(pid, (void *)args[sc->offset], (void *)&ss, ss.ss_len) > == -1) { > err(2, "get_struct %p", (void *)args[sc->offset]); > } > @@ -913,7 +902,7 @@ > char *hand; > const char *h; > > - if (get_struct(fd, (void *)args[sc->offset], &sa, sizeof(sa)) != -1) { > + if (get_struct(pid, (void *)args[sc->offset], &sa, sizeof(sa)) != -1) { > > asprintf(&hand, "%p", sa.sa_handler); > if (sa.sa_handler == SIG_DFL) > @@ -956,7 +945,7 @@ > bytes = sizeof(struct kevent) * numevents; > if ((ke = malloc(bytes)) == NULL) > err(1, "Cannot malloc %d bytes for kevent array", bytes); > - if (numevents >= 0 && get_struct(fd, (void *)args[sc->offset], ke, bytes) != -1) { > + if (numevents >= 0 && get_struct(pid, (void *)args[sc->offset], ke, bytes) != -1) { > used = 0; > tmpsize = 1 + per_ke * numevents + 2; > if ((tmp = malloc(tmpsize)) == NULL) > @@ -986,7 +975,7 @@ > case Stat: > { > struct stat st; > - if (get_struct(fd, (void *)args[sc->offset], &st, sizeof(st)) != -1) { > + if (get_struct(pid, (void *)args[sc->offset], &st, sizeof(st)) != -1) { > char mode[12]; > strmode(st.st_mode, mode); > asprintf(&tmp, "{mode=%s,inode=%jd,size=%jd,blksize=%ld}", > @@ -999,7 +988,7 @@ > case Rusage: > { > struct rusage ru; > - if (get_struct(fd, (void *)args[sc->offset], &ru, sizeof(ru)) != -1) > + if (get_struct(pid, (void *)args[sc->offset], &ru, sizeof(ru)) != -1) > asprintf(&tmp, "{u=%ld.%06ld,s=%ld.%06ld,in=%ld,out=%ld}", > (long)ru.ru_utime.tv_sec, ru.ru_utime.tv_usec, > (long)ru.ru_stime.tv_sec, ru.ru_stime.tv_usec, > @@ -1011,7 +1000,7 @@ > case Rlimit: > { > struct rlimit rl; > - if (get_struct(fd, (void *)args[sc->offset], &rl, sizeof(rl)) != -1) > + if (get_struct(pid, (void *)args[sc->offset], &rl, sizeof(rl)) != -1) > asprintf(&tmp, "{cur=%ju,max=%ju}", > rl.rlim_cur, rl.rlim_max); > else > ==== //depot/vendor/freebsd/src/usr.bin/truss/truss.1#12 (text+ko) - //depot/user/howardsu/truss/usr.bin/truss/truss.1#3 (text+ko) ==== content > @@ -23,7 +23,7 @@ > utility traces the system calls called by the specified process or program. > Output is to the specified output file, or standard error by default. > It does this by stopping and restarting the process being monitored via > -.Xr procfs 5 . > +.Xr ptrace 2 . > .Pp > The options are as follows: > .Bl -tag -width indent > @@ -79,13 +79,6 @@ > .Ar command > options are mutually exclusive.) > .El > -.Pp > -The > -.Xr procctl 8 > -utility can be used to clear tracepoints in a stuck process > -left behind if > -.Nm > -terminates abnormally. > .Sh EXAMPLES > # Follow the system calls used in echoing "hello" > .Dl $ truss /bin/echo hello > @@ -96,8 +89,7 @@ > .Sh SEE ALSO > .Xr kdump 1 , > .Xr ktrace 1 , > -.Xr procfs 5 , > -.Xr procctl 8 > +.Xr ptrace 2 2 > .Sh HISTORY > The > .Nm > ==== //depot/vendor/freebsd/src/usr.bin/truss/truss.h#5 (text+ko) - //depot/user/howardsu/truss/usr.bin/truss/truss.h#4 (text+ko) ==== content > @@ -25,6 +25,8 @@ > * $FreeBSD: src/usr.bin/truss/truss.h,v 1.7 2006/05/15 21:18:28 pav Exp $ > */ > > +#include > + > #define FOLLOWFORKS 0x00000001 > #define RELATIVETIMESTAMPS 0x00000002 > #define ABSOLUTETIMESTAMPS 0x00000004 > @@ -32,17 +34,30 @@ > #define EXECVEARGS 0x00000010 > #define EXECVEENVS 0x00000020 > > +struct threadinfo > +{ > + SLIST_ENTRY(threadinfo) entries; > + lwpid_t tid; > + int in_syscall; > + int in_fork; > +}; > + > struct trussinfo > { > int pid; > int flags; > - int in_fork; > + int pr_why; > + int pr_data; > int strsize; > FILE *outfile; > > struct timespec start_time; > struct timespec before; > struct timespec after; > + > + struct threadinfo *curthread; > + > + SLIST_HEAD(, threadinfo) threadlist; > }; > > #define timespecsubt(tvp, uvp, vvp) \ > @@ -54,3 +69,10 @@ > (vvp)->tv_nsec += 1000000000; \ > } \ > } while (0) > + > +#define S_NONE 0 > +#define S_SCE 1 > +#define S_SCX 2 > +#define S_EXIT 3 > +#define S_SIG 4 > +#define S_EXEC 5 -- - Alfred Perlstein