summaryrefslogtreecommitdiffstats
path: root/usr.bin/truss
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2008-05-16 15:34:06 +0000
committerjhb <jhb@FreeBSD.org>2008-05-16 15:34:06 +0000
commit697ba009c1ef04ed9c402d207914b5edf574fad0 (patch)
treeb0307ce830d4958d3a7ad66908dcf16ee56adbdd /usr.bin/truss
parent0e99128934a93076b49efa4bef1c1d97b81e3398 (diff)
downloadFreeBSD-src-697ba009c1ef04ed9c402d207914b5edf574fad0.zip
FreeBSD-src-697ba009c1ef04ed9c402d207914b5edf574fad0.tar.gz
Teach truss about 32-bit FreeBSD and Linux binaries on amd64. Some
additional work is needed to handle ABI-specific syscall argument parsing, but this gets the basic tracing working. MFC after: 1 week
Diffstat (limited to 'usr.bin/truss')
-rw-r--r--usr.bin/truss/Makefile47
-rw-r--r--usr.bin/truss/amd64-fbsd32.c46
-rw-r--r--usr.bin/truss/amd64-linux32.c26
-rw-r--r--usr.bin/truss/amd64linux32.conf13
-rw-r--r--usr.bin/truss/extern.h4
-rw-r--r--usr.bin/truss/fbsd32.conf13
-rw-r--r--usr.bin/truss/main.c2
7 files changed, 108 insertions, 43 deletions
diff --git a/usr.bin/truss/Makefile b/usr.bin/truss/Makefile
index d1ae0ac..104cd96 100644
--- a/usr.bin/truss/Makefile
+++ b/usr.bin/truss/Makefile
@@ -4,23 +4,12 @@ WARNS?= 6
NO_WERROR=
PROG= truss
SRCS= main.c setup.c syscalls.c syscalls.h ioctl.c ${MACHINE_ARCH}-fbsd.c
-.if ${MACHINE_ARCH} == "i386"
-SRCS+= i386-linux.c linux_syscalls.h
-.endif
CFLAGS+= -I${.CURDIR} -I.
-CLEANFILES=i386l-syscalls.master syscalls.master linux_syscalls.h \
- syscalls.h ioctl.c
+CLEANFILES= syscalls.master syscalls.h ioctl.c
.SUFFIXES: .master
-i386l-syscalls.master: ${.CURDIR}/../../sys/i386/linux/syscalls.master
- cat ${.ALLSRC} > i386l-syscalls.master
-
-linux_syscalls.h: i386l-syscalls.master
- /bin/sh ${.CURDIR}/../../sys/kern/makesyscalls.sh i386l-syscalls.master \
- ${.CURDIR}/i386linux.conf
-
syscalls.master: ${.CURDIR}/../../sys/kern/syscalls.master
cat ${.ALLSRC} > syscalls.master
@@ -31,4 +20,38 @@ syscalls.h: syscalls.master
ioctl.c: ${.CURDIR}/../kdump/mkioctls
sh ${.CURDIR}/../kdump/mkioctls ${DESTDIR}/usr/include > ${.TARGET}
+.if ${MACHINE_ARCH} == "i386"
+SRCS+= i386-linux.c linux_syscalls.h
+CLEANFILES+=i386l-syscalls.master linux_syscalls.h
+
+i386l-syscalls.master: ${.CURDIR}/../../sys/i386/linux/syscalls.master
+ cat ${.ALLSRC} > ${.TARGET}
+
+linux_syscalls.h: i386l-syscalls.master
+ /bin/sh ${.CURDIR}/../../sys/kern/makesyscalls.sh ${.ALLSRC} \
+ ${.CURDIR}/i386linux.conf
+.endif
+
+.if ${MACHINE_ARCH} == "amd64"
+SRCS+= amd64-linux32.c linux32_syscalls.h
+CLEANFILES+=amd64l32-syscalls.master linux32_syscalls.h
+
+amd64l32-syscalls.master: ${.CURDIR}/../../sys/amd64/linux32/syscalls.master
+ cat ${.ALLSRC} > ${.TARGET}
+
+linux32_syscalls.h: amd64l32-syscalls.master
+ /bin/sh ${.CURDIR}/../../sys/kern/makesyscalls.sh ${.ALLSRC} \
+ ${.CURDIR}/amd64linux32.conf
+
+SRCS+= amd64-fbsd32.c freebsd32_syscalls.h
+CLEANFILES+=fbsd32-syscalls.master freebsd32_syscalls.h
+
+fbsd32-syscalls.master: ${.CURDIR}/../../sys/compat/freebsd32/syscalls.master
+ cat ${.ALLSRC} > ${.TARGET}
+
+freebsd32_syscalls.h: fbsd32-syscalls.master
+ /bin/sh ${.CURDIR}/../../sys/kern/makesyscalls.sh ${.ALLSRC} \
+ ${.CURDIR}/fbsd32.conf
+.endif
+
.include <bsd.prog.mk>
diff --git a/usr.bin/truss/amd64-fbsd32.c b/usr.bin/truss/amd64-fbsd32.c
index 4f0eabb..64157e3 100644
--- a/usr.bin/truss/amd64-fbsd32.c
+++ b/usr.bin/truss/amd64-fbsd32.c
@@ -64,9 +64,10 @@ static const char rcsid[] =
static int cpid = -1;
-#include "syscalls.h"
+#include "freebsd32_syscalls.h"
-static int nsyscalls = sizeof(syscallnames) / sizeof(syscallnames[0]);
+static int nsyscalls = sizeof(freebsd32_syscallnames) /
+ sizeof(freebsd32_syscallnames[0]);
/*
* This is what this particular file uses to keep track of a system call.
@@ -77,11 +78,12 @@ static int nsyscalls = sizeof(syscallnames) / sizeof(syscallnames[0]);
* 'struct syscall' describes the system call; it may be NULL, however,
* if we don't know about this particular system call yet.
*/
-static struct freebsd_syscall {
+static struct freebsd32_syscall {
struct syscall *sc;
const char *name;
int number;
unsigned long *args;
+ unsigned int *args32;
int nargs; /* number of arguments -- *not* number of words! */
char **s_args; /* the printable arguments */
} fsc;
@@ -92,6 +94,9 @@ clear_fsc(void) {
if (fsc.args) {
free(fsc.args);
}
+ if (fsc.args32) {
+ free(fsc.args32);
+ }
if (fsc.s_args) {
int i;
for (i = 0; i < fsc.nargs; i++)
@@ -110,11 +115,11 @@ clear_fsc(void) {
*/
void
-i386_syscall_entry(struct trussinfo *trussinfo, int nargs) {
+amd64_fbsd32_syscall_entry(struct trussinfo *trussinfo, int nargs) {
struct reg regs;
int syscall_num;
int i;
- unsigned int parm_offset;
+ unsigned long parm_offset;
struct syscall *sc = NULL;
struct ptrace_io_desc iorequest;
cpid = trussinfo->curthread->tid;
@@ -126,14 +131,14 @@ i386_syscall_entry(struct trussinfo *trussinfo, int nargs) {
fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
return;
}
- parm_offset = regs.r_esp + sizeof(int);
+ parm_offset = regs.r_rsp + sizeof(int);
/*
* FreeBSD has two special kinds of system call redirctions --
* SYS_syscall, and SYS___syscall. The former is the old syscall()
* routine, basicly; the latter is for quad-aligned arguments.
*/
- syscall_num = regs.r_eax;
+ syscall_num = regs.r_rax;
switch (syscall_num) {
case SYS_syscall:
syscall_num = ptrace(PT_READ_D, cpid, (caddr_t)parm_offset, 0);
@@ -147,7 +152,8 @@ i386_syscall_entry(struct trussinfo *trussinfo, int nargs) {
fsc.number = syscall_num;
fsc.name =
- (syscall_num < 0 || syscall_num > nsyscalls) ? NULL : syscallnames[syscall_num];
+ (syscall_num < 0 || syscall_num > nsyscalls) ? NULL :
+ freebsd32_syscallnames[syscall_num];
if (!fsc.name) {
fprintf(trussinfo->outfile, "-- UNKNOWN SYSCALL %d --\n", syscall_num);
}
@@ -163,15 +169,19 @@ i386_syscall_entry(struct trussinfo *trussinfo, int nargs) {
if (nargs == 0)
return;
- fsc.args = malloc((1+nargs) * sizeof(unsigned long));
+ fsc.args32 = malloc((1+nargs) * sizeof(unsigned int));
iorequest.piod_op = PIOD_READ_D;
iorequest.piod_offs = (void *)parm_offset;
- iorequest.piod_addr = fsc.args;
- iorequest.piod_len = (1+nargs) * sizeof(unsigned long);
+ iorequest.piod_addr = fsc.args32;
+ iorequest.piod_len = (1+nargs) * sizeof(unsigned int);
ptrace(PT_IO, cpid, (caddr_t)&iorequest, 0);
if (iorequest.piod_len == 0)
return;
+ fsc.args = malloc((1+nargs) * sizeof(unsigned long));
+ for (i = 0; i < nargs + 1; i++)
+ fsc.args[i] = fsc.args32[i];
+
if (fsc.name)
sc = get_syscall(fsc.name);
if (sc) {
@@ -223,13 +233,13 @@ i386_syscall_entry(struct trussinfo *trussinfo, int nargs) {
#endif
if (fsc.name != NULL &&
- (!strcmp(fsc.name, "execve") || !strcmp(fsc.name, "exit"))) {
+ (!strcmp(fsc.name, "freebsd32_execve") || !strcmp(fsc.name, "exit"))) {
/* XXX
* This could be done in a more general
* manner but it still wouldn't be very pretty.
*/
- if (!strcmp(fsc.name, "execve")) {
+ if (!strcmp(fsc.name, "freebsd32_execve")) {
if ((trussinfo->flags & EXECVEARGS) == 0)
if (fsc.s_args[1]) {
free(fsc.s_args[1]);
@@ -255,7 +265,7 @@ i386_syscall_entry(struct trussinfo *trussinfo, int nargs) {
*/
long
-i386_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused)
+amd64_fbsd32_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused)
{
struct reg regs;
long retval;
@@ -273,8 +283,8 @@ i386_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused)
return (-1);
}
- retval = regs.r_eax;
- errorp = !!(regs.r_eflags & PSL_C);
+ retval = regs.r_rax;
+ errorp = !!(regs.r_rflags & PSL_C);
/*
* This code, while simpler than the initial versions I used, could
@@ -315,12 +325,12 @@ i386_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused)
if (!errorp && fsc.nargs == 0 && fsc.name && strcmp(fsc.name, "pipe") == 0) {
fsc.nargs = 1;
fsc.s_args = malloc((1+fsc.nargs) * sizeof(char*));
- asprintf(&fsc.s_args[0], "[%d,%d]", (int)retval, regs.r_edx);
+ asprintf(&fsc.s_args[0], "[%d,%d]", (int)retval, (int)regs.r_rdx);
retval = 0;
}
if (fsc.name != NULL &&
- (!strcmp(fsc.name, "execve") || !strcmp(fsc.name, "exit"))) {
+ (!strcmp(fsc.name, "freebsd32_execve") || !strcmp(fsc.name, "exit"))) {
trussinfo->curthread->in_syscall = 1;
}
diff --git a/usr.bin/truss/amd64-linux32.c b/usr.bin/truss/amd64-linux32.c
index 1264439..163b141 100644
--- a/usr.bin/truss/amd64-linux32.c
+++ b/usr.bin/truss/amd64-linux32.c
@@ -61,10 +61,10 @@ static const char rcsid[] =
static int cpid = -1;
-#include "linux_syscalls.h"
+#include "linux32_syscalls.h"
static int nsyscalls =
- sizeof(linux_syscallnames) / sizeof(linux_syscallnames[0]);
+ sizeof(linux32_syscallnames) / sizeof(linux32_syscallnames[0]);
/*
* This is what this particular file uses to keep track of a system call.
@@ -105,7 +105,7 @@ clear_fsc(void) {
*/
void
-i386_linux_syscall_entry(struct trussinfo *trussinfo, int nargs) {
+amd64_linux32_syscall_entry(struct trussinfo *trussinfo, int nargs) {
struct reg regs;
int syscall_num;
int i;
@@ -120,11 +120,11 @@ i386_linux_syscall_entry(struct trussinfo *trussinfo, int nargs) {
fprintf(trussinfo->outfile, "-- CANNOT READ REGISTERS --\n");
return;
}
- syscall_num = regs.r_eax;
+ syscall_num = regs.r_rax;
fsc.number = syscall_num;
fsc.name =
- (syscall_num < 0 || syscall_num > nsyscalls) ? NULL : linux_syscallnames[syscall_num];
+ (syscall_num < 0 || syscall_num > nsyscalls) ? NULL : linux32_syscallnames[syscall_num];
if (!fsc.name) {
fprintf(trussinfo->outfile, "-- UNKNOWN SYSCALL %d --\n", syscall_num);
}
@@ -147,11 +147,11 @@ i386_linux_syscall_entry(struct trussinfo *trussinfo, int nargs) {
* that have more than five arguments?
*/
- fsc.args[0] = regs.r_ebx;
- fsc.args[1] = regs.r_ecx;
- fsc.args[2] = regs.r_edx;
- fsc.args[3] = regs.r_esi;
- fsc.args[4] = regs.r_edi;
+ fsc.args[0] = regs.r_rbx;
+ fsc.args[1] = regs.r_rcx;
+ fsc.args[2] = regs.r_rdx;
+ fsc.args[3] = regs.r_rsi;
+ fsc.args[4] = regs.r_rdi;
sc = get_syscall(fsc.name);
if (sc) {
@@ -242,7 +242,7 @@ const int bsd_to_linux_errno[] = {
};
long
-i386_linux_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused)
+amd64_linux32_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused)
{
struct reg regs;
long retval;
@@ -260,8 +260,8 @@ i386_linux_syscall_exit(struct trussinfo *trussinfo, int syscall_num __unused)
return (-1);
}
- retval = regs.r_eax;
- errorp = !!(regs.r_eflags & PSL_C);
+ retval = regs.r_rax;
+ errorp = !!(regs.r_rflags & PSL_C);
/*
* This code, while simpler than the initial versions I used, could
diff --git a/usr.bin/truss/amd64linux32.conf b/usr.bin/truss/amd64linux32.conf
new file mode 100644
index 0000000..7f5e8bd
--- /dev/null
+++ b/usr.bin/truss/amd64linux32.conf
@@ -0,0 +1,13 @@
+# $FreeBSD$
+
+sysnames="linux32_syscalls.h"
+sysproto="/dev/null"
+sysproto_h="/dev/null"
+syshdr="/dev/null"
+sysmk="/dev/null"
+syssw="/dev/null"
+syshide="/dev/null"
+syscallprefix="SYS_"
+switchname="sysent"
+namesname="linux32_syscallnames"
+systrace="/dev/null"
diff --git a/usr.bin/truss/extern.h b/usr.bin/truss/extern.h
index 3882f10..81e6317 100644
--- a/usr.bin/truss/extern.h
+++ b/usr.bin/truss/extern.h
@@ -44,6 +44,10 @@ extern long alpha_syscall_exit(struct trussinfo *, int);
#ifdef __amd64__
extern void amd64_syscall_entry(struct trussinfo *, int);
extern long amd64_syscall_exit(struct trussinfo *, int);
+extern void amd64_linux32_syscall_entry(struct trussinfo *, int);
+extern long amd64_linux32_syscall_exit(struct trussinfo *, int);
+extern void amd64_fbsd32_syscall_entry(struct trussinfo *, int);
+extern long amd64_fbsd32_syscall_exit(struct trussinfo *, int);
#endif
#ifdef __i386__
extern void i386_syscall_entry(struct trussinfo *, int);
diff --git a/usr.bin/truss/fbsd32.conf b/usr.bin/truss/fbsd32.conf
new file mode 100644
index 0000000..3323f11
--- /dev/null
+++ b/usr.bin/truss/fbsd32.conf
@@ -0,0 +1,13 @@
+# $FreeBSD$
+
+sysnames="freebsd32_syscalls.h"
+sysproto="/dev/null"
+sysproto_h="/dev/null"
+syshdr="/dev/null"
+sysmk="/dev/null"
+syssw="/dev/null"
+syshide="/dev/null"
+syscallprefix="SYS_"
+switchname="sysent"
+namesname="freebsd32_syscallnames"
+systrace="/dev/null"
diff --git a/usr.bin/truss/main.c b/usr.bin/truss/main.c
index 8924d8c..88ff02f 100644
--- a/usr.bin/truss/main.c
+++ b/usr.bin/truss/main.c
@@ -83,6 +83,8 @@ struct ex_types {
#endif
#ifdef __amd64__
{ "FreeBSD ELF64", amd64_syscall_entry, amd64_syscall_exit },
+ { "FreeBSD ELF32", amd64_fbsd32_syscall_entry, amd64_fbsd32_syscall_exit },
+ { "Linux ELF32", amd64_linux32_syscall_entry, amd64_linux32_syscall_exit },
#endif
#ifdef __i386__
{ "FreeBSD a.out", i386_syscall_entry, i386_syscall_exit },
OpenPOWER on IntegriCloud