Make use of ptrace(2) instead of procfs in truss(1), eliminating

yet another need of an available /proc/ mount.

Tested with:	make universe
Submitted by:	howardsu
Reviewed by:	alfred
This commit is contained in:
Xin LI 2007-04-10 04:03:34 +00:00
parent 68bca8a5e3
commit 5d2d083c92
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=168569
16 changed files with 448 additions and 581 deletions

View File

@ -1,6 +1,6 @@
# $FreeBSD$ # $FreeBSD$
WARNS?= 2 WARNS?= 6
NO_WERROR= NO_WERROR=
PROG= truss PROG= truss
SRCS= main.c setup.c syscalls.c syscalls.h ioctl.c ${MACHINE_ARCH}-fbsd.c SRCS= main.c setup.c syscalls.c syscalls.h ioctl.c ${MACHINE_ARCH}-fbsd.c

View File

@ -43,8 +43,7 @@ static const char rcsid[] =
*/ */
#include <sys/types.h> #include <sys/types.h>
#include <sys/ioctl.h> #include <sys/ptrace.h>
#include <sys/pioctl.h>
#include <sys/syscall.h> #include <sys/syscall.h>
#include <machine/reg.h> #include <machine/reg.h>
@ -63,7 +62,6 @@ static const char rcsid[] =
#include "syscall.h" #include "syscall.h"
#include "extern.h" #include "extern.h"
static int fd = -1;
static int cpid = -1; static int cpid = -1;
#include "syscalls.h" #include "syscalls.h"
@ -113,25 +111,16 @@ clear_fsc(void) {
void void
amd64_syscall_entry(struct trussinfo *trussinfo, int nargs) { amd64_syscall_entry(struct trussinfo *trussinfo, int nargs) {
char buf[32];
struct reg regs; struct reg regs;
int syscall_num; int syscall_num;
int i, reg; int i, reg;
struct syscall *sc; struct syscall *sc;
if (fd == -1 || trussinfo->pid != cpid) { cpid = trussinfo->curthread->tid;
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(); clear_fsc();
lseek(fd, 0L, 0); if (ptrace(PT_GETREGS, cpid, (caddr_t)&regs, 0) < 0)
if (read(fd, &regs, sizeof(regs)) != sizeof(regs)) { {
fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
return; return;
} }
@ -163,7 +152,7 @@ amd64_syscall_entry(struct trussinfo *trussinfo, int nargs) {
|| !strcmp(fsc.name, "rfork") || !strcmp(fsc.name, "rfork")
|| !strcmp(fsc.name, "vfork")))) || !strcmp(fsc.name, "vfork"))))
{ {
trussinfo->in_fork = 1; trussinfo->curthread->in_fork = 1;
} }
if (nargs == 0) if (nargs == 0)
@ -181,8 +170,13 @@ amd64_syscall_entry(struct trussinfo *trussinfo, int nargs) {
} }
} }
if (nargs > i) { if (nargs > i) {
lseek(Procfd, regs.r_rsp + sizeof(register_t), SEEK_SET); struct ptrace_io_desc iorequest;
if (read(Procfd, &fsc.args[i], (nargs-i) * sizeof(register_t)) == -1) 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; return;
} }
@ -223,7 +217,7 @@ amd64_syscall_entry(struct trussinfo *trussinfo, int nargs) {
i < (fsc.nargs - 1) ? "," : ""); i < (fsc.nargs - 1) ? "," : "");
#endif #endif
if (sc && !(sc->args[i].type & OUT)) { 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 #if DEBUG
@ -279,25 +273,16 @@ amd64_syscall_entry(struct trussinfo *trussinfo, int nargs) {
long long
amd64_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused) amd64_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused)
{ {
char buf[32];
struct reg regs; struct reg regs;
long retval; long retval;
int i; int i;
int errorp; int errorp;
struct syscall *sc; struct syscall *sc;
if (fd == -1 || trussinfo->pid != cpid) { cpid = trussinfo->curthread->tid;
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;
}
lseek(fd, 0L, 0); if (ptrace(PT_GETREGS, cpid, (caddr_t)&regs, 0) < 0)
if (read(fd, &regs, sizeof(regs)) != sizeof(regs)) { {
fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
return (-1); return (-1);
} }
@ -328,7 +313,7 @@ amd64_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused)
if (errorp) if (errorp)
asprintf(&temp, "0x%lx", fsc.args[sc->args[i].offset]); asprintf(&temp, "0x%lx", fsc.args[sc->args[i].offset]);
else 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; fsc.s_args[i] = temp;
} }
} }

View File

@ -43,9 +43,8 @@ static const char rcsid[] =
*/ */
#include <sys/types.h> #include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/pioctl.h>
#include <sys/syscall.h> #include <sys/syscall.h>
#include <sys/ptrace.h>
#include <machine/reg.h> #include <machine/reg.h>
#include <machine/psl.h> #include <machine/psl.h>
@ -63,7 +62,6 @@ static const char rcsid[] =
#include "syscall.h" #include "syscall.h"
#include "extern.h" #include "extern.h"
static int fd = -1;
static int cpid = -1; static int cpid = -1;
#include "syscalls.h" #include "syscalls.h"
@ -113,26 +111,18 @@ clear_fsc(void) {
void void
i386_syscall_entry(struct trussinfo *trussinfo, int nargs) { i386_syscall_entry(struct trussinfo *trussinfo, int nargs) {
char buf[32];
struct reg regs; struct reg regs;
int syscall_num; int syscall_num;
int i; int i;
unsigned int parm_offset; unsigned int parm_offset;
struct syscall *sc = NULL; struct syscall *sc = NULL;
struct ptrace_io_desc iorequest;
if (fd == -1 || trussinfo->pid != cpid) { cpid = trussinfo->curthread->tid;
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(); 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"); fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
return; return;
} }
@ -146,13 +136,11 @@ i386_syscall_entry(struct trussinfo *trussinfo, int nargs) {
syscall_num = regs.r_eax; syscall_num = regs.r_eax;
switch (syscall_num) { switch (syscall_num) {
case SYS_syscall: case SYS_syscall:
lseek(Procfd, parm_offset, SEEK_SET); syscall_num = ptrace(PT_READ_D, cpid, (caddr_t)parm_offset, 0);
read(Procfd, &syscall_num, sizeof(int));
parm_offset += sizeof(int); parm_offset += sizeof(int);
break; break;
case SYS___syscall: case SYS___syscall:
lseek(Procfd, parm_offset, SEEK_SET); syscall_num = ptrace(PT_READ_D, cpid, (caddr_t)parm_offset, 0);
read(Procfd, &syscall_num, sizeof(int));
parm_offset += sizeof(quad_t); parm_offset += sizeof(quad_t);
break; break;
} }
@ -169,15 +157,19 @@ i386_syscall_entry(struct trussinfo *trussinfo, int nargs) {
|| !strcmp(fsc.name, "rfork") || !strcmp(fsc.name, "rfork")
|| !strcmp(fsc.name, "vfork")))) || !strcmp(fsc.name, "vfork"))))
{ {
trussinfo->in_fork = 1; trussinfo->curthread->in_fork = 1;
} }
if (nargs == 0) if (nargs == 0)
return; return;
fsc.args = malloc((1+nargs) * sizeof(unsigned long)); fsc.args = malloc((1+nargs) * sizeof(unsigned long));
lseek(Procfd, parm_offset, SEEK_SET); iorequest.piod_op = PIOD_READ_D;
if (read(Procfd, fsc.args, nargs * sizeof(unsigned long)) == -1) 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; return;
if (fsc.name) if (fsc.name)
@ -218,7 +210,7 @@ i386_syscall_entry(struct trussinfo *trussinfo, int nargs) {
i < (fsc.nargs - 1) ? "," : ""); i < (fsc.nargs - 1) ? "," : "");
#endif #endif
if (sc && !(sc->args[i].type & OUT)) { 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 #if DEBUG
@ -274,28 +266,20 @@ i386_syscall_entry(struct trussinfo *trussinfo, int nargs) {
long long
i386_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused) i386_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused)
{ {
char buf[32];
struct reg regs; struct reg regs;
long retval; long retval;
int i; int i;
int errorp; int errorp;
struct syscall *sc; struct syscall *sc;
if (fd == -1 || trussinfo->pid != cpid) { cpid = trussinfo->curthread->tid;
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;
}
lseek(fd, 0L, 0); if (ptrace(PT_GETREGS, cpid, (caddr_t)&regs, 0) < 0)
if (read(fd, &regs, sizeof(regs)) != sizeof(regs)) { {
fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
return (-1); return (-1);
} }
retval = regs.r_eax; retval = regs.r_eax;
errorp = !!(regs.r_eflags & PSL_C); errorp = !!(regs.r_eflags & PSL_C);
@ -323,7 +307,7 @@ i386_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused)
if (errorp) if (errorp)
asprintf(&temp, "0x%lx", fsc.args[sc->args[i].offset]); asprintf(&temp, "0x%lx", fsc.args[sc->args[i].offset]);
else 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; fsc.s_args[i] = temp;
} }
} }

View File

@ -41,8 +41,7 @@ static const char rcsid[] =
*/ */
#include <sys/types.h> #include <sys/types.h>
#include <sys/ioctl.h> #include <sys/ptrace.h>
#include <sys/pioctl.h>
#include <machine/reg.h> #include <machine/reg.h>
#include <machine/psl.h> #include <machine/psl.h>
@ -60,7 +59,6 @@ static const char rcsid[] =
#include "syscall.h" #include "syscall.h"
#include "extern.h" #include "extern.h"
static int fd = -1;
static int cpid = -1; static int cpid = -1;
#include "linux_syscalls.h" #include "linux_syscalls.h"
@ -108,28 +106,20 @@ clear_fsc(void) {
void void
i386_linux_syscall_entry(struct trussinfo *trussinfo, int nargs) { i386_linux_syscall_entry(struct trussinfo *trussinfo, int nargs) {
char buf[32];
struct reg regs; struct reg regs;
int syscall_num; int syscall_num;
int i; int i;
struct syscall *sc; struct syscall *sc;
if (fd == -1 || trussinfo->pid != cpid) { cpid = trussinfo->curthread->tid;
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(); 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"); fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
return; return;
} }
syscall_num = regs.r_eax; syscall_num = regs.r_eax;
fsc.number = syscall_num; fsc.number = syscall_num;
@ -143,7 +133,7 @@ i386_linux_syscall_entry(struct trussinfo *trussinfo, int nargs) {
&& ((!strcmp(fsc.name, "linux_fork") && ((!strcmp(fsc.name, "linux_fork")
|| !strcmp(fsc.name, "linux_vfork")))) || !strcmp(fsc.name, "linux_vfork"))))
{ {
trussinfo->in_fork = 1; trussinfo->curthread->in_fork = 1;
} }
if (nargs == 0) if (nargs == 0)
@ -200,7 +190,7 @@ i386_linux_syscall_entry(struct trussinfo *trussinfo, int nargs) {
i < (fsc.nargs - 1) ? "," : ""); i < (fsc.nargs - 1) ? "," : "");
#endif #endif
if (sc && !(sc->args[i].type & OUT)) { 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 #if DEBUG
@ -264,28 +254,19 @@ const int bsd_to_linux_errno[] = {
long long
i386_linux_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused) i386_linux_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused)
{ {
char buf[32];
struct reg regs; struct reg regs;
long retval; long retval;
int i; int i;
int errorp; int errorp;
struct syscall *sc; struct syscall *sc;
if (fd == -1 || trussinfo->pid != cpid) { cpid = trussinfo->curthread->tid;
sprintf(buf, "/proc/%d/regs", trussinfo->pid); if (ptrace(PT_GETREGS, cpid, (caddr_t)&regs, 0) < 0)
fd = open(buf, O_RDONLY); {
if (fd == -1) { fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
fprintf(trussinfo->outfile, "-- CANNOT OPEN REGISTERS --\n");
return (-1);
}
cpid = trussinfo->pid;
}
lseek(fd, 0L, 0);
if (read(fd, &regs, sizeof(regs)) != sizeof(regs)) {
fprintf(trussinfo->outfile, "\n");
return (-1); return (-1);
} }
retval = regs.r_eax; retval = regs.r_eax;
errorp = !!(regs.r_eflags & PSL_C); errorp = !!(regs.r_eflags & PSL_C);
@ -313,7 +294,7 @@ i386_linux_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused)
if (errorp) if (errorp)
asprintf(&temp, "0x%lx", fsc.args[sc->args[i].offset]); asprintf(&temp, "0x%lx", fsc.args[sc->args[i].offset]);
else 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; fsc.s_args[i] = temp;
} }
} }

View File

@ -32,8 +32,9 @@
*/ */
extern int setup_and_wait(char **); 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 restore_proc(int);
extern void waitevent(struct trussinfo *);
extern const char *ioctlname(register_t val); extern const char *ioctlname(register_t val);
extern char *strsig(int sig); extern char *strsig(int sig);
#ifdef __alpha__ #ifdef __alpha__
@ -63,4 +64,3 @@ extern void sparc64_syscall_entry(struct trussinfo *, int);
extern long sparc64_syscall_exit(struct trussinfo *, int); extern long sparc64_syscall_exit(struct trussinfo *, int);
#endif #endif
extern int Procfd;

View File

@ -43,9 +43,8 @@ static const char rcsid[] =
*/ */
#include <sys/types.h> #include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/pioctl.h>
#include <sys/syscall.h> #include <sys/syscall.h>
#include <sys/ptrace.h>
#include <machine/reg.h> #include <machine/reg.h>
#include <machine/psl.h> #include <machine/psl.h>
@ -63,7 +62,6 @@ static const char rcsid[] =
#include "syscall.h" #include "syscall.h"
#include "extern.h" #include "extern.h"
static int fd = -1;
static int cpid = -1; static int cpid = -1;
#include "syscalls.h" #include "syscalls.h"
@ -113,26 +111,18 @@ clear_fsc(void) {
void void
i386_syscall_entry(struct trussinfo *trussinfo, int nargs) { i386_syscall_entry(struct trussinfo *trussinfo, int nargs) {
char buf[32];
struct reg regs; struct reg regs;
int syscall_num; int syscall_num;
int i; int i;
unsigned int parm_offset; unsigned int parm_offset;
struct syscall *sc = NULL; struct syscall *sc = NULL;
struct ptrace_io_desc iorequest;
if (fd == -1 || trussinfo->pid != cpid) { cpid = trussinfo->curthread->tid;
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(); 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"); fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
return; return;
} }
@ -146,13 +136,11 @@ i386_syscall_entry(struct trussinfo *trussinfo, int nargs) {
syscall_num = regs.r_eax; syscall_num = regs.r_eax;
switch (syscall_num) { switch (syscall_num) {
case SYS_syscall: case SYS_syscall:
lseek(Procfd, parm_offset, SEEK_SET); syscall_num = ptrace(PT_READ_D, cpid, (caddr_t)parm_offset, 0);
read(Procfd, &syscall_num, sizeof(int));
parm_offset += sizeof(int); parm_offset += sizeof(int);
break; break;
case SYS___syscall: case SYS___syscall:
lseek(Procfd, parm_offset, SEEK_SET); syscall_num = ptrace(PT_READ_D, cpid, (caddr_t)parm_offset, 0);
read(Procfd, &syscall_num, sizeof(int));
parm_offset += sizeof(quad_t); parm_offset += sizeof(quad_t);
break; break;
} }
@ -169,15 +157,19 @@ i386_syscall_entry(struct trussinfo *trussinfo, int nargs) {
|| !strcmp(fsc.name, "rfork") || !strcmp(fsc.name, "rfork")
|| !strcmp(fsc.name, "vfork")))) || !strcmp(fsc.name, "vfork"))))
{ {
trussinfo->in_fork = 1; trussinfo->curthread->in_fork = 1;
} }
if (nargs == 0) if (nargs == 0)
return; return;
fsc.args = malloc((1+nargs) * sizeof(unsigned long)); fsc.args = malloc((1+nargs) * sizeof(unsigned long));
lseek(Procfd, parm_offset, SEEK_SET); iorequest.piod_op = PIOD_READ_D;
if (read(Procfd, fsc.args, nargs * sizeof(unsigned long)) == -1) 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; return;
if (fsc.name) if (fsc.name)
@ -218,7 +210,7 @@ i386_syscall_entry(struct trussinfo *trussinfo, int nargs) {
i < (fsc.nargs - 1) ? "," : ""); i < (fsc.nargs - 1) ? "," : "");
#endif #endif
if (sc && !(sc->args[i].type & OUT)) { 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 #if DEBUG
@ -274,28 +266,20 @@ i386_syscall_entry(struct trussinfo *trussinfo, int nargs) {
long long
i386_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused) i386_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused)
{ {
char buf[32];
struct reg regs; struct reg regs;
long retval; long retval;
int i; int i;
int errorp; int errorp;
struct syscall *sc; struct syscall *sc;
if (fd == -1 || trussinfo->pid != cpid) { cpid = trussinfo->curthread->tid;
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;
}
lseek(fd, 0L, 0); if (ptrace(PT_GETREGS, cpid, (caddr_t)&regs, 0) < 0)
if (read(fd, &regs, sizeof(regs)) != sizeof(regs)) { {
fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
return (-1); return (-1);
} }
retval = regs.r_eax; retval = regs.r_eax;
errorp = !!(regs.r_eflags & PSL_C); errorp = !!(regs.r_eflags & PSL_C);
@ -323,7 +307,7 @@ i386_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused)
if (errorp) if (errorp)
asprintf(&temp, "0x%lx", fsc.args[sc->args[i].offset]); asprintf(&temp, "0x%lx", fsc.args[sc->args[i].offset]);
else 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; fsc.s_args[i] = temp;
} }
} }

View File

@ -41,8 +41,7 @@ static const char rcsid[] =
*/ */
#include <sys/types.h> #include <sys/types.h>
#include <sys/ioctl.h> #include <sys/ptrace.h>
#include <sys/pioctl.h>
#include <machine/reg.h> #include <machine/reg.h>
#include <machine/psl.h> #include <machine/psl.h>
@ -60,7 +59,6 @@ static const char rcsid[] =
#include "syscall.h" #include "syscall.h"
#include "extern.h" #include "extern.h"
static int fd = -1;
static int cpid = -1; static int cpid = -1;
#include "linux_syscalls.h" #include "linux_syscalls.h"
@ -108,28 +106,20 @@ clear_fsc(void) {
void void
i386_linux_syscall_entry(struct trussinfo *trussinfo, int nargs) { i386_linux_syscall_entry(struct trussinfo *trussinfo, int nargs) {
char buf[32];
struct reg regs; struct reg regs;
int syscall_num; int syscall_num;
int i; int i;
struct syscall *sc; struct syscall *sc;
if (fd == -1 || trussinfo->pid != cpid) { cpid = trussinfo->curthread->tid;
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(); 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"); fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
return; return;
} }
syscall_num = regs.r_eax; syscall_num = regs.r_eax;
fsc.number = syscall_num; fsc.number = syscall_num;
@ -143,7 +133,7 @@ i386_linux_syscall_entry(struct trussinfo *trussinfo, int nargs) {
&& ((!strcmp(fsc.name, "linux_fork") && ((!strcmp(fsc.name, "linux_fork")
|| !strcmp(fsc.name, "linux_vfork")))) || !strcmp(fsc.name, "linux_vfork"))))
{ {
trussinfo->in_fork = 1; trussinfo->curthread->in_fork = 1;
} }
if (nargs == 0) if (nargs == 0)
@ -200,7 +190,7 @@ i386_linux_syscall_entry(struct trussinfo *trussinfo, int nargs) {
i < (fsc.nargs - 1) ? "," : ""); i < (fsc.nargs - 1) ? "," : "");
#endif #endif
if (sc && !(sc->args[i].type & OUT)) { 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 #if DEBUG
@ -264,28 +254,19 @@ const int bsd_to_linux_errno[] = {
long long
i386_linux_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused) i386_linux_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused)
{ {
char buf[32];
struct reg regs; struct reg regs;
long retval; long retval;
int i; int i;
int errorp; int errorp;
struct syscall *sc; struct syscall *sc;
if (fd == -1 || trussinfo->pid != cpid) { cpid = trussinfo->curthread->tid;
sprintf(buf, "/proc/%d/regs", trussinfo->pid); if (ptrace(PT_GETREGS, cpid, (caddr_t)&regs, 0) < 0)
fd = open(buf, O_RDONLY); {
if (fd == -1) { fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
fprintf(trussinfo->outfile, "-- CANNOT OPEN REGISTERS --\n");
return (-1);
}
cpid = trussinfo->pid;
}
lseek(fd, 0L, 0);
if (read(fd, &regs, sizeof(regs)) != sizeof(regs)) {
fprintf(trussinfo->outfile, "\n");
return (-1); return (-1);
} }
retval = regs.r_eax; retval = regs.r_eax;
errorp = !!(regs.r_eflags & PSL_C); errorp = !!(regs.r_eflags & PSL_C);
@ -313,7 +294,7 @@ i386_linux_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused)
if (errorp) if (errorp)
asprintf(&temp, "0x%lx", fsc.args[sc->args[i].offset]); asprintf(&temp, "0x%lx", fsc.args[sc->args[i].offset]);
else 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; fsc.s_args[i] = temp;
} }
} }

View File

@ -43,8 +43,7 @@ static const char rcsid[] =
*/ */
#include <sys/types.h> #include <sys/types.h>
#include <sys/ioctl.h> #include <sys/ptrace.h>
#include <sys/pioctl.h>
#include <sys/syscall.h> #include <sys/syscall.h>
#include <machine/reg.h> #include <machine/reg.h>
@ -62,7 +61,6 @@ static const char rcsid[] =
#include "syscall.h" #include "syscall.h"
#include "extern.h" #include "extern.h"
static int fd = -1;
static int cpid = -1; static int cpid = -1;
#include "syscalls.h" #include "syscalls.h"
@ -112,26 +110,16 @@ clear_fsc(void) {
void void
ia64_syscall_entry(struct trussinfo *trussinfo, int nargs) { ia64_syscall_entry(struct trussinfo *trussinfo, int nargs) {
char buf[32];
struct reg regs; struct reg regs;
int syscall_num; int syscall_num;
int i; int i;
unsigned long *parm_offset; unsigned long *parm_offset;
struct syscall *sc; struct syscall *sc;
if (fd == -1 || trussinfo->pid != cpid) { cpid = trussinfo->curthread->tid;
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(); clear_fsc();
lseek(fd, 0L, 0); if (ptrace(PT_GETREGS, cpid, (caddr_t)&regs, 0) < 0) {
if (read(fd, &regs, sizeof(regs)) != sizeof(regs)) {
fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
return; return;
} }
@ -158,7 +146,7 @@ ia64_syscall_entry(struct trussinfo *trussinfo, int nargs) {
|| !strcmp(fsc.name, "rfork") || !strcmp(fsc.name, "rfork")
|| !strcmp(fsc.name, "vfork")))) || !strcmp(fsc.name, "vfork"))))
{ {
trussinfo->in_fork = 1; trussinfo->curthread->in_fork = 1;
} }
if (nargs == 0) if (nargs == 0)
@ -204,7 +192,7 @@ ia64_syscall_entry(struct trussinfo *trussinfo, int nargs) {
i < (fsc.nargs - 1) ? "," : ""); i < (fsc.nargs - 1) ? "," : "");
#endif #endif
if (sc && !(sc->args[i].type & OUT)) { 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 #if DEBUG
@ -260,25 +248,15 @@ ia64_syscall_entry(struct trussinfo *trussinfo, int nargs) {
long long
ia64_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused) ia64_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused)
{ {
char buf[32];
struct reg regs; struct reg regs;
long retval; long retval;
int i; int i;
int errorp; int errorp;
struct syscall *sc; struct syscall *sc;
if (fd == -1 || trussinfo->pid != cpid) { cpid = trussinfo->curthread->tid;
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;
}
lseek(fd, 0L, 0); if (ptrace(PT_GETREGS, cpid, (caddr_t)&regs, 0) < 0) {
if (read(fd, &regs, sizeof(regs)) != sizeof(regs)) {
fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
return (-1); return (-1);
} }
@ -309,7 +287,7 @@ ia64_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused)
if (errorp) if (errorp)
asprintf(&temp, "0x%lx", fsc.args[sc->args[i].offset]); asprintf(&temp, "0x%lx", fsc.args[sc->args[i].offset]);
else 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; fsc.s_args[i] = temp;
} }
} }

View File

@ -39,11 +39,10 @@ __FBSDID("$FreeBSD$");
*/ */
#include <sys/param.h> #include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/pioctl.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/resource.h> #include <sys/resource.h>
#include <sys/sysctl.h>
#include <ctype.h> #include <ctype.h>
#include <err.h> #include <err.h>
@ -59,12 +58,7 @@ __FBSDID("$FreeBSD$");
#include "truss.h" #include "truss.h"
#include "extern.h" #include "extern.h"
/* #define MAXARGS 5
* It's difficult to parameterize this because it must be
* accessible in a signal handler.
*/
int Procfd;
static void static void
usage(void) usage(void)
@ -111,26 +105,26 @@ struct ex_types {
/* /*
* Set the execution type. This is called after every exec, and when * Set the execution type. This is called after every exec, and when
* a process is first monitored. The procfs pseudo-file "etype" has * a process is first monitored.
* the execution module type -- see /proc/curproc/etype for an example.
*/ */
static struct ex_types * static struct ex_types *
set_etype(struct trussinfo *trussinfo) set_etype(struct trussinfo *trussinfo)
{ {
struct ex_types *funcs; struct ex_types *funcs;
char etype[24];
char progt[32]; char progt[32];
int fd;
size_t len = sizeof(progt);
int mib[4];
int error;
sprintf(etype, "/proc/%d/etype", trussinfo->pid); mib[0] = CTL_KERN;
if ((fd = open(etype, O_RDONLY)) == -1) { mib[1] = KERN_PROC;
strcpy(progt, "FreeBSD a.out"); mib[2] = KERN_PROC_SV_NAME;
} else { mib[3] = trussinfo->pid;
int len = read(fd, progt, sizeof(progt)); error = sysctl(mib, 4, progt, &len, NULL, 0);
progt[len-1] = '\0'; if (error != 0)
close(fd); err(2, "can not get etype");
}
for (funcs = ex_types; funcs->type; funcs++) for (funcs = ex_types; funcs->type; funcs++)
if (!strcmp(funcs->type, progt)) if (!strcmp(funcs->type, progt))
@ -167,14 +161,12 @@ main(int ac, char **av)
int c; int c;
int i; int i;
char **command; char **command;
struct procfs_status pfs;
struct ex_types *funcs; struct ex_types *funcs;
int in_exec, sigexit, initial_open; int sigexit, initial_open;
char *fname; char *fname;
struct trussinfo *trussinfo; struct trussinfo *trussinfo;
char *signame; char *signame;
in_exec = 0;
sigexit = 0; sigexit = 0;
fname = NULL; fname = NULL;
initial_open = 1; initial_open = 1;
@ -184,9 +176,12 @@ main(int ac, char **av)
if (trussinfo == NULL) if (trussinfo == NULL)
errx(1, "malloc() failed"); errx(1, "malloc() failed");
bzero(trussinfo, sizeof(struct trussinfo)); bzero(trussinfo, sizeof(struct trussinfo));
trussinfo->outfile = stderr; trussinfo->outfile = stderr;
trussinfo->strsize = 32; 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) { while ((c = getopt(ac, av, "p:o:faedDs:S")) != -1) {
switch (c) { switch (c) {
case 'p': /* specified pid */ case 'p': /* specified pid */
@ -245,6 +240,7 @@ main(int ac, char **av)
signal(SIGTERM, SIG_IGN); signal(SIGTERM, SIG_IGN);
signal(SIGQUIT, SIG_IGN); signal(SIGQUIT, SIG_IGN);
} else { } else {
start_tracing(trussinfo->pid);
signal(SIGINT, restore_proc); signal(SIGINT, restore_proc);
signal(SIGTERM, restore_proc); signal(SIGTERM, restore_proc);
signal(SIGQUIT, restore_proc); signal(SIGQUIT, restore_proc);
@ -257,18 +253,9 @@ main(int ac, char **av)
*/ */
START_TRACE: 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));
initial_open = 0;
if (Procfd == -1)
return (0);
pfs.why = 0;
funcs = set_etype(trussinfo); funcs = set_etype(trussinfo);
initial_open = 0;
/* /*
* At this point, it's a simple loop, waiting for the process to * At this point, it's a simple loop, waiting for the process to
* stop, finding out why, printing out why, and then continuing it. * stop, finding out why, printing out why, and then continuing it.
@ -278,118 +265,92 @@ START_TRACE:
clock_gettime(CLOCK_REALTIME, &trussinfo->start_time); clock_gettime(CLOCK_REALTIME, &trussinfo->start_time);
do { do {
int val = 0;
struct timespec timediff; struct timespec timediff;
waitevent(trussinfo);
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->curthread->in_fork &&
(trussinfo->flags & FOLLOWFORKS)) {
int childpid;
trussinfo->curthread->in_fork = 0;
childpid =
funcs->exit_syscall(trussinfo,
trussinfo->pr_data);
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 * Fork a new copy of ourself to trace
* an exec -- one for the S_EXEC, and one for * the child of the original traced
* the syscall exit. It also, conveniently, * process.
* ensures that the first message printed out
* isn't the return-from-syscall used to
* create the process.
*/ */
if (in_exec) { if (fork() == 0) {
in_exec = 0; trussinfo->pid = childpid;
break; start_tracing(trussinfo->pid);
goto START_TRACE;
} }
if (trussinfo->in_fork &&
(trussinfo->flags & FOLLOWFORKS)) {
int childpid;
trussinfo->in_fork = 0;
childpid =
funcs->exit_syscall(trussinfo,
pfs.val);
/*
* 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;
}
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;
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; break;
} }
} funcs->exit_syscall(trussinfo, MAXARGS);
if (ioctl(Procfd, PIOCCONT, val) == -1) { break;
if (kill(trussinfo->pid, 0) == -1 && errno == ESRCH) case S_SIG:
if (trussinfo->flags & NOSIGS)
break; break;
else if (trussinfo->flags & FOLLOWFORKS)
warn("PIOCCONT"); 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;
} }
} while (pfs.why != S_EXIT); } while (trussinfo->pr_why != S_EXIT);
fflush(trussinfo->outfile); fflush(trussinfo->outfile);
if (sigexit) { if (sigexit) {
struct rlimit rlp; struct rlimit rlp;
@ -400,5 +361,6 @@ START_TRACE:
(void) signal(sigexit, SIG_DFL); (void) signal(sigexit, SIG_DFL);
(void) kill(getpid(), sigexit); (void) kill(getpid(), sigexit);
} }
return (0); return (0);
} }

View File

@ -41,8 +41,7 @@ static const char rcsid[] =
*/ */
#include <sys/types.h> #include <sys/types.h>
#include <sys/ioctl.h> #include <sys/ptrace.h>
#include <sys/pioctl.h>
#include <sys/syscall.h> #include <sys/syscall.h>
#include <machine/reg.h> #include <machine/reg.h>
@ -62,7 +61,6 @@ static const char rcsid[] =
#include "syscall.h" #include "syscall.h"
#include "extern.h" #include "extern.h"
static int fd = -1;
static int cpid = -1; static int cpid = -1;
#include "syscalls.h" #include "syscalls.h"
@ -120,19 +118,10 @@ powerpc_syscall_entry(struct trussinfo *trussinfo, int nargs) {
unsigned int regargs; unsigned int regargs;
struct syscall *sc; struct syscall *sc;
if (fd == -1 || trussinfo->pid != cpid) { cpid = trussinfo->curthread->tid;
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(); clear_fsc();
lseek(fd, 0L, 0); if (ptrace(PT_GETREGS, cpid, (caddr_t)&regs, 0) < 0) {
if (read(fd, &regs, sizeof(regs)) != sizeof(regs)) {
fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n"); fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
return; return;
} }
@ -167,7 +156,7 @@ powerpc_syscall_entry(struct trussinfo *trussinfo, int nargs) {
|| !strcmp(fsc.name, "rfork") || !strcmp(fsc.name, "rfork")
|| !strcmp(fsc.name, "vfork")))) || !strcmp(fsc.name, "vfork"))))
{ {
trussinfo->in_fork = 1; trussinfo->curthread->in_fork = 1;
} }
if (nargs == 0) if (nargs == 0)
@ -176,9 +165,16 @@ powerpc_syscall_entry(struct trussinfo *trussinfo, int nargs) {
fsc.args = malloc((1+nargs) * sizeof(unsigned long)); fsc.args = malloc((1+nargs) * sizeof(unsigned long));
if (nargs > regargs) { if (nargs > regargs) {
struct ptrace_io_desc iorequest;
memmove(&fsc.args[0], args, regargs * sizeof(fsc.args[0])); 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 { } else {
memmove(&fsc.args[0], args, nargs * sizeof(fsc.args[0])); memmove(&fsc.args[0], args, nargs * sizeof(fsc.args[0]));
} }
@ -220,7 +216,7 @@ powerpc_syscall_entry(struct trussinfo *trussinfo, int nargs) {
i < (fsc.nargs - 1) ? "," : ""); i < (fsc.nargs - 1) ? "," : "");
#endif #endif
if (sc && !(sc->args[i].type & OUT)) { 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 #if DEBUG
@ -275,25 +271,15 @@ powerpc_syscall_entry(struct trussinfo *trussinfo, int nargs) {
long long
powerpc_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused) powerpc_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused)
{ {
char buf[32];
struct reg regs; struct reg regs;
long retval; long retval;
int i; int i;
int errorp; int errorp;
struct syscall *sc; struct syscall *sc;
if (fd == -1 || trussinfo->pid != cpid) { cpid = trussinfo->curthread->tid;
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;
}
lseek(fd, 0L, 0); if (ptrace(PT_GETREGS, cpid, (caddr_t)&regs, 0) < 0) {
if (read(fd, &regs, sizeof(regs)) != sizeof(regs)) {
fprintf(trussinfo->outfile, "\n"); fprintf(trussinfo->outfile, "\n");
return (-1); return (-1);
} }
@ -332,7 +318,7 @@ powerpc_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused)
if (errorp) if (errorp)
asprintf(&temp, "0x%lx", fsc.args[sc->args[i].offset]); asprintf(&temp, "0x%lx", fsc.args[sc->args[i].offset]);
else 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; fsc.s_args[i] = temp;
} }
} }

View File

@ -38,11 +38,12 @@ __FBSDID("$FreeBSD$");
*/ */
#include <sys/param.h> #include <sys/param.h>
#include <sys/ioctl.h> #include <sys/types.h>
#include <sys/pioctl.h> #include <sys/ptrace.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <err.h> #include <err.h>
#include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <signal.h> #include <signal.h>
#include <stdio.h> #include <stdio.h>
@ -51,10 +52,12 @@ __FBSDID("$FreeBSD$");
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#include <machine/reg.h>
#include "truss.h" #include "truss.h"
#include "extern.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 * setup_and_wait() is called to start a process. All it really does
@ -66,75 +69,28 @@ static int evflags = 0;
int int
setup_and_wait(char *command[]) setup_and_wait(char *command[])
{ {
struct procfs_status pfs;
char buf[32];
int fd;
int pid; int pid;
int flags; int waitval;
int loop;
pid = fork(); pid = vfork();
if (pid == -1) { if (pid == -1) {
err(1, "fork failed"); err(1, "fork failed");
} }
if (pid == 0) { /* Child */ if (pid == 0) { /* Child */
int mask = S_EXEC | S_EXIT; ptrace(PT_TRACE_ME, 0, 0, 0);
fd = open("/proc/curproc/mem", O_WRONLY); setpgid (0, 0);
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");
execvp(command[0], command); execvp(command[0], command);
mask = ~0; err(1, "execvp %s", command[0]);
ioctl(fd, PIOCBIC, ~0);
err(4, "execvp %s", command[0]);
} }
/* Only in the parent here */ /* Only in the parent here */
if (waitpid(pid, &waitval, 0) < -1) {
if (waitpid(pid, NULL, WNOHANG) != 0) { err(1, "unexpect stop in waitpid");
/* return 0;
* Process exited before it got to us -- meaning the exec failed
* miserably -- so we just quietly exit.
*/
exit(1);
} }
sprintf(buf, "/proc/%d/mem", pid); child_pid = 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);
return (pid); return (pid);
} }
@ -145,45 +101,24 @@ setup_and_wait(char *command[])
*/ */
int int
start_tracing(int pid, int failisfatal, int eventflags, int flags) start_tracing(int pid)
{ {
int fd; int waitval;
char buf[32]; int ret;
struct procfs_status tmp; int retry = 10;
sprintf(buf, "/proc/%d/mem", pid); do {
/* usleep(500000); */ 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); child_pid = pid;
if (fd == -1) { if (waitpid(pid, &waitval, 0) < -1)
/* err(1, "Unexpect stop in waitpid");
* 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);
}
if (ioctl(fd, PIOCSTATUS, &tmp) == -1) { return (0);
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);
} }
/* /*
@ -193,10 +128,89 @@ start_tracing(int pid, int failisfatal, int eventflags, int flags)
* process. * process.
*/ */
void void
restore_proc(int signo __unused) { restore_proc(int signo __unused)
{
int waitval;
ioctl(Procfd, PIOCBIC, ~0); /* stop the child so that we can detach */
if (evflags) kill(child_pid, SIGSTOP);
ioctl(Procfd, PIOCBIS, evflags); if (waitpid(child_pid, &waitval, 0) < -1)
err(1, "Unexpected stop in waitpid");
if (ptrace(PT_DETACH, child_pid, (caddr_t)1, 0) < 0)
err(1, "Can not detach the process");
kill(child_pid, SIGCONT);
exit(0); exit(0);
} }
/*
* Change curthread member based on lwpid.
* If it is a new thread, create a threadinfo structure
*/
static 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;
}
/*
* Start the traced process and wait until it stoped.
* Fill trussinfo structure.
* When this even returns, the traced process is in stop state.
*/
void
waitevent(struct trussinfo *info)
{
int waitval;
static int pending_signal = 0;
ptrace(PT_SYSCALL, info->pid, (caddr_t)1, pending_signal);
pending_signal = 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);
pending_signal = info->pr_data;
break;
}
}
}

View File

@ -45,8 +45,7 @@ static const char rcsid[] =
*/ */
#include <sys/types.h> #include <sys/types.h>
#include <sys/ioctl.h> #include <sys/ptrace.h>
#include <sys/pioctl.h>
#include <sys/syscall.h> #include <sys/syscall.h>
#include <machine/frame.h> #include <machine/frame.h>
@ -68,7 +67,6 @@ static const char rcsid[] =
#include "syscall.h" #include "syscall.h"
#include "extern.h" #include "extern.h"
static int fd = -1;
static int cpid = -1; static int cpid = -1;
#include "syscalls.h" #include "syscalls.h"
@ -118,26 +116,18 @@ clear_fsc(void) {
void void
sparc64_syscall_entry(struct trussinfo *trussinfo, int nargs) { sparc64_syscall_entry(struct trussinfo *trussinfo, int nargs) {
char buf[32];
struct reg regs; struct reg regs;
int syscall_num; int syscall_num;
int i; int i;
struct syscall *sc; struct syscall *sc;
int indir = 0; /* indirect system call */ int indir = 0; /* indirect system call */
struct ptrace_io_desc iorequest;
if (fd == -1 || trussinfo->pid != cpid) { cpid = trussinfo->curthread->tid;
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(); 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"); fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
return; return;
} }
@ -165,7 +155,7 @@ sparc64_syscall_entry(struct trussinfo *trussinfo, int nargs) {
|| !strcmp(fsc.name, "rfork") || !strcmp(fsc.name, "rfork")
|| !strcmp(fsc.name, "vfork")))) || !strcmp(fsc.name, "vfork"))))
{ {
trussinfo->in_fork = 1; trussinfo->curthread->in_fork = 1;
} }
if (nargs == 0) if (nargs == 0)
@ -186,9 +176,14 @@ sparc64_syscall_entry(struct trussinfo *trussinfo, int nargs) {
* on the stack, as is normal for other processors. * on the stack, as is normal for other processors.
* The fall-through for all of these is deliberate!!! * The fall-through for all of these is deliberate!!!
*/ */
lseek(Procfd, regs.r_out[6] + SPOFF + iorequest.piod_op = PIOD_READ_D;
offsetof(struct frame, fr_pad[6]), SEEK_SET); iorequest.piod_offs = (void *)(regs.r_out[6] + SPOFF +
read(fd, &fsc.args[6], (nargs - 6) * sizeof(fsc.args[0])); 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 6: fsc.args[5] = regs.r_out[5];
case 5: fsc.args[4] = regs.r_out[4]; case 5: fsc.args[4] = regs.r_out[4];
case 4: fsc.args[3] = regs.r_out[3]; case 4: fsc.args[3] = regs.r_out[3];
@ -240,7 +235,7 @@ sparc64_syscall_entry(struct trussinfo *trussinfo, int nargs) {
i < (fsc.nargs - 1) ? "," : ""); i < (fsc.nargs - 1) ? "," : "");
#endif #endif
if (sc && !(sc->args[i].type & OUT)) { 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 #if DEBUG
@ -295,25 +290,15 @@ sparc64_syscall_entry(struct trussinfo *trussinfo, int nargs) {
long long
sparc64_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused) { sparc64_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused) {
char buf[32];
struct reg regs; struct reg regs;
long retval; long retval;
int i; int i;
int errorp; int errorp;
struct syscall *sc; struct syscall *sc;
if (fd == -1 || trussinfo->pid != cpid) { cpid = trussinfo->curthread->tid;
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;
}
lseek(fd, 0L, 0); if (ptrace(PT_GETREGS, cpid, (caddr_t)&regs, 0) < 0) {
if (read(fd, &regs, sizeof(regs)) != sizeof(regs)) {
fprintf(trussinfo->outfile, "\n"); fprintf(trussinfo->outfile, "\n");
return (-1); return (-1);
} }
@ -344,7 +329,7 @@ sparc64_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused) {
if (errorp) if (errorp)
asprintf(&temp, "0x%lx", fsc.args[sc->args[i].offset]); asprintf(&temp, "0x%lx", fsc.args[sc->args[i].offset]);
else 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; fsc.s_args[i] = temp;
} }
} }

View File

@ -60,8 +60,7 @@ struct syscall {
}; };
struct syscall *get_syscall(const char*); struct syscall *get_syscall(const char*);
char *get_string(int, void*, int); char *print_arg(struct syscall_args *, unsigned long*, long, struct trussinfo *);
char *print_arg(int, struct syscall_args *, unsigned long*, long, struct trussinfo *);
void print_syscall(struct trussinfo *, const char *, int, char **); void print_syscall(struct trussinfo *, const char *, int, char **);
void print_syscall_ret(struct trussinfo *, const char *, int, char **, int, void print_syscall_ret(struct trussinfo *, const char *, int, char **, int,
long); long);

View File

@ -41,6 +41,7 @@ static const char rcsid[] =
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/ptrace.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/un.h> #include <sys/un.h>
@ -216,7 +217,7 @@ struct syscall syscalls[] = {
/* Xlat idea taken from strace */ /* Xlat idea taken from strace */
struct xlat { struct xlat {
int val; int val;
char *str; const char *str;
}; };
#define X(a) { a, #a }, #define X(a) { a, #a },
@ -324,7 +325,8 @@ static struct xlat pathconf_arg[] = {
/* Searches an xlat array for a value, and returns it if found. Otherwise /* Searches an xlat array for a value, and returns it if found. Otherwise
return a string representation. */ return a string representation. */
char *lookup(struct xlat *xlat, int val, int base) static const char
*lookup(struct xlat *xlat, int val, int base)
{ {
static char tmp[16]; static char tmp[16];
for (; xlat->str != NULL; xlat++) for (; xlat->str != NULL; xlat++)
@ -347,7 +349,8 @@ char *lookup(struct xlat *xlat, int val, int base)
return tmp; return tmp;
} }
char *xlookup(struct xlat *xlat, int val) static const char *
xlookup(struct xlat *xlat, int val)
{ {
return lookup(xlat, val, 16); return lookup(xlat, val, 16);
} }
@ -355,7 +358,8 @@ char *xlookup(struct xlat *xlat, int val)
/* Searches an xlat array containing bitfield values. Remaining bits /* Searches an xlat array containing bitfield values. Remaining bits
set after removing the known ones are printed at the end: set after removing the known ones are printed at the end:
IN|0x400 */ IN|0x400 */
char *xlookup_bits(struct xlat *xlat, int val) static char
*xlookup_bits(struct xlat *xlat, int val)
{ {
static char str[512]; static char str[512];
int len = 0; int len = 0;
@ -408,13 +412,20 @@ get_syscall(const char *name) {
*/ */
static int static int
get_struct(int procfd, void *offset, void *buf, int len) { get_struct(int pid, void *offset, void *buf, int len) {
struct ptrace_io_desc iorequest;
if (pread(procfd, buf, len, (uintptr_t)offset) != len)
return -1; 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) < 0)
return -1;
return 0; return 0;
} }
#define MAXSIZE 4096
#define BLOCKSIZE 1024
/* /*
* get_string * get_string
* Copy a string from the process. Note that it is * Copy a string from the process. Note that it is
@ -422,39 +433,42 @@ get_struct(int procfd, void *offset, void *buf, int len) {
* only get that much. * only get that much.
*/ */
char * static char *
get_string(int procfd, void *offset, int max) { get_string(pid_t pid, void *offset, int max) {
char *buf; char *buf;
int size, len, c, fd; struct ptrace_io_desc iorequest;
FILE *p; int totalsize, size;
int diff = 0;
if ((fd = dup(procfd)) == -1) int i;
err(1, "dup");
if ((p = fdopen(fd, "r")) == NULL) totalsize = size = max ? (max + 1) : BLOCKSIZE;
err(1, "fdopen"); buf = malloc(totalsize);
buf = malloc( size = (max ? max + 1 : 64 ) ); if (buf == NULL)
len = 0; return NULL;
buf[0] = 0; for(;;) {
if (fseeko(p, (uintptr_t)offset, SEEK_SET) == 0) { diff = totalsize - size;
while ((c = fgetc(p)) != EOF) { iorequest.piod_op = PIOD_READ_D;
buf[len++] = c; iorequest.piod_offs = (char *)offset + diff;
if (c == 0 || len == max) iorequest.piod_addr = buf + diff;
break; iorequest.piod_len = size;
if (len == size) { if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0) {
char *tmp; free(buf);
tmp = realloc(buf, size+64); return NULL;
if (tmp == NULL) { }
buf[len] = 0; for (i = 0 ; i < size; i++) {
break; if (buf[diff + i] == '\0')
} return (buf);
size += 64; }
buf = tmp; if (totalsize < MAXSIZE - BLOCKSIZE && max == 0) {
} totalsize += BLOCKSIZE;
buf = realloc(buf, totalsize);
size = BLOCKSIZE;
}
else {
buf[totalsize] = '\0';
return buf;
} }
buf[len] = 0;
} }
fclose(p);
return (buf);
} }
@ -469,9 +483,9 @@ get_string(int procfd, void *offset, int max) {
*/ */
char * 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; char *tmp = NULL;
int pid = trussinfo->pid;
switch (sc->type & ARG_MASK) { switch (sc->type & ARG_MASK) {
case Hex: case Hex:
asprintf(&tmp, "0x%lx", args[sc->offset]); asprintf(&tmp, "0x%lx", args[sc->offset]);
@ -486,7 +500,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str
{ {
/* NULL-terminated string. */ /* NULL-terminated string. */
char *tmp2; char *tmp2;
tmp2 = get_string(fd, (void*)args[sc->offset], 0); tmp2 = get_string(pid, (void*)args[sc->offset], 0);
asprintf(&tmp, "\"%s\"", tmp2); asprintf(&tmp, "\"%s\"", tmp2);
free(tmp2); free(tmp2);
} }
@ -514,7 +528,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str
len = max_string; len = max_string;
truncated = 1; 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); tmp3 = malloc(len * 4 + 1);
while (len) { while (len) {
if (strvisx(tmp3, tmp2, len, VIS_CSTYLE|VIS_TAB|VIS_NL) <= max_string) if (strvisx(tmp3, tmp2, len, VIS_CSTYLE|VIS_TAB|VIS_NL) <= max_string)
@ -535,7 +549,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str
char *string; char *string;
char *strarray[100]; /* XXX This is ugly. */ 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) { sizeof(strarray)) == -1) {
err(1, "get_struct %p", (void *)args[sc->offset]); err(1, "get_struct %p", (void *)args[sc->offset]);
} }
@ -544,7 +558,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str
/* Find out how large of a buffer we'll need. */ /* Find out how large of a buffer we'll need. */
while (strarray[num] != NULL) { while (strarray[num] != NULL) {
string = get_string(fd, (void*)strarray[num], 0); string = get_string(pid, (void*)strarray[num], 0);
size += strlen(string); size += strlen(string);
free(string); free(string);
num++; num++;
@ -555,7 +569,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str
tmp2 += sprintf(tmp2, " ["); tmp2 += sprintf(tmp2, " [");
for (i = 0; i < num; i++) { 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) ? ' ' : ','); tmp2 += sprintf(tmp2, " \"%s\"%c", string, (i+1 == num) ? ' ' : ',');
free(string); free(string);
} }
@ -585,7 +599,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str
tmp = strdup(""); tmp = strdup("");
break; break;
} }
tmp2 = get_string(fd, (void*)args[sc->offset], retval); tmp2 = get_string(pid, (void*)args[sc->offset], retval);
asprintf(&tmp, "\"%s\"", tmp2); asprintf(&tmp, "\"%s\"", tmp2);
free(tmp2); free(tmp2);
} }
@ -608,7 +622,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str
case Umtx: case Umtx:
{ {
struct umtx 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); asprintf(&tmp, "{0x%lx}", (long)umtx.u_owner);
else else
asprintf(&tmp, "0x%lx", args[sc->offset]); asprintf(&tmp, "0x%lx", args[sc->offset]);
@ -617,7 +631,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str
case Timespec: case Timespec:
{ {
struct timespec ts; 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); asprintf(&tmp, "{%ld.%09ld}", (long)ts.tv_sec, ts.tv_nsec);
else else
asprintf(&tmp, "0x%lx", args[sc->offset]); asprintf(&tmp, "0x%lx", args[sc->offset]);
@ -626,7 +640,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str
case Timeval: case Timeval:
{ {
struct timeval tv; 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); asprintf(&tmp, "{%ld.%06ld}", (long)tv.tv_sec, tv.tv_usec);
else else
asprintf(&tmp, "0x%lx", args[sc->offset]); asprintf(&tmp, "0x%lx", args[sc->offset]);
@ -635,7 +649,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str
case Timeval2: case Timeval2:
{ {
struct timeval tv[2]; 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}", asprintf(&tmp, "{%ld.%06ld, %ld.%06ld}",
(long)tv[0].tv_sec, tv[0].tv_usec, (long)tv[0].tv_sec, tv[0].tv_usec,
(long)tv[1].tv_sec, tv[1].tv_usec); (long)tv[1].tv_sec, tv[1].tv_usec);
@ -646,7 +660,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str
case Itimerval: case Itimerval:
{ {
struct itimerval itv; 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}", asprintf(&tmp, "{%ld.%06ld, %ld.%06ld}",
(long)itv.it_interval.tv_sec, (long)itv.it_interval.tv_sec,
itv.it_interval.tv_usec, itv.it_interval.tv_usec,
@ -670,7 +684,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str
if ((pfd = malloc(bytes)) == NULL) if ((pfd = malloc(bytes)) == NULL)
err(1, "Cannot malloc %d bytes for pollfd array", bytes); 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; used = 0;
tmpsize = 1 + per_fd * numfds + 2; tmpsize = 1 + per_fd * numfds + 2;
@ -709,7 +723,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str
if ((fds = malloc(bytes)) == NULL) if ((fds = malloc(bytes)) == NULL)
err(1, "Cannot malloc %d bytes for fd_set array", bytes); 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; used = 0;
tmpsize = 1 + numfds * per_fd + 2; tmpsize = 1 + numfds * per_fd + 2;
if ((tmp = malloc(tmpsize)) == NULL) if ((tmp = malloc(tmpsize)) == NULL)
@ -749,7 +763,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str
int i, used; int i, used;
sig = args[sc->offset]; 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) sizeof(ss)) == -1)
{ {
asprintf(&tmp, "0x%lx", args[sc->offset]); asprintf(&tmp, "0x%lx", args[sc->offset]);
@ -853,7 +867,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str
} }
/* yuck: get ss_len */ /* 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) sizeof(ss.ss_len) + sizeof(ss.ss_family)) == -1)
err(1, "get_struct %p", (void *)args[sc->offset]); err(1, "get_struct %p", (void *)args[sc->offset]);
/* /*
@ -874,7 +888,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str
break; 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) { == -1) {
err(2, "get_struct %p", (void *)args[sc->offset]); err(2, "get_struct %p", (void *)args[sc->offset]);
} }
@ -913,7 +927,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str
char *hand; char *hand;
const char *h; 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); asprintf(&hand, "%p", sa.sa_handler);
if (sa.sa_handler == SIG_DFL) if (sa.sa_handler == SIG_DFL)
@ -956,7 +970,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str
bytes = sizeof(struct kevent) * numevents; bytes = sizeof(struct kevent) * numevents;
if ((ke = malloc(bytes)) == NULL) if ((ke = malloc(bytes)) == NULL)
err(1, "Cannot malloc %d bytes for kevent array", bytes); 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; used = 0;
tmpsize = 1 + per_ke * numevents + 2; tmpsize = 1 + per_ke * numevents + 2;
if ((tmp = malloc(tmpsize)) == NULL) if ((tmp = malloc(tmpsize)) == NULL)
@ -986,7 +1000,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str
case Stat: case Stat:
{ {
struct stat st; 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]; char mode[12];
strmode(st.st_mode, mode); strmode(st.st_mode, mode);
asprintf(&tmp, "{mode=%s,inode=%jd,size=%jd,blksize=%ld}", asprintf(&tmp, "{mode=%s,inode=%jd,size=%jd,blksize=%ld}",
@ -999,7 +1013,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str
case Rusage: case Rusage:
{ {
struct rusage ru; 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}", 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_utime.tv_sec, ru.ru_utime.tv_usec,
(long)ru.ru_stime.tv_sec, ru.ru_stime.tv_usec, (long)ru.ru_stime.tv_sec, ru.ru_stime.tv_usec,
@ -1011,7 +1025,7 @@ print_arg(int fd, struct syscall_args *sc, unsigned long *args, long retval, str
case Rlimit: case Rlimit:
{ {
struct rlimit rl; 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}", asprintf(&tmp, "{cur=%ju,max=%ju}",
rl.rlim_cur, rl.rlim_max); rl.rlim_cur, rl.rlim_max);
else else

View File

@ -23,7 +23,7 @@ The
utility traces the system calls called by the specified process or program. utility traces the system calls called by the specified process or program.
Output is to the specified output file, or standard error by default. Output is to the specified output file, or standard error by default.
It does this by stopping and restarting the process being monitored via It does this by stopping and restarting the process being monitored via
.Xr procfs 5 . .Xr ptrace 2 .
.Pp .Pp
The options are as follows: The options are as follows:
.Bl -tag -width indent .Bl -tag -width indent
@ -79,13 +79,6 @@ and
.Ar command .Ar command
options are mutually exclusive.) options are mutually exclusive.)
.El .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 .Sh EXAMPLES
# Follow the system calls used in echoing "hello" # Follow the system calls used in echoing "hello"
.Dl $ truss /bin/echo hello .Dl $ truss /bin/echo hello
@ -96,8 +89,7 @@ terminates abnormally.
.Sh SEE ALSO .Sh SEE ALSO
.Xr kdump 1 , .Xr kdump 1 ,
.Xr ktrace 1 , .Xr ktrace 1 ,
.Xr procfs 5 , .Xr ptrace 2 2
.Xr procctl 8
.Sh HISTORY .Sh HISTORY
The The
.Nm .Nm

View File

@ -25,6 +25,8 @@
* $FreeBSD$ * $FreeBSD$
*/ */
#include <sys/queue.h>
#define FOLLOWFORKS 0x00000001 #define FOLLOWFORKS 0x00000001
#define RELATIVETIMESTAMPS 0x00000002 #define RELATIVETIMESTAMPS 0x00000002
#define ABSOLUTETIMESTAMPS 0x00000004 #define ABSOLUTETIMESTAMPS 0x00000004
@ -32,17 +34,30 @@
#define EXECVEARGS 0x00000010 #define EXECVEARGS 0x00000010
#define EXECVEENVS 0x00000020 #define EXECVEENVS 0x00000020
struct threadinfo
{
SLIST_ENTRY(threadinfo) entries;
lwpid_t tid;
int in_syscall;
int in_fork;
};
struct trussinfo struct trussinfo
{ {
int pid; int pid;
int flags; int flags;
int in_fork; int pr_why;
int pr_data;
int strsize; int strsize;
FILE *outfile; FILE *outfile;
struct timespec start_time; struct timespec start_time;
struct timespec before; struct timespec before;
struct timespec after; struct timespec after;
struct threadinfo *curthread;
SLIST_HEAD(, threadinfo) threadlist;
}; };
#define timespecsubt(tvp, uvp, vvp) \ #define timespecsubt(tvp, uvp, vvp) \
@ -54,3 +69,10 @@ struct trussinfo
(vvp)->tv_nsec += 1000000000; \ (vvp)->tv_nsec += 1000000000; \
} \ } \
} while (0) } 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