Re: [Review] Remove procfs dependency of truss

From: Alfred Perlstein <alfred_at_freebsd.org>
Date: Fri, 6 Apr 2007 05:59:40 -0700
* Howard Su <howard0su_at_gmail.com> [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 <howard0su_at_gmail.com> 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 <pid_of_top>
> >
> >--
> >-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
> _at__at_ -43,8 +43,7 _at__at_
>   */
>  
>  #include <sys/types.h>
> -#include <sys/ioctl.h>
> -#include <sys/pioctl.h>
> +#include <sys/ptrace.h>
>  #include <sys/syscall.h>
>  
>  #include <machine/reg.h>
> _at__at_ -63,7 +62,6 _at__at_
>  #include "syscall.h"
>  #include "extern.h"
>  
> -static int fd = -1;
>  static int cpid = -1;
>  
>  #include "syscalls.h"
> _at__at_ -113,25 +111,16 _at__at_
>  
>  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, &regs, sizeof(regs)) != sizeof(regs)) {
> +  if (ptrace(PT_GETREGS, cpid, (caddr_t)&regs, 0) < 0)
> +  {
>      fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
>      return;
>    }
> _at__at_ -163,7 +152,7 _at__at_
>      || !strcmp(fsc.name, "rfork")
>      || !strcmp(fsc.name, "vfork"))))
>    {
> -    trussinfo->in_fork = 1;
> +    trussinfo->curthread->in_fork = 1;
>    }
>  
>    if (nargs == 0)
> _at__at_ -181,8 +170,13 _at__at_
>      }
>    }
>    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;
>    }
>  
> _at__at_ -223,7 +217,7 _at__at_
>  	      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
> _at__at_ -279,25 +273,16 _at__at_
>  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, &regs, sizeof(regs)) != sizeof(regs)) {
> +  if (ptrace(PT_GETREGS, cpid, (caddr_t)&regs, 0) < 0)
> +  {
>      fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
>      return (-1);
>    }
> _at__at_ -328,7 +313,7 _at__at_
>  	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
> _at__at_ -32,8 +32,9 _at__at_
>   */
>  
>  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__
> _at__at_ -63,4 +64,3 _at__at_
>  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
> _at__at_ -43,9 +43,8 _at__at_
>   */
>  
>  #include <sys/types.h>
> -#include <sys/ioctl.h>
> -#include <sys/pioctl.h>
>  #include <sys/syscall.h>
> +#include <sys/ptrace.h>
>  
>  #include <machine/reg.h>
>  #include <machine/psl.h>
> _at__at_ -63,7 +62,6 _at__at_
>  #include "syscall.h"
>  #include "extern.h"
>  
> -static int fd = -1;
>  static int cpid = -1;
>  
>  #include "syscalls.h"
> _at__at_ -113,26 +111,18 _at__at_
>  
>  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, &regs, sizeof(regs)) != sizeof(regs)) {
> +  
> +  if (ptrace(PT_GETREGS, cpid, (caddr_t)&regs, 0) < 0)
> +  {
>      fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
>      return;
>    }
> _at__at_ -146,13 +136,11 _at__at_
>    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;
>    }
> _at__at_ -169,15 +157,19 _at__at_
>      || !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)
> _at__at_ -218,7 +210,7 _at__at_
>  	      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
> _at__at_ -274,28 +266,20 _at__at_
>  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, &regs, sizeof(regs)) != sizeof(regs)) {
> +  if (ptrace(PT_GETREGS, cpid, (caddr_t)&regs, 0) < 0)
> +  {
>      fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
>      return (-1);
>    }
> +  
>    retval = regs.r_eax;
>    errorp = !!(regs.r_eflags & PSL_C);
>  
> _at__at_ -323,7 +307,7 _at__at_
>  	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
> _at__at_ -41,8 +41,7 _at__at_
>   */
>  
>  #include <sys/types.h>
> -#include <sys/ioctl.h>
> -#include <sys/pioctl.h>
> +#include <sys/ptrace.h>
>  
>  #include <machine/reg.h>
>  #include <machine/psl.h>
> _at__at_ -60,7 +59,6 _at__at_
>  #include "syscall.h"
>  #include "extern.h"
>  
> -static int fd = -1;
>  static int cpid = -1;
>  
>  #include "linux_syscalls.h"
> _at__at_ -108,28 +106,20 _at__at_
>  
>  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, &regs, sizeof(regs)) != sizeof(regs)) {
> +  
> +  if (ptrace(PT_GETREGS, cpid, (caddr_t)&regs, 0) < 0)
> +  {
>      fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
>      return;
> -  }
> +  } 
>    syscall_num = regs.r_eax;
>  
>    fsc.number = syscall_num;
> _at__at_ -143,7 +133,7 _at__at_
>     && ((!strcmp(fsc.name, "linux_fork")
>      || !strcmp(fsc.name, "linux_vfork"))))
>    {
> -    trussinfo->in_fork = 1;
> +    trussinfo->curthread->in_fork = 1;
>    }
>  
>    if (nargs == 0)
> _at__at_ -200,7 +190,7 _at__at_
>  	      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
> _at__at_ -264,28 +254,19 _at__at_
>  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)&regs, 0) < 0)
> +  {
> +    fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
> +    return (-1);
>    }
>  
> -  lseek(fd, 0L, 0);
> -  if (read(fd, &regs, sizeof(regs)) != sizeof(regs)) {
> -    fprintf(trussinfo->outfile, "\n");
> -    return (-1);
> -  }
>    retval = regs.r_eax;
>    errorp = !!(regs.r_eflags & PSL_C);
>  
> _at__at_ -313,7 +294,7 _at__at_
>  	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
> _at__at_ -43,8 +43,7 _at__at_
>   */
>  
>  #include <sys/types.h>
> -#include <sys/ioctl.h>
> -#include <sys/pioctl.h>
> +#include <sys/ptrace.h>
>  #include <sys/syscall.h>
>  
>  #include <machine/reg.h>
> _at__at_ -62,7 +61,6 _at__at_
>  #include "syscall.h"
>  #include "extern.h"
>  
> -static int fd = -1;
>  static int cpid = -1;
>  
>  #include "syscalls.h"
> _at__at_ -112,26 +110,16 _at__at_
>  
>  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, &regs, sizeof(regs)) != sizeof(regs)) {
> +  if (ptrace(PT_GETREGS, cpid, (caddr_t)&regs, 0) < 0) {
>      fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
>      return;
>    }
> _at__at_ -158,7 +146,7 _at__at_
>      || !strcmp(fsc.name, "rfork")
>      || !strcmp(fsc.name, "vfork"))))
>    {
> -    trussinfo->in_fork = 1;
> +    trussinfo->curthread->in_fork = 1;
>    }
>  
>    if (nargs == 0)
> _at__at_ -204,7 +192,7 _at__at_
>  	      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
> _at__at_ -260,25 +248,15 _at__at_
>  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, &regs, sizeof(regs)) != sizeof(regs)) {
> +  if (ptrace(PT_GETREGS, cpid, (caddr_t)&regs, 0) < 0) {
>      fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
>      return (-1);
>    }
> _at__at_ -309,7 +287,7 _at__at_
>  	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
> _at__at_ -39,11 +39,10 _at__at_
>   */
>  
>  #include <sys/param.h>
> -#include <sys/ioctl.h>
> -#include <sys/pioctl.h>
>  #include <sys/types.h>
>  #include <sys/time.h>
>  #include <sys/resource.h>
> +#include <sys/sysctl.h>
>  
>  #include <ctype.h>
>  #include <err.h>
> _at__at_ -59,13 +58,8 _at__at_
>  #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)
>  {
> _at__at_ -119,18 +113,19 _at__at_
>  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))
> _at__at_ -167,14 +162,12 _at__at_
>  	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;
> _at__at_ -184,9 +177,12 _at__at_
>  	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 */
> _at__at_ -245,6 +241,7 _at__at_
>  		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);
> _at__at_ -257,18 +254,9 _at__at_
>  	 */
>  
>  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.
> _at__at_ -278,118 +266,92 _at__at_
>  	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;
> _at__at_ -400,5 +362,6 _at__at_
>  		(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
> _at__at_ -41,8 +41,7 _at__at_
>   */
>  
>  #include <sys/types.h>
> -#include <sys/ioctl.h>
> -#include <sys/pioctl.h>
> +#include <sys/ptrace.h>
>  #include <sys/syscall.h>
>  
>  #include <machine/reg.h>
> _at__at_ -62,7 +61,6 _at__at_
>  #include "syscall.h"
>  #include "extern.h"
>  
> -static int fd = -1;
>  static int cpid = -1;
>  
>  #include "syscalls.h"
> _at__at_ -120,19 +118,10 _at__at_
>    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, &regs, sizeof(regs)) != sizeof(regs)) {
> +  if (ptrace(PT_GETREGS, cpid, (caddr_t)&regs, 0) < 0) {
>      fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
>      return;
>    }
> _at__at_ -167,7 +156,7 _at__at_
>      || !strcmp(fsc.name, "rfork")
>      || !strcmp(fsc.name, "vfork"))))
>    {
> -    trussinfo->in_fork = 1;
> +    trussinfo->curthread->in_fork = 1;
>    }
>  
>    if (nargs == 0)
> _at__at_ -176,9 +165,16 _at__at_
>    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]));
>    }
> _at__at_ -220,7 +216,7 _at__at_
>  	      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
> _at__at_ -275,25 +271,15 _at__at_
>  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, &regs, sizeof(regs)) != sizeof(regs)) {
> +  if (ptrace(PT_GETREGS, cpid, (caddr_t)&regs, 0) < 0) {
>      fprintf(trussinfo->outfile, "\n");
>      return (-1);
>    }
> _at__at_ -332,7 +318,7 _at__at_
>  	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
> _at__at_ -38,11 +38,12 _at__at_
>   */
>  
>  #include <sys/param.h>
> -#include <sys/ioctl.h>
> -#include <sys/pioctl.h>
> +#include <sys/types.h>
> +#include <sys/ptrace.h>
>  #include <sys/wait.h>
>  
>  #include <err.h>
> +#include <errno.h>
>  #include <fcntl.h>
>  #include <signal.h>
>  #include <stdio.h>
> _at__at_ -51,10 +52,12 _at__at_
>  #include <time.h>
>  #include <unistd.h>
>  
> +#include <machine/reg.h>
> +
>  #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
> _at__at_ -66,75 +69,28 _at__at_
>  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);
>  }
>  
> _at__at_ -145,45 +101,24 _at__at_
>   */
>  
>  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);
>  }
>  
>  /*
> _at__at_ -193,10 +128,74 _at__at_
>   * 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
> _at__at_ -45,8 +45,7 _at__at_
>   */
>  
>  #include <sys/types.h>
> -#include <sys/ioctl.h>
> -#include <sys/pioctl.h>
> +#include <sys/ptrace.h>
>  #include <sys/syscall.h>
>  
>  #include <machine/frame.h>
> _at__at_ -68,7 +67,6 _at__at_
>  #include "syscall.h"
>  #include "extern.h"
>  
> -static int fd = -1;
>  static int cpid = -1;
>  
>  #include "syscalls.h"
> _at__at_ -118,26 +116,18 _at__at_
>  
>  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, &regs, sizeof(regs)) != sizeof(regs)) {
> +  
> +  if (ptrace(PT_GETREGS, cpid, (caddr_t)&regs, 0) < 0) {
>      fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
>      return;
>    }
> _at__at_ -165,7 +155,7 _at__at_
>      || !strcmp(fsc.name, "rfork")
>      || !strcmp(fsc.name, "vfork"))))
>    {
> -    trussinfo->in_fork = 1;
> +    trussinfo->curthread->in_fork = 1;
>    }
>  
>    if (nargs == 0)
> _at__at_ -186,9 +176,14 _at__at_
>  	 * 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];
> _at__at_ -240,7 +235,7 _at__at_
>  	      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
> _at__at_ -302,18 +297,9 _at__at_
>    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, &regs, sizeof(regs)) != sizeof(regs)) {
> +  if (ptrace(PT_GETREGS, cpid, (caddr_t)&regs, 0) < 0) {
>      fprintf(trussinfo->outfile, "\n");
>      return (-1);
>    }
> _at__at_ -344,7 +330,7 _at__at_
>  	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
> _at__at_ -61,7 +61,7 _at__at_
>  
>  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
> _at__at_ -41,6 +41,7 _at__at_
>  
>  #include <sys/mman.h>
>  #include <sys/types.h>
> +#include <sys/ptrace.h>
>  #include <sys/socket.h>
>  #include <sys/time.h>
>  #include <sys/un.h>
> _at__at_ -408,9 +409,13 _at__at_
>   */
>  
>  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;
>  }
> _at__at_ -423,37 +428,21 _at__at_
>   */
>  
>  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);
>  }
>  
> _at__at_ -469,9 +458,9 _at__at_
>   */
>  
>  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]);
> _at__at_ -486,7 +475,7 _at__at_
>      {
>        /* 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);
>      }
> _at__at_ -514,7 +503,7 _at__at_
>          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)
> _at__at_ -535,7 +524,7 _at__at_
>        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]);
>        }
> _at__at_ -544,7 +533,7 _at__at_
>  
>        /* 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++;
> _at__at_ -555,7 +544,7 _at__at_
>  
>        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);
>        }
> _at__at_ -585,7 +574,7 _at__at_
>  	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);
>      }
> _at__at_ -608,7 +597,7 _at__at_
>    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]);
> _at__at_ -617,7 +606,7 _at__at_
>    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]);
> _at__at_ -626,7 +615,7 _at__at_
>    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]);
> _at__at_ -635,7 +624,7 _at__at_
>    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);
> _at__at_ -646,7 +635,7 _at__at_
>    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,
> _at__at_ -670,7 +659,7 _at__at_
>  
>        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;
> _at__at_ -709,7 +698,7 _at__at_
>  
>        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)
> _at__at_ -749,7 +738,7 _at__at_
>        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]);
> _at__at_ -853,7 +842,7 _at__at_
>        }
>  
>        /* 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]);
>        /*
> _at__at_ -874,7 +863,7 _at__at_
>  		      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]);
>        }
> _at__at_ -913,7 +902,7 _at__at_
>        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)
> _at__at_ -956,7 +945,7 _at__at_
>        	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)
> _at__at_ -986,7 +975,7 _at__at_
>    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}",
> _at__at_ -999,7 +988,7 _at__at_
>    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,
> _at__at_ -1011,7 +1000,7 _at__at_
>    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
> _at__at_ -23,7 +23,7 _at__at_
>  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
> _at__at_ -79,13 +79,6 _at__at_
>  .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
> _at__at_ -96,8 +89,7 _at__at_
>  .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
> _at__at_ -25,6 +25,8 _at__at_
>   * $FreeBSD: src/usr.bin/truss/truss.h,v 1.7 2006/05/15 21:18:28 pav Exp $
>   */
>  
> +#include <sys/queue.h>
> +
>  #define FOLLOWFORKS        0x00000001
>  #define RELATIVETIMESTAMPS 0x00000002
>  #define ABSOLUTETIMESTAMPS 0x00000004
> _at__at_ -32,17 +34,30 _at__at_
>  #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)					\
> _at__at_ -54,3 +69,10 _at__at_
>  			(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
Received on Fri Apr 06 2007 - 10:59:40 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:39:07 UTC