[Review] Remove procfs dependency of truss
Alfred Perlstein
alfred at freebsd.org
Fri Apr 6 12:59:40 UTC 2007
* 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
> @@ -43,8 +43,7 @@
> */
>
> #include <sys/types.h>
> -#include <sys/ioctl.h>
> -#include <sys/pioctl.h>
> +#include <sys/ptrace.h>
> #include <sys/syscall.h>
>
> #include <machine/reg.h>
> @@ -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 <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>
> @@ -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 <sys/types.h>
> -#include <sys/ioctl.h>
> -#include <sys/pioctl.h>
> +#include <sys/ptrace.h>
>
> #include <machine/reg.h>
> #include <machine/psl.h>
> @@ -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 <sys/types.h>
> -#include <sys/ioctl.h>
> -#include <sys/pioctl.h>
> +#include <sys/ptrace.h>
> #include <sys/syscall.h>
>
> #include <machine/reg.h>
> @@ -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 <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>
> @@ -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 <sys/types.h>
> -#include <sys/ioctl.h>
> -#include <sys/pioctl.h>
> +#include <sys/ptrace.h>
> #include <sys/syscall.h>
>
> #include <machine/reg.h>
> @@ -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 <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>
> @@ -51,10 +52,12 @@
> #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
> @@ -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 <sys/types.h>
> -#include <sys/ioctl.h>
> -#include <sys/pioctl.h>
> +#include <sys/ptrace.h>
> #include <sys/syscall.h>
>
> #include <machine/frame.h>
> @@ -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 <sys/mman.h>
> #include <sys/types.h>
> +#include <sys/ptrace.h>
> #include <sys/socket.h>
> #include <sys/time.h>
> #include <sys/un.h>
> @@ -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 <sys/queue.h>
> +
> #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
More information about the freebsd-current
mailing list