Add FreeBSD support
diff --git a/CREDITS b/CREDITS
index 4ff1bc8..ed03b50 100644
--- a/CREDITS
+++ b/CREDITS
@@ -39,3 +39,4 @@
Florian Lohoff <flo@rfc822.org>
D.J. Barrow <djbarrow@de.ibm.com>
Topi Miettinen <Topi.Miettinen@nic.fi>
+ Gaël Roualland <gael.roualland@dial.oleane.com>
diff --git a/ChangeLog b/ChangeLog
index 12050bd..7f6d438 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2000-09-01 Wichert Akkerman <wakkerma@debian.org>
+
+ * lots of files: merge patch from Gaël Roualland to add
+ support for FreeBSD.
+
2000-08-09 Wichert Akkerman <wakkerma@debian.org>
* file.c: update to reflect that st_ino suddenly became a long long
diff --git a/Makefile.in b/Makefile.in
index 8b070f9..ca72d1d 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -20,7 +20,7 @@
LDFLAGS = @LDFLAGS@
WARNFLAGS = @WARNFLAGS@
-# OS is one of `linux', `sunos4', or `svr4'.
+# OS is one of `linux', `sunos4', `svr4', or `freebsd'.
OS = @opsys@
# ARCH is one of `i386', `m68k', `sparc', `arm', `mips' or `ia64'.
ARCH = @arch@
@@ -47,7 +47,7 @@
INCLUDES = -I. -I$(OS)/$(ARCH) -I$(srcdir)/$(OS)/$(ARCH) -I$(OS) -I$(srcdir)/$(OS)
SUBDIRS = $(OSARCH)
-ALL_SUBDIRS = test linux linux/alpha linux/powerpc sunos4 svr4
+ALL_SUBDIRS = test linux linux/alpha linux/powerpc sunos4 svr4 freebsd/i386
OBJ = strace.o version.o syscall.o util.o \
desc.o file.o ipc.o io.o ioctl.o mem.o net.o process.o bjm.o \
resource.o signal.o sock.o system.o term.o time.o proc.o stream.o
diff --git a/acconfig.h b/acconfig.h
index 2a711d9..b86ddfa 100644
--- a/acconfig.h
+++ b/acconfig.h
@@ -9,6 +9,9 @@
or a derivative like Solaris 2.x or Irix 5.x. */
#undef SVR4
+/* Define if this is running the FreeBSD operating system. */
+#undef FREEBSD
+
/* Define for UnixWare systems. */
#undef UNIXWARE
diff --git a/configure.in b/configure.in
index c59e583..9f74a54 100644
--- a/configure.in
+++ b/configure.in
@@ -22,6 +22,9 @@
irix[56]*)
opsys=svr4
;;
+freebsd*)
+ opsys=freebsd
+ ;;
*)
AC_MSG_ERROR(this operating system is not yet supported by strace)
;;
@@ -30,7 +33,7 @@
# Autoheader trick. Heh, heh.
opsys_list='
-@@@syms="$syms LINUX SUNOS4 SVR4"@@@
+@@@syms="$syms LINUX SUNOS4 SVR4 FREEBSD"@@@
'
AC_MSG_CHECKING(for supported architecture)
@@ -148,7 +151,7 @@
AC_CHECK_LIB(nsl, main)
fi
AC_CHECK_FUNCS(sigaction strerror strsignal pread sys_siglist _sys_siglist getdents mctl putpmsg prctl sendmsg inet_ntop)
-AC_CHECK_HEADERS(sys/reg.h sys/filio.h sys/acl.h sys/asynch.h sys/door.h sys/stream.h sys/tiuser.h sys/sysconfig.h asm/sigcontext.h ioctls.h sys/ioctl.h sys/ptrace.h termio.h linux/ptrace.h asm/reg.h linux/icmp.h linux/in6.h sys/uio.h linux/netlink.h linux/if_packet.h sys/poll.h)
+AC_CHECK_HEADERS(sys/reg.h sys/filio.h sys/acl.h sys/asynch.h sys/door.h sys/stream.h sys/tiuser.h sys/sysconfig.h asm/sigcontext.h ioctls.h sys/ioctl.h sys/ptrace.h termio.h linux/ptrace.h asm/reg.h linux/icmp.h linux/in6.h sys/uio.h linux/netlink.h linux/if_packet.h sys/poll.h sys/vfs.h)
AC_DECL_SYS_ERRLIST
AC_DECL_SYS_SIGLIST
AC_DECL__SYS_SIGLIST
diff --git a/defs.h b/defs.h
index 906d62e..4dbed04 100644
--- a/defs.h
+++ b/defs.h
@@ -84,12 +84,30 @@
# endif
#endif
-#ifdef SVR4
+#if defined(SVR4) || defined(FREEBSD)
+#define USE_PROCFS
+#else
+#undef USE_PROCFS
+#endif
+
+#ifdef FREEBSD
+#ifndef I386
+#error "FreeBSD support is only for i386 arch right now."
+#endif
+#include <machine/psl.h>
+#include <machine/reg.h>
+#include <sys/syscall.h>
+#endif
+
+#ifdef USE_PROCFS
#include <sys/procfs.h>
#ifdef HAVE_MP_PROCFS
#include <sys/uio.h>
#endif
-#else /* !SVR4 */
+#ifdef FREEBSD
+#include <sys/pioctl.h>
+#endif /* FREEBSD */
+#else /* !USE_PROCFS */
#if defined(LINUXSPARC) && defined(__GLIBC__)
#include <sys/ptrace.h>
#else
@@ -184,6 +202,22 @@
#define PR_FLAGS pr_flags
#endif
#endif
+#ifdef FREEBSD
+#define IOCTL ioctl
+#define IOCTL_STATUS(t) ioctl (t->pfd, PIOCSTATUS, &t->status)
+#define IOCTL_WSTOP(t) ioctl (t->pfd, PIOCWAIT, &t->status)
+#define PIOCRUN PIOCCONT
+#define PIOCWSTOP PIOCWAIT
+#define PR_WHY why
+#define PR_WHAT val
+#define PR_FLAGS flags
+/* from /usr/src/sys/miscfs/procfs/procfs_vnops.c,
+ status.state = 0 for running, 1 for stopped */
+#define PR_SYSENTRY S_SCE
+#define PR_SYSEXIT S_SCX
+#define PR_SIGNALLED S_SIG
+#define PR_FAULTED S_CORE
+#endif
/* Trace Control Block */
struct tcb {
@@ -219,6 +253,11 @@
prstatus_t status; /* procfs status structure */
#endif
#endif
+#ifdef FREEBSD
+ struct procfs_status status;
+ int pfd_reg;
+ int pfd_status;
+#endif
};
/* TCB flags */
@@ -269,8 +308,10 @@
#define RVAL_HEX 001 /* hex format */
#define RVAL_OCTAL 002 /* octal format */
#define RVAL_UDECIMAL 003 /* unsigned decimal format */
-#define RVAL_LDECIMAL 004 /* long long format */
- /* Maybe add long long hex, octal, unsigned */
+#define RVAL_LDECIMAL 004 /* long decimal format */
+#define RVAL_LHEX 005 /* long hex format */
+#define RVAL_LOCTAL 006 /* long octal format */
+#define RVAL_LUDECIMAL 007 /* long unsigned decimal format */
#define RVAL_MASK 007 /* mask for these values */
#define RVAL_STR 010 /* Print `auxstr' field after return val */
@@ -315,6 +356,7 @@
extern void set_overhead P((int));
extern void qualify P((char *));
extern void newoutf P((struct tcb *));
+extern int get_scno P((struct tcb *));
extern int trace_syscall P((struct tcb *));
extern void printxval P((struct xlat *, int, char *));
extern int printargs P((struct tcb *));
@@ -375,7 +417,7 @@
#if !(defined(LINUX) && !defined(SPARC))
extern long getrval2 P((struct tcb *));
#endif
-#ifdef SVR4
+#ifdef USE_PROCFS
extern int proc_open P((struct tcb *tcp, int attaching));
#endif
diff --git a/file.c b/file.c
index a53d229..a74beda 100644
--- a/file.c
+++ b/file.c
@@ -120,7 +120,15 @@
# include <sys/cred.h>
#endif /* SVR4 */
+#ifdef HAVE_SYS_VFS_H
#include <sys/vfs.h>
+#endif
+
+#ifdef FREEBSD
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#endif
#ifdef MAJOR_IN_SYSMACROS
#include <sys/sysmacros.h>
@@ -222,6 +230,12 @@
#endif
#ifdef FNOCTTY
{ FNOCTTY, "FNOCTTY" },
+#endif
+#ifdef O_SHLOCK
+ { O_SHLOCK, "O_SHLOCK" },
+#endif
+#ifdef O_EXLOCK
+ { O_EXLOCK, "O_EXLOCK" },
#endif
{ 0, NULL },
};
@@ -339,14 +353,33 @@
sys_lseek(tcp)
struct tcb *tcp;
{
+ off_t offset;
+ int _whence;
+
if (entering(tcp)) {
tprintf("%ld, ", tcp->u_arg[0]);
- if (tcp->u_arg[2] == SEEK_SET)
- tprintf("%lu, ", tcp->u_arg[1]);
+#ifndef FREEBSD
+ offset = tcp->u_arg[1];
+ _whence = tcp->u_arg[2];
+ if (_whence == SEEK_SET)
+ tprintf("%lu, ", offset);
else
- tprintf("%ld, ", tcp->u_arg[1]);
- printxval(whence, tcp->u_arg[2], "SEEK_???");
- }
+ tprintf("%ld, ", offset);
+#else /* FREEBSD */
+ offset = ((off_t) tcp->u_arg[1] << 32) + tcp->u_arg[2];
+ _whence = tcp->u_arg[4];
+ if (_whence == SEEK_SET)
+ tprintf("%llu, ", offset);
+ else
+ tprintf("%lld, ", offset);
+#endif
+ printxval(whence, _whence, "SEEK_???");
+ }
+#ifdef FREEBSD
+ else
+ if (!syserror(tcp))
+ return RVAL_LUDECIMAL;
+#endif /* FREEBSD */
return RVAL_UDECIMAL;
}
@@ -383,7 +416,11 @@
{
if (entering(tcp)) {
printpath(tcp, tcp->u_arg[0]);
+#ifndef FREEBSD
tprintf(", %lu", tcp->u_arg[1]);
+#else
+ tprintf(", %llu", ((off_t) tcp->u_arg[1] << 32) + tcp->u_arg[2]);
+#endif
}
return 0;
}
@@ -393,7 +430,12 @@
struct tcb *tcp;
{
if (entering(tcp)) {
+#ifndef FREEBSD
tprintf("%ld, %lu", tcp->u_arg[0], tcp->u_arg[1]);
+#else
+ tprintf("%ld, %llu", tcp->u_arg[0],
+ ((off_t) tcp->u_arg[1] << 32) + tcp->u_arg[2]);
+#endif
}
return 0;
}
@@ -534,6 +576,50 @@
}
#endif /* LINUXSPARC */
+#ifdef FREEBSD
+static struct xlat fileflags[] = {
+ { UF_NODUMP, "UF_NODUMP" },
+ { UF_IMMUTABLE, "UF_IMMUTABLE" },
+ { UF_APPEND, "UF_APPEND" },
+ { UF_OPAQUE, "UF_OPAQUE" },
+ { UF_NOUNLINK, "UF_NOUNLINK" },
+ { SF_ARCHIVED, "SF_ARCHIVED" },
+ { SF_IMMUTABLE, "SF_IMMUTABLE" },
+ { SF_APPEND, "SF_APPEND" },
+ { SF_NOUNLINK, "SF_NOUNLINK" },
+ { 0, NULL },
+};
+
+int
+sys_chflags(tcp)
+struct tcb *tcp;
+{
+ if (entering(tcp)) {
+ printpath(tcp, tcp->u_arg[0]);
+ tprintf(", ");
+ if (tcp->u_arg[1])
+ printflags(fileflags, tcp->u_arg[1]);
+ else
+ tprintf("0");
+ }
+ return 0;
+}
+
+int
+sys_fchflags(tcp)
+struct tcb *tcp;
+{
+ if (entering(tcp)) {
+ tprintf("%ld, ", tcp->u_arg[0]);
+ if (tcp->u_arg[1])
+ printflags(fileflags, tcp->u_arg[1]);
+ else
+ tprintf("0");
+ }
+ return 0;
+}
+#endif
+
static void
realprintstat(tcp, statbuf)
struct tcb *tcp;
@@ -577,7 +663,17 @@
if (!abbrev(tcp)) {
tprintf("st_atime=%s, ", sprinttime(statbuf->st_atime));
tprintf("st_mtime=%s, ", sprinttime(statbuf->st_mtime));
+#ifndef FREEBSD
tprintf("st_ctime=%s}", sprinttime(statbuf->st_ctime));
+#else /* FREEBSD */
+ tprintf("st_ctime=%s, ", sprinttime(statbuf->st_ctime));
+ tprintf("st_flags=");
+ if (statbuf->st_flags) {
+ printflags(fileflags, statbuf->st_flags);
+ } else
+ tprintf("0");
+ tprintf(", st_gen=%u}", statbuf->st_gen);
+#endif /* FREEBSD */
}
else
tprintf("...}");
@@ -1581,6 +1677,21 @@
#endif /* linux */
+#ifdef FREEBSD
+struct xlat direnttypes[] = {
+ { DT_FIFO, "DT_FIFO" },
+ { DT_CHR, "DT_CHR" },
+ { DT_DIR, "DT_DIR" },
+ { DT_BLK, "DT_BLK" },
+ { DT_REG, "DT_REG" },
+ { DT_LNK, "DT_LNK" },
+ { DT_SOCK, "DT_SOCK" },
+ { DT_WHT, "DT_WHT" },
+ { 0, NULL },
+};
+
+#endif
+
int
sys_getdents(tcp)
struct tcb *tcp;
@@ -1635,6 +1746,15 @@
d->d_namlen, d->d_namlen, d->d_name);
}
#endif /* SUNOS4 */
+#ifdef FREEBSD
+ if (!abbrev(tcp)) {
+ tprintf("%s{d_fileno=%u, d_reclen=%u, d_type=",
+ i ? " " : "", d->d_fileno, d->d_reclen);
+ printxval(direnttypes, d->d_type, "DT_???");
+ tprintf(", d_namlen=%u, d_name=\"%.*s\"}",
+ d->d_namlen, d->d_namlen, d->d_name);
+ }
+#endif /* FREEBSD */
if (!d->d_reclen) {
tprintf("/* d_reclen == 0, problem here */");
break;
@@ -1651,8 +1771,62 @@
return 0;
}
-#ifdef linux
+#ifdef FREEBSD
+int
+sys_getdirentries(tcp)
+struct tcb * tcp;
+{
+ int i, len, dents = 0;
+ long basep;
+ char *buf;
+ if (entering(tcp)) {
+ tprintf("%lu, ", tcp->u_arg[0]);
+ return 0;
+ }
+ if (syserror(tcp) || !verbose(tcp)) {
+ tprintf("%#lx, %lu, %#lx", tcp->u_arg[1], tcp->u_arg[2], tcp->u_arg[3]);
+ return 0;
+ }
+ len = tcp->u_rval;
+ if ((buf = malloc(len)) == NULL) {
+ tprintf("out of memory\n");
+ return 0;
+ }
+ if (umoven(tcp, tcp->u_arg[1], len, buf) < 0) {
+ tprintf("{...}, %lu, %#lx", tcp->u_arg[2], tcp->u_arg[3]);
+ free(buf);
+ return 0;
+ }
+ if (!abbrev(tcp))
+ tprintf("{");
+ for (i = 0; i < len;) {
+ struct kernel_dirent *d = (struct kernel_dirent *) &buf[i];
+ if (!abbrev(tcp)) {
+ tprintf("%s{d_fileno=%u, d_reclen=%u, d_type=",
+ i ? " " : "", d->d_fileno, d->d_reclen);
+ printxval(direnttypes, d->d_type, "DT_???");
+ tprintf(", d_namlen=%u, d_name=\"%.*s\"}",
+ d->d_namlen, d->d_namlen, d->d_name);
+ }
+ i += d->d_reclen;
+ dents++;
+ }
+ if (!abbrev(tcp))
+ tprintf("}");
+ else
+ tprintf("/* %u entries */", dents);
+ free(buf);
+ tprintf(", %lu", tcp->u_arg[2]);
+ if (umove(tcp, tcp->u_arg[3], &basep) < 0)
+ tprintf(", %#lx", tcp->u_arg[3]);
+ else
+ tprintf(", [%lu]", basep);
+ return 0;
+}
+#endif
+
+#ifdef linux
int
sys_getcwd(tcp)
struct tcb *tcp;
@@ -1668,6 +1842,22 @@
}
#endif /* linux */
+#ifdef FREEBSD
+int
+sys___getcwd(tcp)
+struct tcb *tcp;
+{
+ if (exiting(tcp)) {
+ if (syserror(tcp))
+ tprintf("%#lx", tcp->u_arg[0]);
+ else
+ printpathn(tcp, tcp->u_arg[0], tcp->u_arg[1]);
+ tprintf(", %lu", tcp->u_arg[1]);
+ }
+ return 0;
+}
+#endif
+
#ifdef HAVE_SYS_ASYNCH_H
int
diff --git a/freebsd/.cvsignore b/freebsd/.cvsignore
new file mode 100644
index 0000000..f3c7a7c
--- /dev/null
+++ b/freebsd/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/freebsd/ioctlent.sh b/freebsd/ioctlent.sh
new file mode 100644
index 0000000..7d8a21c
--- /dev/null
+++ b/freebsd/ioctlent.sh
@@ -0,0 +1,62 @@
+#!/bin/sh
+
+# initialy from $FreeBSD: src/usr.bin/kdump/mkioctls,v 1.18 2000/08/02 07:37:44 ru Exp $
+# changed by Gaël Roualland.
+
+# Validate arg count.
+if [ $# -ne 1 ]
+then
+ echo "usage: $0 include-directory" >&2
+ exit 1
+fi
+
+# build a list of files with ioctls
+ioctl_includes=`
+ cd $1
+ find * -name '*.h' -follow |
+ egrep -v '^(netns)/' |
+ xargs egrep -l \
+'^#[ ]*define[ ]+[A-Za-z_][A-Za-z0-9_]*[ ]+_IO[^a-z0-9_]'`
+
+# Generate the output file.
+echo '/* This file is automatically generated by ioctlent.sh */'
+echo
+echo '/* XXX obnoxious prerequisites. */'
+echo '#define COMPAT_43'
+echo
+echo '#include <sys/types.h>'
+echo '#include <sys/param.h>'
+echo '#include <sys/devicestat.h>'
+echo '#include <sys/disklabel.h>'
+echo '#include <sys/socket.h>'
+echo '#include <sys/time.h>'
+echo '#include <sys/tty.h>'
+echo '#include <net/ethernet.h>'
+echo '#include <net/if.h>'
+echo '#include <net/if_var.h>'
+echo '#include <net/route.h>'
+echo '#include <netatm/atm.h>'
+echo '#include <netatm/atm_if.h>'
+echo '#include <netatm/atm_sap.h>'
+echo '#include <netatm/atm_sys.h>'
+echo '#include <netinet/in.h>'
+echo '#include <netinet/ip_compat.h>'
+echo '#include <netinet/ip_fil.h>'
+echo '#include <netinet/ip_auth.h>'
+echo '#include <netinet/ip_nat.h>'
+echo '#include <netinet/ip_frag.h>'
+echo '#include <netinet/ip_state.h>'
+echo '#include <netinet/ip_mroute.h>'
+echo '#include <netinet6/in6_var.h>'
+echo '#include <netinet6/nd6.h>'
+echo '#include <netinet6/ip6_mroute.h>'
+echo '#include <cam/cam.h>'
+echo '#include <stdio.h>'
+echo
+echo "$ioctl_includes" | sed -e 's/^/#include </' -e s'/$/>/'
+echo
+echo 'struct ioctlent ioctlent [] ='
+echo '{'
+(cd $1 && for i in $ioctl_includes ; do echo "#include <$i>" | gcc -I$1 -E -dM - | egrep '^#[ ]*define[ ]+[A-Za-z_][A-Za-z0-9_]*[ ]+_IO[^a-z0-9_]' | sed -n -e 's|^#[ ]*define[ ]*\([A-Za-z_][A-Za-z0-9_]*\).*| { "'$i'", "\1", \1 },|p' ; done )
+
+echo '};'
diff --git a/freebsd/syscalls.cat b/freebsd/syscalls.cat
new file mode 100644
index 0000000..0dde7b6
--- /dev/null
+++ b/freebsd/syscalls.cat
@@ -0,0 +1,177 @@
+#
+# Copyright (c) 2000, Gaël Roualland <gael.roualland@iname.com>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# $Id$
+#
+# Syscalls categories
+# syntax: syscall catmask
+#
+# mostly built from other archs/os syscallent.h
+
+# file calls
+access TF
+acct TF
+acl TF
+chdir TF
+chmod TF
+chown TF
+chroot TF
+creat TF
+close TF
+chflags TF
+fstat64 TF
+fstat TF
+fchdir TF
+fchflags TF
+lchown TF
+link TF
+lstat TF
+lstat64 TF
+lxstat TF
+mkdir TF
+mknod TF
+mount TF
+oldlstat TF
+oldstat TF
+oldumount TF
+open TF
+outime TF
+pathconf TF
+pread TF
+pwrite TF
+readlink TF
+rename TF
+rmdir TF
+sendfile TF
+stat TF
+stat64 TF
+statfs TF
+statvfs TF
+swapon TF
+symlink TF
+truncate TF
+umount TF
+unlink TF
+unmount TF
+uselib TF
+utime TF
+utimes TF
+xmknod TF
+xstat TF
+
+# file/process calls
+exec TF|TP
+execv TF|TP
+execve TF|TP
+
+# IPC calls
+msgctl TI
+msgget TI
+msgrcv TI
+msgsnd TI
+msgsys TI
+semctl TI
+semget TI
+semop TI
+semsys TI
+shmat TI
+shmctl TI
+shmdt TI
+shmget TI
+shmsys TI
+
+# network calls
+accept TN
+bind TN
+connect TN
+getmsg TN
+getpeername TN
+getpmsg TN
+getsockname TN
+getsockopt TN
+listen TN
+poll TN
+putmsg TN
+putpmsg TN
+recv TN
+recvfrom TN
+recvmsg TN
+send TN
+sendmsg TN
+sendto TN
+setsockopt TN
+shutdown TN
+socket TN
+socketpair TN
+
+# process calls
+_exit TP
+clone TP
+fork TP
+fork1 TP
+owait TP
+owait3 TP
+vfork TP
+wait TP
+wait4 TP
+waitid TP
+waitpid TP
+waitsys TP
+
+# signal calls
+kill TS
+killpg TS
+ksigqueue TS
+pause TS
+rt_sigaction TS
+rt_sigpending TS
+rt_sigprocmask TS
+rt_sigqueueinfo TS
+rt_sigreturn TS
+rt_sigsuspend TS
+rt_sigtimedwait TS
+sigaction TS
+sigaltstack TS
+sigblock TS
+sigcleanup TS
+sigfillset TS
+siggetmask TS
+sighold TS
+sigignore TS
+signal TS
+sigpause TS
+sigpending TS
+sigpoll TS
+sigprocmask TS
+sigrelse TS
+sigreturn TS
+sigsendset TS
+sigset TS
+sigsetmask TS
+sigstack TS
+sigsuspend TS
+sigtimedwait TS
+sigvec TS
diff --git a/freebsd/syscalls.pl b/freebsd/syscalls.pl
new file mode 100644
index 0000000..0b072a9
--- /dev/null
+++ b/freebsd/syscalls.pl
@@ -0,0 +1,151 @@
+#!/usr/bin/perl -w
+#
+# Copyright (c) 2000, Gaël Roualland <gael.roualland@iname.com>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# $Id$
+#/
+
+# Buils syscall.h and syscallent.h from:
+# - syscalls.cat containing lines of format: syscall catmask
+# - syscalls.print containing lines of format: syscall [printfunction]
+# if no printfunction is provided, sys_<call> is used.
+# - syscalls.master in the FreeBSD kernel source tree (/usr/src/sys/kern)
+
+use strict;
+use POSIX;
+
+use vars qw(%sysprint %syscat);
+
+sub usage() {
+ print STDERR
+ "usage: $0 syscalls.master [<syscalls.print>] [<syscalls.cat>]\n";
+ exit 1;
+}
+
+sub readprint ($) {
+ my($fprint) = @_;
+
+ open (PRINT, "< $fprint") || die "can't open $fprint: $!";
+ while(<PRINT>) {
+ chomp;
+ s/^\s*//;
+ s/\s+$//;
+ s/#.*$//;
+ my($sys, $func) = split(/\s+/);
+ if (defined($sys)) {
+ if (defined($func)) {
+ $sysprint{$sys} = $func;
+ } else {
+ $sysprint{$sys} = "sys_$sys";
+ }
+ }
+ }
+ close(PRINT);
+}
+
+sub readcat ($) {
+ my($fcat) = @_;
+
+ open (CAT, "< $fcat") || die "can't open $fcat: $!";
+ while(<CAT>) {
+ chomp;
+ s/^\s*//;
+ s/\s+$//;
+ s/#.*$//;
+ my($sys, $cat) = split(/\s+/);
+ $syscat{$sys} = $cat if (defined($sys) && defined($cat));
+ }
+ close(CAT);
+}
+
+
+usage if (!defined($ARGV[0]) || defined($ARGV[3]));
+
+%sysprint = ();
+readprint $ARGV[1] if defined $ARGV[1];
+
+%syscat = ();
+readcat $ARGV[2] if defined $ARGV[2];
+
+open(MASTER, "< $ARGV[0]") || die "can't open $ARGV[0]: $!";
+
+open(SYSCALL, "> syscall.h") || die "can't create syscall.h: $!";
+
+print SYSCALL "/*\n * Automatically generated by $0 on " . ctime(time()) . " */\n\n";
+print "/*\n * Automatically generated by $0 on " . ctime(time()) . " */\n\n";
+
+my $sysnum = 0;
+
+while (<MASTER>) {
+ chomp;
+ # join broken lines
+ while (/\\$/) {
+ my $line;
+ s/\\$//;
+ $line = <MASTER>;
+ chomp($line);
+ $_ = "$_$line";
+ }
+
+ if (/^(\d+)\s+\w+\s+\w+\s+\{\s*([^}]+)\s*\}([^}]*)$/) {
+ my($proto, $ext, $name, $nargs, @args, $pfunc, $cat);
+
+ $proto = $2;
+ $ext = $3;
+
+ if ($1 > $sysnum) { # syscall gap
+ while($sysnum < $1) {
+ print " { -1,\t0,\tprintargs,\t\"SYS_$sysnum\"\t}, /* $sysnum */\n";
+ $sysnum++;
+ }
+ } elsif ($1 < $sysnum) {
+ warn "error in master file: syscall $1 found, expecting $sysnum.";
+ }
+
+ if ($proto =~ /^[^\s]+\s+([^\s]+)\s*\(([^)]*)\);/) {
+ my @args = split(/,/, $2);
+ $nargs = @args;
+ $name = $1;
+ $name = $1 if ($ext =~ /^\s*([^\s]+)\s+[^\s]+\s+[^\s]+$/);
+ if (defined($sysprint{$name})) {
+ $pfunc = $sysprint{$name};
+ print SYSCALL "int $pfunc();\n";
+ } else {
+ $pfunc = "sys_$name";
+ print SYSCALL "#define $pfunc printargs\n";
+ }
+ if (defined($syscat{$name})) {
+ $cat = $syscat{$name};
+ } else {
+ $cat = "0";
+ }
+ print " { $nargs,\t$cat,\t$pfunc,\t\"$name\"\t}, /* $sysnum */\n";
+ $sysnum++;
+ } else {
+ warn "bad syscall specification for $sysnum: $proto";
+ }
+ }
+}
diff --git a/freebsd/syscalls.print b/freebsd/syscalls.print
new file mode 100644
index 0000000..bc59a6f
--- /dev/null
+++ b/freebsd/syscalls.print
@@ -0,0 +1,192 @@
+#
+# Copyright (c) 2000, Gaël Roualland <gael.roualland@iname.com>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# $Id$
+#
+# Printable syscalls
+# syntax: syscall [printfunc]
+#
+# mostly built from sys_* functions in source code
+
+__getcwd
+__sysctl
+accept
+access
+adjtime
+alarm
+bind
+brk
+capget
+capset
+chdir
+chflags
+chmod
+chown
+chroot
+close
+connect
+creat
+dup
+dup2
+errlist
+execv
+execve
+exit
+fchdir
+fchflags
+fchmod
+fchown
+fchroot
+fcntl
+flock
+fork
+fpathconf
+fstat
+fstatfs
+fsync
+ftruncate
+getdents
+getdirentries
+getdomainname
+getdtablesize
+getgid
+getgroups
+gethostid
+gethostname
+getitimer
+getpagesize
+getpeername
+getpgid
+getpgrp
+getpid
+getpriority
+getrlimit
+getrusage
+getsid
+getsockname
+getsockopt
+gettimeofday
+getuid
+indir
+ioctl
+kill
+killpg
+link
+listen
+lseek
+lstat
+mincore
+mkdir
+mkfifo
+mknod
+mmap
+mprotect
+msgctl
+msgget
+msgrcv
+msgsnd
+msync
+munmap
+nerr
+nice
+open
+pathconf
+pipe
+poll
+pread
+ptrace
+pwrite
+quotactl
+read
+readlink
+readv
+recv
+recvfrom
+recvmsg
+rename
+rmdir
+sbrk
+select
+semctl
+semget
+semop
+send
+sendfile
+sendmsg
+sendto
+setdomainname
+setgroups
+sethostname
+setitimer
+setpgid
+setpgrp
+setpriority
+setregid
+setresgid
+setresuid
+setreuid
+setrlimit
+setsid
+setsockopt
+settimeofday
+shmat
+shmctl
+shmdt
+shmget
+shutdown
+sigaction
+sigaltstack
+sigblock
+sigcleanup
+signal
+sigpause
+sigpending
+sigprocmask
+sigsetmask
+sigstack
+sigsuspend
+sigvec
+socket
+socketpair
+stat
+statfs
+stime
+symlink
+sysctl
+time
+times
+truncate
+umask
+uname
+unlink
+utime
+utimes
+vfork
+wait
+wait4
+waitpid
+write
+writev
diff --git a/io.c b/io.c
index 45c3413..a819c11 100644
--- a/io.c
+++ b/io.c
@@ -63,13 +63,47 @@
return 0;
}
+void
+tprint_iov(tcp, len, addr)
+struct tcb * tcp;
+int len;
+char * addr;
+{
+ struct iovec *iov;
+ int i;
+
+
+ if (!len) {
+ tprintf("[]");
+ return;
+ }
+
+ if ((iov = (struct iovec *) malloc(len * sizeof *iov)) == NULL) {
+ fprintf(stderr, "No memory");
+ return;
+ }
+ if (umoven(tcp, (int) addr,
+ len * sizeof *iov, (char *) iov) < 0) {
+ tprintf("%#lx", tcp->u_arg[1]);
+ } else {
+ tprintf("[");
+ for (i = 0; i < len; i++) {
+ if (i)
+ tprintf(", ");
+ tprintf("{");
+ printstr(tcp, (long) iov[i].iov_base,
+ iov[i].iov_len);
+ tprintf(", %lu}", (unsigned long)iov[i].iov_len);
+ }
+ tprintf("]");
+ }
+ free((char *) iov);
+}
+
int
sys_readv(tcp)
struct tcb *tcp;
{
- struct iovec *iov;
- int i, len;
-
if (entering(tcp)) {
tprintf("%ld, ", tcp->u_arg[0]);
} else {
@@ -78,27 +112,7 @@
tcp->u_arg[1], tcp->u_arg[2]);
return 0;
}
- len = tcp->u_arg[2];
- if ((iov = (struct iovec *) malloc(len * sizeof *iov)) == NULL) {
- fprintf(stderr, "No memory");
- return 0;
- }
- if (umoven(tcp, tcp->u_arg[1],
- len * sizeof *iov, (char *) iov) < 0) {
- tprintf("%#lx", tcp->u_arg[1]);
- } else {
- tprintf("[");
- for (i = 0; i < len; i++) {
- if (i)
- tprintf(", ");
- tprintf("{");
- printstr(tcp, (long) iov[i].iov_base,
- iov[i].iov_len);
- tprintf(", %lu}", (unsigned long)iov[i].iov_len);
- }
- tprintf("]");
- }
- free((char *) iov);
+ tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
tprintf(", %lu", tcp->u_arg[2]);
}
return 0;
@@ -108,39 +122,15 @@
sys_writev(tcp)
struct tcb *tcp;
{
- struct iovec *iov;
- int i, len;
-
if (entering(tcp)) {
tprintf("%ld, ", tcp->u_arg[0]);
- len = tcp->u_arg[2];
- iov = (struct iovec *) malloc(len * sizeof *iov);
- if (iov == NULL) {
- fprintf(stderr, "No memory");
- return 0;
- }
- if (umoven(tcp, tcp->u_arg[1],
- len * sizeof *iov, (char *) iov) < 0) {
- tprintf("%#lx", tcp->u_arg[1]);
- } else {
- tprintf("[");
- for (i = 0; i < len; i++) {
- if (i)
- tprintf(", ");
- tprintf("{");
- printstr(tcp, (long) iov[i].iov_base,
- iov[i].iov_len);
- tprintf(", %lu}", (unsigned long)iov[i].iov_len);
- }
- tprintf("]");
- }
- free((char *) iov);
+ tprint_iov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
tprintf(", %lu", tcp->u_arg[2]);
}
return 0;
}
-#ifdef SVR4
+#if defined(SVR4) || defined(FREEBSD)
int
sys_pread(tcp)
@@ -157,9 +147,14 @@
/* off_t is signed int */
tprintf(", %lu, %ld", tcp->u_arg[2], tcp->u_arg[3]);
#else
+#ifndef FREEBSD
tprintf(", %lu, %llu", tcp->u_arg[2],
(((unsigned long long) tcp->u_arg[4]) << 32
| tcp->u_arg[3]));
+#else
+ tprintf(", %lu, %llu", tcp->u_arg[2],
+ (((off_t) tcp->u_arg[3]) << 32) + tcp->u_arg[4]);
+#endif
#endif
}
return 0;
@@ -176,14 +171,61 @@
/* off_t is signed int */
tprintf(", %lu, %ld", tcp->u_arg[2], tcp->u_arg[3]);
#else
+#ifndef FREEBSD
tprintf(", %lu, %llu", tcp->u_arg[2],
(((unsigned long long) tcp->u_arg[4]) << 32
| tcp->u_arg[3]));
+#else
+ tprintf(", %lu, %llu", tcp->u_arg[2],
+ (((off_t) tcp->u_arg[3]) << 32) + tcp->u_arg[4]);
+#endif
#endif
}
return 0;
}
-#endif /* SVR4 */
+#endif /* SVR4 || FREEBSD */
+
+#ifdef FREEBSD
+#include <sys/types.h>
+#include <sys/socket.h>
+
+int
+sys_sendfile(tcp)
+struct tcb *tcp;
+{
+ if (entering(tcp)) {
+ tprintf("%ld, %ld, %llu, %lu", tcp->u_arg[0], tcp->u_arg[1],
+ (((unsigned long long) tcp->u_arg[3]) << 32 |
+ tcp->u_arg[2]), tcp->u_arg[4]);
+ } else {
+ off_t offset;
+
+ if (!tcp->u_arg[5])
+ tprintf(", NULL");
+ else {
+ struct sf_hdtr hdtr;
+
+ if (umove(tcp, tcp->u_arg[5], &hdtr) < 0)
+ tprintf(", %#lx", tcp->u_arg[5]);
+ else {
+ tprintf(", { ");
+ tprint_iov(tcp, hdtr.hdr_cnt, hdtr.headers);
+ tprintf(", %u, ", hdtr.hdr_cnt);
+ tprint_iov(tcp, hdtr.trl_cnt, hdtr.trailers);
+ tprintf(", %u }", hdtr.hdr_cnt);
+ }
+ }
+ if (!tcp->u_arg[6])
+ tprintf(", NULL");
+ else if (umove(tcp, tcp->u_arg[6], &offset) < 0)
+ tprintf(", %#lx", tcp->u_arg[6]);
+ else
+ tprintf(", [%llu]", offset);
+ tprintf(", %lu", tcp->u_arg[7]);
+ }
+ return 0;
+}
+#endif /* FREEBSD */
#ifdef LINUX
int
diff --git a/ioctl.c b/ioctl.c
index f4bb784..ed2a32b 100644
--- a/ioctl.c
+++ b/ioctl.c
@@ -105,15 +105,22 @@
#ifdef LINUX
case 0x89:
#else /* !LINUX */
- case 'r': case 's': case 'i': case 'p':
+ case 'r': case 's': case 'i':
+#ifndef FREEBSD
+ case 'p':
+#endif
#endif /* !LINUX */
return sock_ioctl(tcp, code, arg);
-#ifdef SVR4
+#ifdef USE_PROCFS
#ifndef HAVE_MP_PROCFS
+#ifndef FREEBSD
case 'q':
+#else
+ case 'p':
+#endif
return proc_ioctl(tcp, code, arg);
#endif
-#endif /* SVR4 */
+#endif /* USE_PROCFS */
#ifdef HAVE_SYS_STREAM_H
case 'S':
return stream_ioctl(tcp, code, arg);
diff --git a/ipc.c b/ipc.c
index e4dacab..06688f0 100644
--- a/ipc.c
+++ b/ipc.c
@@ -32,7 +32,7 @@
#include "defs.h"
-#if defined(LINUX) || defined(SUNOS4)
+#if defined(LINUX) || defined(SUNOS4) || defined(FREEBSD)
#include <sys/ipc.h>
#include <sys/sem.h>
@@ -98,8 +98,12 @@
{ SHM_STAT, "SHM_STAT" },
{ SHM_INFO, "SHM_INFO" },
#endif /* LINUX */
+#ifdef SHM_LOCK
{ SHM_LOCK, "SHM_LOCK" },
+#endif
+#ifdef SHM_UNLOCK
{ SHM_UNLOCK, "SHM_UNLOCK" },
+#endif
{ 0, NULL },
};
@@ -352,4 +356,4 @@
return 0;
}
-#endif /* defined(LINUX) || defined(SUNOS4) */
+#endif /* defined(LINUX) || defined(SUNOS4) || defined(FREEBSD) */
diff --git a/mem.c b/mem.c
index 73a72fc..0d72870 100644
--- a/mem.c
+++ b/mem.c
@@ -134,6 +134,22 @@
#ifdef MAP_LOCKED
{ MAP_LOCKED,"MAP_LOCKED"},
#endif
+ /* FreeBSD ones */
+#ifdef MAP_ANON
+ { MAP_ANON, "MAP_ANON" },
+#endif
+#ifdef MAP_HASSEMAPHORE
+ { MAP_HASSEMAPHORE, "MAP_HASSEMAPHORE" },
+#endif
+#ifdef MAP_STACK
+ { MAP_STACK, "MAP_STACK" },
+#endif
+#ifdef MAP_NOSYNC
+ { MAP_NOSYNC, "MAP_NOSYNC" },
+#endif
+#ifdef MAP_NOCORE
+ { MAP_NOCORE, "MAP_NOCORE" },
+#endif
{ 0, NULL },
};
@@ -155,8 +171,12 @@
printflags(mmap_prot, u_arg[2]);
tprintf(", ");
/* flags */
+#ifdef MAP_TYPE
printxval(mmap_flags, u_arg[3] & MAP_TYPE, "MAP_???");
addflags(mmap_flags, u_arg[3] & ~MAP_TYPE);
+#else
+ printflags(mmap_flags, u_arg[3]);
+#endif
/* fd */
tprintf(", %ld, ", u_arg[4]);
/* offset */
diff --git a/net.c b/net.c
index db88c6d..da061c8 100644
--- a/net.c
+++ b/net.c
@@ -36,6 +36,9 @@
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
+#ifdef FREEBSD
+#include <netinet/tcp.h>
+#endif
#include <arpa/inet.h>
#if defined(LINUX)
#include <asm/types.h>
diff --git a/proc.c b/proc.c
index d4969a6..854657d 100644
--- a/proc.c
+++ b/proc.c
@@ -186,3 +186,88 @@
#endif /* HAVE_MP_PROCFS */
#endif /* SVR4 */
+#ifdef FREEBSD
+#include <sys/pioctl.h>
+
+static struct xlat proc_status_why[] = {
+ { S_EXEC, "S_EXEC" },
+ { S_SIG, "S_SIG" },
+ { S_SCE, "S_SCE" },
+ { S_SCX, "S_SCX" },
+ { S_CORE, "S_CORE" },
+ { S_EXIT, "S_EXIT" },
+ { 0, NULL }
+};
+
+static struct xlat proc_status_flags[] = {
+ { PF_LINGER, "PF_LINGER" },
+ { PF_ISUGID, "PF_ISUGID" },
+ { 0, NULL }
+};
+
+int
+proc_ioctl(tcp, code, arg)
+struct tcb *tcp;
+int code, arg;
+{
+ int val;
+ struct procfs_status status;
+
+ if (entering(tcp))
+ return 0;
+
+ switch (code) {
+ case PIOCSTATUS:
+ case PIOCWAIT:
+ if (arg == 0)
+ tprintf(", NULL");
+ else if (syserror(tcp))
+ tprintf(", %x", arg);
+ else if (umove(tcp, arg, &status) < 0)
+ tprintf(", {...}");
+ else {
+ tprintf(", {state=%d, flags=", status.state);
+ if (!printflags(proc_status_flags, status.flags))
+ tprintf("0");
+ tprintf(", events=");
+ printflags(proc_status_why, status.events);
+ tprintf(", why=");
+ printxval(proc_status_why, status.why, "S_???");
+ tprintf(", val=%lu}", status.val);
+ }
+ return 1;
+ case PIOCBIS:
+ if (arg) {
+ tprintf(", ");
+ printflags(proc_status_why, arg);
+ } else
+ tprintf(", 0");
+ return 1;
+ return 1;
+ case PIOCSFL:
+ if (arg) {
+ tprintf(", ");
+ printflags(proc_status_flags, arg);
+ } else
+ tprintf(", 0");
+ return 1;
+ case PIOCGFL:
+ if (syserror(tcp))
+ tprintf(", %#x", arg);
+ else if (umove(tcp, arg, &val) < 0)
+ tprintf(", {...}");
+ else {
+ tprintf(", [");
+ if (val)
+ printflags(proc_status_flags, val);
+ else
+ tprintf("0");
+ tprintf("]");
+ }
+ return 1;
+ default:
+ /* ad naseum */
+ return 0;
+ }
+}
+#endif
diff --git a/process.c b/process.c
index b409fa1..dda3b9e 100644
--- a/process.c
+++ b/process.c
@@ -49,6 +49,10 @@
#include <machine/reg.h>
#endif /* SUNOS4 */
+#ifdef FREEBSD
+#include <sys/ptrace.h>
+#endif
+
#ifdef HAVE_SYS_REG_H
# include <sys/reg.h>
#ifndef PTRACE_PEEKUSR
@@ -333,7 +337,7 @@
return 0;
}
-#ifdef SVR4
+#ifdef USE_PROCFS
int
sys_fork(tcp)
@@ -372,12 +376,13 @@
fprintf(stderr, "sys_fork: tcb table full\n");
return 0;
}
- proc_open(tcpchild, 1);
+ if (proc_open(tcpchild, 1) < 0)
+ droptcb(tcpchild);
}
return 0;
}
-#else /* !SVR4 */
+#else /* !USE_PROCFS */
#ifdef LINUX
@@ -673,9 +678,9 @@
return 0;
}
-#endif /* !SVR4 */
+#endif /* !USE_PROCFS */
-#if defined(SUNOS4) || defined(LINUX)
+#if defined(SUNOS4) || defined(LINUX) || defined(FREEBSD)
int
sys_vfork(tcp)
@@ -686,7 +691,7 @@
return 0;
}
-#endif /* SUNOS4 || LINUX */
+#endif /* SUNOS4 || LINUX || FREEBSD */
#ifndef LINUX
@@ -832,7 +837,7 @@
return 0;
}
-#ifdef LINUX
+#if defined(LINUX) || defined(FREEBSD)
int
sys_setresuid(tcp)
struct tcb *tcp;
@@ -858,7 +863,7 @@
return 0;
}
-#endif /* LINUX */
+#endif /* LINUX || FREEBSD */
int
sys_setgroups(tcp)
@@ -1280,6 +1285,25 @@
#endif /* SVR4 */
+#ifdef FREEBSD
+int
+sys_wait(tcp)
+struct tcb *tcp;
+{
+ int status;
+
+ if (exiting(tcp)) {
+ if (!syserror(tcp)) {
+ if (umove(tcp, tcp->u_arg[0], &status) < 0)
+ tprintf("%#lx", tcp->u_arg[0]);
+ else
+ printstatus(status);
+ }
+ }
+ return 0;
+}
+#endif
+
int
sys_waitpid(tcp)
struct tcb *tcp;
@@ -1608,6 +1632,7 @@
#ifndef SVR4
static struct xlat ptrace_cmds[] = {
+#ifndef FREEBSD
{ PTRACE_TRACEME, "PTRACE_TRACEME" },
{ PTRACE_PEEKTEXT, "PTRACE_PEEKTEXT", },
{ PTRACE_PEEKDATA, "PTRACE_PEEKDATA", },
@@ -1653,9 +1678,29 @@
#endif /* !I386 */
{ PTRACE_GETUCODE, "PTRACE_GETUCODE" },
#endif /* SUNOS4 */
+#else /* FREEBSD */
+ { PT_TRACE_ME, "PT_TRACE_ME" },
+ { PT_READ_I, "PT_READ_I" },
+ { PT_READ_D, "PT_READ_D" },
+ { PT_WRITE_I, "PT_WRITE_I" },
+ { PT_WRITE_D, "PT_WRITE_D" },
+ { PT_READ_U, "PT_WRITE_U" },
+ { PT_CONTINUE, "PT_CONTINUE" },
+ { PT_KILL, "PT_KILL" },
+ { PT_STEP, "PT_STEP" },
+ { PT_ATTACH, "PT_ATTACH" },
+ { PT_DETACH, "PT_DETACH" },
+ { PT_GETREGS, "PT_GETREGS" },
+ { PT_SETREGS, "PT_SETREGS" },
+ { PT_GETFPREGS, "PT_GETFPREGS" },
+ { PT_SETFPREGS, "PT_SETFPREGS" },
+ { PT_GETDBREGS, "PT_GETDBREGS" },
+ { PT_SETDBREGS, "PT_SETDBREGS" },
+#endif /* FREEBSD */
{ 0, NULL },
};
+#ifndef FREEBSD
#ifndef SUNOS4_KERNEL_ARCH_KLUDGE
static
#endif /* !SUNOS4_KERNEL_ARCH_KLUDGE */
@@ -2038,6 +2083,7 @@
{ sizeof(struct user), "sizeof(struct user)" },
{ 0, NULL },
};
+#endif
int
sys_ptrace(tcp)
@@ -2049,10 +2095,15 @@
cmd = xlookup(ptrace_cmds, tcp->u_arg[0]);
if (!cmd)
+#ifndef FREEBSD
cmd = "PTRACE_???";
+#else
+ cmd = "PT_???";
+#endif
if (entering(tcp)) {
tprintf("%s, %lu, ", cmd, tcp->u_arg[1]);
addr = tcp->u_arg[2];
+#ifndef FREEBSD
if (tcp->u_arg[0] == PTRACE_PEEKUSER
|| tcp->u_arg[0] == PTRACE_POKEUSER) {
for (x = struct_user_offsets; x->str; x++) {
@@ -2069,6 +2120,7 @@
tprintf("%s, ", x->str);
}
else
+#endif
tprintf("%#lx, ", tcp->u_arg[2]);
#ifdef LINUX
switch (tcp->u_arg[0]) {
@@ -2113,6 +2165,10 @@
}
}
#endif /* SUNOS4 */
+#ifdef FREEBSD
+ tprintf("%lu", tcp->u_arg[3]);
+ }
+#endif /* FREEBSD */
return 0;
}
diff --git a/resource.c b/resource.c
index 74222f4..be776ce 100644
--- a/resource.c
+++ b/resource.c
@@ -41,7 +41,7 @@
#ifdef SUNOS4
#include <ufs/quota.h>
#endif /* SUNOS4 */
-#ifdef SVR4
+#if defined(SVR4) || defined(FREEBSD)
#include <sys/times.h>
#include <sys/time.h>
#endif
@@ -439,14 +439,23 @@
#endif /* Linux */
-#ifdef SUNOS4
+#if defined(SUNOS4) || defined(FREEBSD)
+
+#ifdef FREEBSD
+#include <ufs/ufs/quota.h>
+#endif
static struct xlat quotacmds[] = {
{ Q_QUOTAON, "Q_QUOTAON" },
{ Q_QUOTAOFF, "Q_QUOTAOFF" },
{ Q_GETQUOTA, "Q_GETQUOTA" },
{ Q_SETQUOTA, "Q_SETQUOTA" },
+#ifdef Q_SETQLIM
{ Q_SETQLIM, "Q_SETQLIM" },
+#endif
+#ifdef Q_SETUSE
+ { Q_SETUSE, "Q_SETUSE" },
+#endif
{ Q_SYNC, "Q_SYNC" },
{ 0, NULL },
};
@@ -457,12 +466,19 @@
{
/* fourth arg (addr) not interpreted here */
if (entering(tcp)) {
+#ifdef SUNOS4
printxval(quotacmds, tcp->u_arg[0], "Q_???");
tprintf(", ");
printstr(tcp, tcp->u_arg[1], -1);
+#endif
+#ifdef FREEBSD
+ printpath(tcp, tcp->u_arg[0]);
+ tprintf(", ");
+ printxval(quotacmds, tcp->u_arg[1], "Q_???");
+#endif
tprintf(", %lu, %#lx", tcp->u_arg[2], tcp->u_arg[3]);
}
return 0;
}
-#endif /* SUNOS4 */
+#endif /* SUNOS4 || FREEBSD */
diff --git a/signal.c b/signal.c
index 90ac5fe..1b807d8 100644
--- a/signal.c
+++ b/signal.c
@@ -146,7 +146,7 @@
char **signalent;
int nsignals;
-#ifdef SUNOS4
+#if defined(SUNOS4) || defined(FREEBSD)
static struct xlat sigvec_flags[] = {
{ SV_ONSTACK, "SV_ONSTACK" },
@@ -156,7 +156,7 @@
{ 0, NULL },
};
-#endif /* SUNOS4 */
+#endif /* SUNOS4 || FREEBSD */
#ifdef HAVE_SIGACTION
@@ -429,7 +429,7 @@
#endif /* !SVR4 */
}
-#if defined(SUNOS4)
+#if defined(SUNOS4) || defined(FREEBSD)
int
sys_sigvec(tcp)
@@ -534,7 +534,7 @@
return 0;
}
-#endif /* SUNOS4 */
+#endif /* SUNOS4 || FREEBSD */
#ifndef SVR4
@@ -546,12 +546,14 @@
sigset_t sigm;
long_to_sigset(tcp->u_arg[0], &sigm);
printsigmask(&sigm, 0);
+#ifndef USE_PROCFS
if ((tcp->u_arg[0] & sigmask(SIGTRAP))) {
/* Mark attempt to block SIGTRAP */
tcp->flags |= TCB_SIGTRAPPED;
/* Send unblockable signal */
kill(tcp->pid, SIGSTOP);
}
+#endif /* !USE_PROCFS */
}
else if (!syserror(tcp)) {
sigset_t sigm;
@@ -622,21 +624,21 @@
tprintf("{SIG_DFL}");
break;
case (long) SIG_IGN:
-#ifndef SVR4
+#ifndef USE_PROCFS
if (tcp->u_arg[0] == SIGTRAP) {
tcp->flags |= TCB_SIGTRAPPED;
kill(tcp->pid, SIGSTOP);
}
-#endif /* !SVR4 */
+#endif /* !USE_PROCFS */
tprintf("{SIG_IGN}");
break;
default:
-#ifndef SVR4
+#ifndef USE_PROCFS
if (tcp->u_arg[0] == SIGTRAP) {
tcp->flags |= TCB_SIGTRAPPED;
kill(tcp->pid, SIGSTOP);
}
-#endif /* !SVR4 */
+#endif /* !USE_PROCFS */
tprintf("{%#lx, ", (long) sa.SA_HANDLER);
#ifndef LINUX
printsigmask (&sa.sa_mask, 0);
@@ -674,21 +676,21 @@
tprintf("SIG_DFL");
break;
case (int) SIG_IGN:
-#ifndef SVR4
+#ifndef USE_PROCFS
if (tcp->u_arg[0] == SIGTRAP) {
tcp->flags |= TCB_SIGTRAPPED;
kill(tcp->pid, SIGSTOP);
}
-#endif /* !SVR4 */
+#endif /* !USE_PROCFS */
tprintf("SIG_IGN");
break;
default:
-#ifndef SVR4
+#ifndef USE_PROCFS
if (tcp->u_arg[0] == SIGTRAP) {
tcp->flags |= TCB_SIGTRAPPED;
kill(tcp->pid, SIGSTOP);
}
-#endif /* !SVR4 */
+#endif /* !USE_PROCFS */
tprintf("%#lx", tcp->u_arg[1]);
}
return 0;
@@ -960,7 +962,7 @@
#endif /* LINUX */
-#ifdef SVR4
+#if defined(SVR4) || defined(FREEBSD)
int
sys_sigsuspend(tcp)
@@ -976,6 +978,7 @@
}
return 0;
}
+#ifndef FREEBSD
static struct xlat ucontext_flags[] = {
{ UC_SIGMASK, "UC_SIGMASK" },
{ UC_STACK, "UC_STACK" },
@@ -988,10 +991,10 @@
#endif
{ 0, NULL },
};
+#endif /* !FREEBSD */
+#endif /* SVR4 || FREEBSD */
-#endif
-
-#if defined SVR4 || defined LINUX
+#if defined SVR4 || defined LINUX || defined FREEBSD
#if defined LINUX && !defined SS_ONSTACK
#define SS_ONSTACK 1
#define SS_DISABLE 2
@@ -1004,6 +1007,9 @@
} stack_t;
#endif
#endif
+#ifdef FREEBSD
+#define stack_t struct sigaltstack
+#endif
static struct xlat sigaltstack_flags[] = {
{ SS_ONSTACK, "SS_ONSTACK" },
@@ -1082,7 +1088,7 @@
#endif /* SVR4 */
-#ifdef LINUX
+#if defined(LINUX) || defined(FREEBSD)
static int
print_stack_t(tcp, addr)
diff --git a/strace.c b/strace.c
index f96eaa0..3e4b4a6 100644
--- a/strace.c
+++ b/strace.c
@@ -44,9 +44,12 @@
#include <grp.h>
#include <string.h>
+#ifdef USE_PROCFS
+#include <poll.h>
+#endif
+
#ifdef SVR4
#include <sys/stropts.h>
-#include <poll.h>
#ifdef HAVE_MP_PROCFS
#include <sys/uio.h>
#endif
@@ -87,7 +90,7 @@
#endif /* !__STDC__ */
#endif /* !HAVE_SIG_ATOMIC_T */
-#ifdef SVR4
+#ifdef USE_PROCFS
static struct tcb *pfd2tcb P((int pfd));
static void reaper P((int sig));
@@ -115,7 +118,7 @@
#else
#define POLLWANT POLLPRI
#endif
-#endif /* SVR4 */
+#endif /* USE_PROCFS */
static void
usage(ofp, exitval)
@@ -334,19 +337,19 @@
tcp->outf = outf;
if (!(tcp->flags & TCB_INUSE) || !(tcp->flags & TCB_ATTACHED))
continue;
-#ifdef SVR4
+#ifdef USE_PROCFS
if (proc_open(tcp, 1) < 0) {
fprintf(stderr, "trouble opening proc file\n");
droptcb(tcp);
continue;
}
-#else /* !SVR4 */
+#else /* !USE_PROCFS */
if (ptrace(PTRACE_ATTACH, tcp->pid, (char *) 1, 0) < 0) {
perror("attach: ptrace(PTRACE_ATTACH, ...)");
droptcb(tcp);
continue;
}
-#endif /* !SVR4 */
+#endif /* !USE_PROCFS */
if (!qflag)
fprintf(stderr,
"Process %u attached - interrupt to quit\n",
@@ -408,8 +411,8 @@
exit(1);
break;
case 0: {
-#ifdef SVR4
- if (outf != stderr) close (fileno (outf));
+#ifdef USE_PROCFS
+ if (outf != stderr) close (fileno (outf));
#ifdef MIPS
/* Kludge for SGI, see proc_open for details. */
sa.sa_handler = foobar;
@@ -417,8 +420,12 @@
sigemptyset(&sa.sa_mask);
sigaction(SIGINT, &sa, NULL);
#endif /* MIPS */
+#ifndef FREEBSD
pause();
-#else /* !SVR4 */
+#else /* FREEBSD */
+ kill(getpid(), SIGSTOP); /* stop HERE */
+#endif /* FREEBSD */
+#else /* !USE_PROCFS */
if (outf!=stderr)
close(fileno (outf));
@@ -459,7 +466,7 @@
}
else
setreuid(run_uid, run_uid);
-#endif /* !SVR4 */
+#endif /* !USE_PROCFS */
execv(pathname, &argv[optind]);
perror("strace: exec");
@@ -472,16 +479,16 @@
cleanup();
exit(1);
}
-#ifdef SVR4
+#ifdef USE_PROCFS
if (proc_open(tcp, 0) < 0) {
fprintf(stderr, "trouble opening proc file\n");
cleanup();
exit(1);
}
-#endif /* SVR4 */
-#ifndef SVR4
+#endif /* USE_PROCFS */
+#ifndef USE_PROCFS
fake_execve(tcp, pathname, &argv[optind], environ);
-#endif
+#endif /* !USE_PROCFS */
break;
}
}
@@ -512,10 +519,10 @@
sigaction(SIGQUIT, &sa, NULL);
sigaction(SIGPIPE, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
-#ifdef SVR4
+#ifdef USE_PROCFS
sa.sa_handler = reaper;
sigaction(SIGCHLD, &sa, NULL);
-#endif /* SVR4 */
+#endif /* USE_PROCFS */
if (trace() < 0)
exit(1);
@@ -572,7 +579,7 @@
return NULL;
}
-#ifdef SVR4
+#ifdef USE_PROCFS
int
proc_open(tcp, attaching)
struct tcb *tcp;
@@ -580,9 +587,11 @@
{
char proc[32];
long arg;
+#ifdef SVR4
sysset_t sc_enter, sc_exit;
sigset_t signals;
fltset_t faults;
+#endif
#ifndef HAVE_POLLABLE_PROCFS
static int last_pfd;
#endif
@@ -630,8 +639,13 @@
}
#else
/* Open the process pseudo-file in /proc. */
+#ifndef FREEBSD
sprintf(proc, "/proc/%d", tcp->pid);
if ((tcp->pfd = open(proc, O_RDWR|O_EXCL)) < 0) {
+#else /* FREEBSD */
+ sprintf(proc, "/proc/%d/mem", tcp->pid);
+ if ((tcp->pfd = open(proc, O_RDWR)) < 0) {
+#endif /* FREEBSD */
perror("strace: open(\"/proc/...\", ...)");
return -1;
}
@@ -644,6 +658,21 @@
return -1;
}
#endif
+#ifdef FREEBSD
+ sprintf(proc, "/proc/%d/regs", tcp->pid);
+ if ((tcp->pfd_reg = open(proc, O_RDONLY)) < 0) {
+ perror("strace: open(\"/proc/.../regs\", ...)");
+ return -1;
+ }
+ if (cflag) {
+ sprintf(proc, "/proc/%d/status", tcp->pid);
+ if ((tcp->pfd_status = open(proc, O_RDONLY)) < 0) {
+ perror("strace: open(\"/proc/.../status\", ...)");
+ return -1;
+ }
+ } else
+ tcp->pfd_status = -1;
+#endif /* FREEBSD */
rebuild_pollv();
if (!attaching) {
/*
@@ -655,15 +684,21 @@
perror("strace: PIOCSTATUS");
return -1;
}
+#ifndef FREEBSD
if (tcp->status.PR_FLAGS & PR_ASLEEP)
- break;
+#else
+ if (tcp->status.state == 1)
+#endif
+ break;
}
}
+#ifndef FREEBSD
/* Stop the process so that we own the stop. */
if (IOCTL(tcp->pfd, PIOCSTOP, (char *)NULL) < 0) {
perror("strace: PIOCSTOP");
return -1;
}
+#endif
#ifdef PIOCSET
/* Set Run-on-Last-Close. */
arg = PR_RLC;
@@ -678,6 +713,7 @@
return -1;
}
#else /* !PIOCSET */
+#ifndef FREEBSD
if (ioctl(tcp->pfd, PIOCSRLC) < 0) {
perror("PIOCSRLC");
return -1;
@@ -686,7 +722,20 @@
perror("PIOC{S,R}FORK");
return -1;
}
+#else /* FREEBSD */
+ /* just unset the PF_LINGER flag for the Run-on-Last-Close. */
+ if (ioctl(tcp->pfd, PIOCGFL, &arg) < 0) {
+ perror("PIOCGFL");
+ return -1;
+ }
+ arg &= ~PF_LINGER;
+ if (ioctl(tcp->pfd, PIOCSFL, arg) < 0) {
+ perror("PIOCSFL");
+ return -1;
+ }
+#endif /* FREEBSD */
#endif /* !PIOCSET */
+#ifndef FREEBSD
/* Enable all syscall entries. */
prfillset(&sc_enter);
if (IOCTL(tcp->pfd, PIOCSENTRY, &sc_enter) < 0) {
@@ -711,6 +760,14 @@
perror("PIOCSFAULT");
return -1;
}
+#else /* FREEBSD */
+ /* set events flags. */
+ arg = S_SIG | S_SCE | S_SCX ;
+ if(ioctl(tcp->pfd, PIOCBIS, arg) < 0) {
+ perror("PIOCBIS");
+ return -1;
+ }
+#endif /* FREEBSD */
if (!attaching) {
#ifdef MIPS
/*
@@ -719,13 +776,19 @@
*/
kill(tcp->pid, SIGINT);
#else /* !MIPS */
+#ifdef PRSABORT
/* The child is in a pause(), abort it. */
arg = PRSABORT;
if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
perror("PIOCRUN");
return -1;
}
-#endif /* !MIPS */
+#endif
+#endif /* !MIPS*/
+#ifdef FREEBSD
+ /* wake up the child if it received the SIGSTOP */
+ kill(tcp->pid, SIGCONT);
+#endif
for (;;) {
/* Wait for the child to do something. */
if (IOCTL_WSTOP (tcp) < 0) {
@@ -733,22 +796,40 @@
return -1;
}
if (tcp->status.PR_WHY == PR_SYSENTRY) {
-#ifdef HAVE_PR_SYSCALL
- int scno = tcp->status.pr_syscall;
-#else /* !HAVE_PR_SYSCALL */
- int scno = tcp->status.PR_WHAT;
-#endif /* !HAVE_PR_SYSCALL */
- if (scno == SYS_execve)
+ tcp->flags &= ~TCB_INSYSCALL;
+ get_scno(tcp);
+ if (tcp->scno == SYS_execve)
break;
}
/* Set it running: maybe execve will be next. */
+#ifndef FREEBSD
arg = 0;
if (IOCTL(tcp->pfd, PIOCRUN, &arg) < 0) {
+#else /* FREEBSD */
+ if (IOCTL(tcp->pfd, PIOCRUN, 0) < 0) {
+#endif /* FREEBSD */
perror("PIOCRUN");
return -1;
}
+#ifdef FREEBSD
+ /* handle the case where we "opened" the child before
+ it did the kill -STOP */
+ if (tcp->status.PR_WHY == PR_SIGNALLED &&
+ tcp->status.PR_WHAT == SIGSTOP)
+ kill(tcp->pid, SIGCONT);
+#endif
}
+#ifndef FREEBSD
}
+#else /* FREEBSD */
+ } else {
+ /* little hack to show the current syscall */
+ IOCTL_STATUS(tcp);
+ tcp->flags &= ~TCB_INSYSCALL;
+ tcp->status.why = PR_SYSENTRY;
+ trace_syscall(tcp);
+ }
+#endif /* FREEBSD */
#ifndef HAVE_POLLABLE_PROCFS
if (proc_poll_pipe[0] != -1)
proc_poller(tcp->pfd);
@@ -762,7 +843,7 @@
return 0;
}
-#endif /* SVR4 */
+#endif /* USE_PROCFS */
static struct tcb *
pid2tcb(pid)
@@ -780,7 +861,7 @@
return NULL;
}
-#ifdef SVR4
+#ifdef USE_PROCFS
static struct tcb *
pfd2tcb(pfd)
@@ -798,7 +879,7 @@
return NULL;
}
-#endif /* SVR4 */
+#endif /* USE_PROCFS */
void
droptcb(tcp)
@@ -812,7 +893,17 @@
if (tcp->pfd != -1) {
close(tcp->pfd);
tcp->pfd = -1;
-#ifdef SVR4
+#ifdef FREEBSD
+ if (tcp->pfd_reg != -1) {
+ close(tcp->pfd_reg);
+ tcp->pfd_reg = -1;
+ }
+ if (tcp->pfd_status != -1) {
+ close(tcp->pfd_status);
+ tcp->pfd_status = -1;
+ }
+#endif /* !FREEBSD */
+#ifdef USE_PROCFS
rebuild_pollv();
#endif
}
@@ -827,7 +918,7 @@
tcp->outf = 0;
}
-#ifndef SVR4
+#ifndef USE_PROCFS
static int
resume(tcp)
@@ -852,7 +943,7 @@
return 0;
}
-#endif /* !SVR4 */
+#endif /* !USE_PROCFS */
/* detach traced process; continue with sig */
@@ -934,10 +1025,10 @@
perror("detach: ptrace(PTRACE_DETACH, ...)");
#endif /* SUNOS4 */
-#ifndef SVR4
+#ifndef USE_PROCFS
if (waiting_parent(tcp))
error = resume(tcp->parent);
-#endif /* !SVR4 */
+#endif /* !USE_PROCFS */
if (!qflag)
fprintf(stderr, "Process %u detached\n", tcp->pid);
@@ -946,7 +1037,7 @@
return error;
}
-#ifdef SVR4
+#ifdef USE_PROCFS
static void
reaper(sig)
@@ -966,7 +1057,7 @@
}
}
-#endif /* SVR4 */
+#endif /* USE_PROCFS */
static void
cleanup()
@@ -1054,7 +1145,7 @@
#endif /* HAVE_STRSIGNAL */
-#ifdef SVR4
+#ifdef USE_PROCFS
static void
rebuild_pollv()
@@ -1141,6 +1232,9 @@
int i;
int n;
struct rlimit rl;
+#ifdef FREEBSD
+ struct procfs_status pfs;
+#endif /* FREEBSD */
switch (fork()) {
case -1:
@@ -1180,7 +1274,11 @@
pollinfo.fd = pfd;
pollinfo.pid = getpid();
for (;;) {
- if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
+#ifndef FREEBSD
+ if (ioctl(pfd, PIOCWSTOP, NULL) < 0)
+#else /* FREEBSD */
+ if (ioctl(pfd, PIOCWSTOP, &pfs) < 0)
+#endif /* FREEBSD */
{
switch (errno) {
case EINTR:
@@ -1331,7 +1429,17 @@
FOUND:
/* Get the status of the process. */
if (!interrupted) {
+#ifndef FREEBSD
ioctl_result = IOCTL_WSTOP (tcp);
+#else /* FREEBSD */
+ /* Thanks to some scheduling mystery, the first poller
+ sometimes waits for the already processed end of fork
+ event. Doing a non blocking poll here solves the problem. */
+ if (proc_poll_pipe[0] != -1)
+ ioctl_result = IOCTL_STATUS (tcp);
+ else
+ ioctl_result = IOCTL_WSTOP (tcp);
+#endif /* FREEBSD */
ioctl_errno = errno;
#ifndef HAVE_POLLABLE_PROCFS
if (proc_poll_pipe[0] != -1) {
@@ -1354,6 +1462,9 @@
case EINTR:
case EBADF:
continue;
+#ifdef FREEBSD
+ case ENOTTY:
+#endif
case ENOENT:
droptcb(tcp);
continue;
@@ -1371,15 +1482,27 @@
if (cflag) {
struct timeval stime;
+#ifdef FREEBSD
+ char buf[1024];
+ int len;
+ if ((len = pread(tcp->pfd_status, buf, sizeof(buf) - 1, 0)) > 0) {
+ buf[len] = '\0';
+ sscanf(buf,
+ "%*s %*d %*d %*d %*d %*d,%*d %*s %*d,%*d %*d,%*d %ld,%ld",
+ &stime.tv_sec, &stime.tv_usec);
+ } else
+ stime.tv_sec = stime.tv_usec = 0;
+#else /* !FREEBSD */
stime.tv_sec = tcp->status.pr_stime.tv_sec;
stime.tv_usec = tcp->status.pr_stime.tv_nsec/1000;
+#endif /* !FREEBSD */
tv_sub(&tcp->dtime, &stime, &tcp->stime);
tcp->stime = stime;
}
-
what = tcp->status.PR_WHAT;
switch (tcp->status.PR_WHY) {
+#ifndef FREEBSD
case PR_REQUESTED:
if (tcp->status.PR_FLAGS & PR_ASLEEP) {
tcp->status.PR_WHY = PR_SYSENTRY;
@@ -1389,6 +1512,7 @@
}
}
break;
+#endif /* !FREEBSD */
case PR_SYSENTRY:
#ifdef POLL_HACK
in_syscall = tcp;
@@ -1414,13 +1538,21 @@
printtrailer(tcp);
}
break;
+#ifdef FREEBSD
+ case 0: /* handle case we polled for nothing */
+ continue;
+#endif
default:
fprintf(stderr, "odd stop %d\n", tcp->status.PR_WHY);
exit(1);
break;
}
arg = 0;
+#ifndef FREEBSD
if (IOCTL (tcp->pfd, PIOCRUN, &arg) < 0) {
+#else
+ if (IOCTL (tcp->pfd, PIOCRUN, 0) < 0) {
+#endif
perror("PIOCRUN");
exit(1);
}
@@ -1428,7 +1560,7 @@
return 0;
}
-#else /* !SVR4 */
+#else /* !USE_PROCFS */
static int
trace()
@@ -1667,7 +1799,7 @@
return 0;
}
-#endif /* !SVR4 */
+#endif /* !USE_PROCFS */
static int curcol;
diff --git a/stream.c b/stream.c
index 0cc14a0..4abf861 100644
--- a/stream.c
+++ b/stream.c
@@ -30,7 +30,7 @@
#include "defs.h"
-#if defined(HAVE_SYS_STREAM_H) || defined(linux)
+#if defined(HAVE_SYS_STREAM_H) || defined(linux) || defined(FREEBSD)
#if defined(linux)
#ifdef HAVE_SYS_POLL_H
@@ -48,11 +48,15 @@
#else /* linux */
+#ifndef FREEBSD
#include <stropts.h>
#include <poll.h>
#include <sys/conf.h>
#include <sys/stream.h>
#include <sys/tihdr.h>
+#else /* FREEBSD */
+#include <poll.h>
+#endif /* FREEBSD */
#endif /* linux */
@@ -62,6 +66,7 @@
#include <sys/timod.h>
#endif /* HAVE_SYS_TIUSER_H */
+#ifndef FREEBSD
static struct xlat msgflags[] = {
{ RS_HIPRI, "RS_HIPRI" },
{ 0, NULL },
@@ -252,6 +257,7 @@
}
#endif /* HAVE_PUTPMSG */
+#endif /* !FREEBSD */
#ifdef HAVE_SYS_POLL_H
@@ -349,7 +355,7 @@
}
#endif
-#ifndef linux
+#if !defined(linux) && !defined(FREEBSD)
static struct xlat stream_flush_options[] = {
{ FLUSHR, "FLUSHR" },
@@ -824,7 +830,7 @@
}
}
-#endif /* linux */
+#endif /* !linux && !FREEBSD */
-#endif /* LINUXSPARC && linux */
+#endif /* HAVE_SYS_STREAM_H || linux || FREEBSD */
diff --git a/syscall.c b/syscall.c
index 9642446..e59b16f 100644
--- a/syscall.c
+++ b/syscall.c
@@ -410,7 +410,23 @@
}
}
+#ifndef FREEBSD
enum subcall_style { shift_style, deref_style, mask_style, door_style };
+#else /* FREEBSD */
+enum subcall_style { shift_style, deref_style, mask_style, door_style, table_style };
+
+struct subcall {
+ int call;
+ int nsubcalls;
+ int subcalls[5];
+};
+
+const struct subcall subcalls_table[] = {
+ { SYS_shmsys, 5, { SYS_shmat, SYS_shmctl, SYS_shmdt, SYS_shmget, SYS_shmctl } },
+ { SYS_semsys, 4, { SYS___semctl, SYS_semget, SYS_semop, SYS_semconfig } },
+ { SYS_msgsys, 4, { SYS_msgctl, SYS_msgget, SYS_msgsnd, SYS_msgrcv } },
+};
+#endif /* FREEBSD */
#if !(defined(LINUX) && ( defined(ALPHA) || defined(IA64) || defined(MIPS) ))
@@ -464,6 +480,11 @@
enum subcall_style style;
{
int i, addr, mask, arg;
+
+#ifndef FREEBSD
+ if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= nsubcalls)
+ return;
+#endif
switch (style) {
case shift_style:
if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= nsubcalls)
@@ -513,6 +534,18 @@
else
tcp->u_nargs--;
break;
+#ifdef FREEBSD
+ case table_style:
+ for (i = 0; i < sizeof(subcalls_table) / sizeof(struct subcall); i++)
+ if (subcalls_table[i].call == tcp->scno) break;
+ if (i < sizeof(subcalls_table) / sizeof(struct subcall) &&
+ tcp->u_arg[0] >= 0 && tcp->u_arg[0] < subcalls_table[i].nsubcalls) {
+ tcp->scno = subcalls_table[i].subcalls[tcp->u_arg[0]];
+ for (i = 0; i < tcp->u_nargs; i++)
+ tcp->u_arg[i] = tcp->u_arg[i + 1];
+ }
+ break;
+#endif /* FREEBSD */
}
}
#endif
@@ -602,13 +635,18 @@
static long pc;
#endif
#endif /* LINUX */
+#ifdef FREEBSD
+ struct reg regs;
+#endif /* FREEBSD */
int
get_scno(tcp)
struct tcb *tcp;
{
long scno = 0;
+#ifndef USE_PROCFS
int pid = tcp->pid;
+#endif /* !PROCFS */
#ifdef LINUX
#if defined(S390)
@@ -774,13 +812,29 @@
if (upeek(pid, uoff(u_arg[7]), &scno) < 0)
return -1;
#endif
-#ifdef SVR4
+#ifdef USE_PROCFS
#ifdef HAVE_PR_SYSCALL
scno = tcp->status.pr_syscall;
#else /* !HAVE_PR_SYSCALL */
+#ifndef FREEBSD
scno = tcp->status.PR_WHAT;
+#else /* FREEBSD */
+ if (pread(tcp->pfd_reg, ®s, sizeof(regs), 0) < 0) {
+ perror("pread");
+ return -1;
+ }
+ switch (regs.r_eax) {
+ case SYS_syscall:
+ case SYS___syscall:
+ pread(tcp->pfd, &scno, sizeof(scno), regs.r_esp + sizeof(int));
+ break;
+ default:
+ scno = regs.r_eax;
+ break;
+ }
+#endif /* FREEBSD */
#endif /* !HAVE_PR_SYSCALL */
-#endif
+#endif /* USE_PROCFS */
if (!(tcp->flags & TCB_INSYSCALL))
tcp->scno = scno;
return 1;
@@ -791,9 +845,11 @@
syscall_fixup(tcp)
struct tcb *tcp;
{
+#ifndef USE_PROCFS
int pid = tcp->pid;
+#else /* USE_PROCFS */
+ int scno = tcp->scno;
-#ifdef SVR4
if (!(tcp->flags & TCB_INSYSCALL)) {
if (tcp->status.PR_WHY != PR_SYSENTRY) {
if (
@@ -819,7 +875,7 @@
tcp->flags &= ~TCB_INSYSCALL;
}
}
-#endif /* SVR4 */
+#endif /* USE_PROCFS */
#ifdef SUNOS4
if (!(tcp->flags & TCB_INSYSCALL)) {
if (scno == 0) {
@@ -1054,6 +1110,17 @@
}
#endif /* MIPS */
#endif /* SVR4 */
+#ifdef FREEBSD
+ if (regs.r_eflags & PSL_C) {
+ tcp->u_rval = -1;
+ u_error = regs.r_eax;
+ } else {
+ tcp->u_rval = regs.r_eax;
+ tcp->u_lrval =
+ ((unsigned long long) regs.r_edx << 32) + regs.r_eax;
+ u_error = 0;
+ }
+#endif /* FREEBSD */
tcp->u_error = u_error;
return 1;
}
@@ -1061,12 +1128,17 @@
int syscall_enter(tcp)
struct tcb *tcp;
{
+#ifndef USE_PROCFS
int pid = tcp->pid;
+#endif /* !USE_PROCFS */
#ifdef LINUX
#if defined(S390)
{
int i;
- tcp->u_nargs = sysent[tcp->scno].nargs;
+ if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
+ tcp->u_nargs = sysent[tcp->scno].nargs;
+ else
+ tcp->u_nargs = MAX_ARGS;
for (i = 0; i < tcp->u_nargs; i++) {
if (upeek(pid,i==0 ? PT_ORIGGPR2:PT_GPR2+(i<<2), &tcp->u_arg[i]) < 0)
return -1;
@@ -1075,7 +1147,10 @@
#elif defined (ALPHA)
{
int i;
- tcp->u_nargs = sysent[tcp->scno].nargs;
+ if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
+ tcp->u_nargs = sysent[tcp->scno].nargs;
+ else
+ tcp->u_nargs = MAX_ARGS;
for (i = 0; i < tcp->u_nargs; i++) {
/* WTA: if scno is out-of-bounds this will bomb. Add range-check
* for scno somewhere above here!
@@ -1095,7 +1170,10 @@
bsp = ia64_rse_skip_regs(bsp, -(cfm & 0x7f));
- tcp->u_nargs = sysent[tcp->scno].nargs;
+ if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
+ tcp->u_nargs = sysent[tcp->scno].nargs;
+ else
+ tcp->u_nargs = MAX_ARGS;
for (i = 0; i < tcp->u_nargs; ++i) {
if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(bsp, i), sizeof(long),
(char *) &tcp->u_arg[i])
@@ -1108,7 +1186,10 @@
long sp;
int i, nargs;
- nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
+ if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
+ nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
+ else
+ nargs = tcp->u_nargs = MAX_ARGS;
if(nargs > 4) {
if(upeek(pid, REG_SP, &sp) < 0)
return -1;
@@ -1128,7 +1209,10 @@
#elif defined (POWERPC)
{
int i;
- tcp->u_nargs = sysent[tcp->scno].nargs;
+ if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
+ tcp->u_nargs = sysent[tcp->scno].nargs;
+ else
+ tcp->u_nargs = MAX_ARGS;
for (i = 0; i < tcp->u_nargs; i++) {
if (upeek(pid, (i==0) ? (4*PT_ORIG_R3) : ((i+PT_R3)*4), &tcp->u_arg[i]) < 0)
return -1;
@@ -1137,15 +1221,21 @@
#elif defined (SPARC)
{
int i;
-
- tcp->u_nargs = sysent[tcp->scno].nargs;
+
+ if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
+ tcp->u_nargs = sysent[tcp->scno].nargs;
+ else
+ tcp->u_nargs = MAX_ARGS;
for (i = 0; i < tcp->u_nargs; i++)
tcp->u_arg[i] = *((®s.r_o0) + i);
}
#else /* Other architecture (like i386) (32bits specific) */
{
int i;
- tcp->u_nargs = sysent[tcp->scno].nargs;
+ if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
+ tcp->u_nargs = sysent[tcp->scno].nargs;
+ else
+ tcp->u_nargs = MAX_ARGS;
for (i = 0; i < tcp->u_nargs; i++) {
if (upeek(pid, i*4, &tcp->u_arg[i]) < 0)
return -1;
@@ -1156,7 +1246,10 @@
#ifdef SUNOS4
{
int i;
- tcp->u_nargs = sysent[tcp->scno].nargs;
+ if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
+ tcp->u_nargs = sysent[tcp->scno].nargs;
+ else
+ tcp->u_nargs = MAX_ARGS;
for (i = 0; i < tcp->u_nargs; i++) {
struct user *u;
@@ -1172,7 +1265,7 @@
* SGI is broken: even though it has pr_sysarg, it doesn't
* set them on system call entry. Get a clue.
*/
- if (sysent[tcp->scno].nargs != -1)
+ if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
tcp->u_nargs = sysent[tcp->scno].nargs;
else
tcp->u_nargs = tcp->status.pr_nsysarg;
@@ -1188,7 +1281,7 @@
}
#else /* !MIPS */
#ifdef HAVE_PR_SYSCALL
- if (sysent[tcp->scno].nargs != -1)
+ if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
tcp->u_nargs = sysent[tcp->scno].nargs;
else
tcp->u_nargs = tcp->status.pr_nsysarg;
@@ -1199,7 +1292,7 @@
}
#else /* !HAVE_PR_SYSCALL */
#ifdef I386
- if (sysent[tcp->scno].nargs != -1)
+ if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
tcp->u_nargs = sysent[tcp->scno].nargs;
else
#if UNIXWARE >= 2
@@ -1213,6 +1306,31 @@
#endif /* !HAVE_PR_SYSCALL */
#endif /* !MIPS */
#endif /* SVR4 */
+#ifdef FREEBSD
+ if (tcp->scno >= 0 && tcp->scno < nsyscalls &&
+ sysent[tcp->scno].nargs > tcp->status.val)
+ tcp->u_nargs = sysent[tcp->scno].nargs;
+ else
+ tcp->u_nargs = tcp->status.val;
+ if (tcp->u_nargs < 0)
+ tcp->u_nargs = 0;
+ if (tcp->u_nargs > MAX_ARGS)
+ tcp->u_nargs = MAX_ARGS;
+ switch(regs.r_eax) {
+ case SYS___syscall:
+ pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
+ regs.r_esp + sizeof(int) + sizeof(quad_t));
+ break;
+ case SYS_syscall:
+ pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
+ regs.r_esp + 2 * sizeof(int));
+ break;
+ default:
+ pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
+ regs.r_esp + sizeof(int));
+ break;
+ }
+#endif /* FREEBSD */
return 1;
}
@@ -1245,7 +1363,8 @@
internal_syscall(tcp);
- if (!(qual_flags[tcp->scno] & QUAL_TRACE)) {
+ if (tcp->scno >= 0 && tcp->scno < nsyscalls &&
+ !(qual_flags[tcp->scno] & QUAL_TRACE)) {
tcp->flags &= ~TCB_INSYSCALL;
return 0;
}
@@ -1253,14 +1372,14 @@
if (tcp->flags & TCB_REPRINT) {
printleader(tcp);
tprintf("<... ");
- if (tcp->scno >= nsyscalls)
+ if (tcp->scno >= nsyscalls || tcp->scno < 0)
tprintf("syscall_%lu", tcp->scno);
else
tprintf("%s", sysent[tcp->scno].sys_name);
tprintf(" resumed> ");
}
- if (cflag) {
+ if (cflag && tcp->scno < nsyscalls && tcp->scno >= 0) {
call_count[tcp->scno]++;
if (tcp->u_error)
error_count[tcp->scno]++;
@@ -1288,7 +1407,7 @@
return 0;
}
- if (tcp->scno >= nsyscalls
+ if (tcp->scno >= nsyscalls || tcp->scno < 0
|| (qual_flags[tcp->scno] & QUAL_RAW))
sys_res = printargs(tcp);
else
@@ -1296,7 +1415,8 @@
u_error = tcp->u_error;
tprintf(") ");
tabto(acolumn);
- if (qual_flags[tcp->scno] & QUAL_RAW) {
+ if (tcp->scno >= nsyscalls || tcp->scno < 0 ||
+ qual_flags[tcp->scno] & QUAL_RAW) {
if (u_error)
tprintf("= -1 (errno %ld)", u_error);
else
@@ -1349,10 +1469,18 @@
tprintf("= %ld", tcp->u_rval);
break;
#ifdef HAVE_LONG_LONG
- case RVAL_LDECIMAL:
- tprintf ("= %lld", tcp->u_lrval);
+ case RVAL_LHEX:
+ tprintf("= %#llx", tcp->u_lrval);
break;
- /* LHEX, LOCTAL, LUDECIMAL... */
+ case RVAL_LOCTAL:
+ tprintf("= %#llo", tcp->u_lrval);
+ break;
+ case RVAL_LUDECIMAL:
+ tprintf("= %llu", tcp->u_lrval);
+ break;
+ case RVAL_LDECIMAL:
+ tprintf("= %lld", tcp->u_lrval);
+ break;
#endif
default:
fprintf(stderr,
@@ -1452,6 +1580,13 @@
break;
#endif /* SYS_door_subcall */
#endif /* SVR4 */
+#ifdef FREEBSD
+ case SYS_msgsys:
+ case SYS_shmsys:
+ case SYS_semsys:
+ decode_subcall(tcp, 0, 0, table_style);
+ break;
+#endif
#ifdef SUNOS4
case SYS_semsys:
decode_subcall(tcp, SYS_semsys_subcall,
@@ -1469,7 +1604,7 @@
}
internal_syscall(tcp);
- if (!(qual_flags[tcp->scno] & QUAL_TRACE)) {
+ if (tcp->scno >=0 && tcp->scno < nsyscalls && !(qual_flags[tcp->scno] & QUAL_TRACE)) {
tcp->flags |= TCB_INSYSCALL;
return 0;
}
@@ -1483,11 +1618,11 @@
printleader(tcp);
tcp->flags &= ~TCB_REPRINT;
tcp_last = tcp;
- if (tcp->scno >= nsyscalls)
+ if (tcp->scno >= nsyscalls || tcp->scno < 0)
tprintf("syscall_%lu(", tcp->scno);
else
tprintf("%s(", sysent[tcp->scno].sys_name);
- if (tcp->scno >= nsyscalls ||
+ if (tcp->scno >= nsyscalls || tcp->scno < 0 ||
((qual_flags[tcp->scno] & QUAL_RAW) && tcp->scno != SYS_exit))
sys_res = printargs(tcp);
else
@@ -1545,7 +1680,11 @@
val = tcp->status.PR_REG[CTX_V1];
#endif /* MIPS */
#endif /* SVR4 */
-
+#ifdef FREEBSD
+ struct reg regs;
+ pread(tcp->pfd_reg, ®s, sizeof(regs), 0);
+ val = regs.r_edx;
+#endif
return val;
}
diff --git a/system.c b/system.c
index f16b711..39930b5 100644
--- a/system.c
+++ b/system.c
@@ -543,6 +543,19 @@
{ 0, NULL },
};
+int
+sys_sysconf(tcp)
+struct tcb *tcp;
+{
+ if (entering(tcp)) {
+ printxval(sysconflimits, tcp->u_arg[0], "_SC_???");
+ }
+ return 0;
+}
+
+#endif /* SUNOS4 */
+
+#if defined(SUNOS4) || defined(FREEBSD)
static struct xlat pathconflimits[] = {
#ifdef _PC_LINK_MAX
{ _PC_LINK_MAX, "_PC_LINK_MAX" }, /* max links to file/dir */
@@ -574,15 +587,6 @@
{ 0, NULL },
};
-int
-sys_sysconf(tcp)
-struct tcb *tcp;
-{
- if (entering(tcp)) {
- printxval(sysconflimits, tcp->u_arg[0], "_SC_???");
- }
- return 0;
-}
int
sys_pathconf(tcp)
@@ -591,7 +595,7 @@
if (entering(tcp)) {
printstr(tcp, tcp->u_arg[0], -1);
tprintf(", ");
- printxval(pathconflimits, tcp->u_arg[1], "_SC_???");
+ printxval(pathconflimits, tcp->u_arg[1], "_PC_???");
}
return 0;
}
@@ -602,12 +606,12 @@
{
if (entering(tcp)) {
tprintf("%lu, ", tcp->u_arg[0]);
- printxval(pathconflimits, tcp->u_arg[1], "_SC_???");
+ printxval(pathconflimits, tcp->u_arg[1], "_PC_???");
}
return 0;
}
-#endif /* SUNOS4 */
+#endif /* SUNOS4 || FREEBSD */
#ifdef SVR4
@@ -1903,6 +1907,55 @@
}
#endif
+#ifdef FREEBSD
+#include <sys/sysctl.h>
+
+int sys___sysctl(tcp)
+struct tcb *tcp;
+{
+ int qoid[CTL_MAXNAME+2];
+ char ctl[1024];
+ size_t len;
+ int i, numeric;
+
+ if (entering(tcp)) {
+ if (tcp->u_arg[1] < 0 || tcp->u_arg[1] > CTL_MAXNAME ||
+ (umoven(tcp, tcp->u_arg[0], tcp->u_arg[1] * sizeof(int),
+ (char *) (qoid + 2)) < 0))
+ tprintf("[...], ");
+ else {
+ /* Use sysctl to ask the name of the current MIB
+ This uses the undocumented "Staff-functions" used
+ by the sysctl program. See kern_sysctl.c for
+ details. */
+ qoid[0] = 0; /* sysctl */
+ qoid[1] = 1; /* name */
+ i = sizeof(ctl);
+ tprintf("[");
+ if (sysctl(qoid, tcp->u_arg[1] + 2, ctl, &i, 0, 0) >= 0) {
+ numeric = !abbrev(tcp);
+ tprintf("%s%s", ctl, numeric ? ", " : "");
+ } else
+ numeric = 1;
+ if (numeric) {
+ for (i = 0; i < tcp->u_arg[1]; i++)
+ tprintf("%s%d", i ? "." : "", qoid[i + 2]);
+ }
+ tprintf("], ");
+ tprintf("%lu, ", tcp->u_arg[1]);
+ }
+ } else {
+ if (!syserror(tcp) && (umove(tcp, tcp->u_arg[3], &len) >= 0)) {
+ printstr(tcp, tcp->u_arg[2], len);
+ tprintf(", [%u], ", len);
+ } else
+ tprintf("%#lx, %#lx, ", tcp->u_arg[2], tcp->u_arg[3]);
+ printstr(tcp, tcp->u_arg[4], tcp->u_arg[5]);
+ tprintf(", %lu", tcp->u_arg[5]);
+ }
+ return 0;
+}
+#endif
#if UNIXWARE >= 2
diff --git a/term.c b/term.c
index 4cf10a9..db15ef9 100644
--- a/term.c
+++ b/term.c
@@ -47,12 +47,14 @@
{ 0, NULL },
};
+#ifdef TCLFLSH
static struct xlat tcflsh_options[] = {
{ TCIFLUSH, "TCIFLUSH" },
{ TCOFLUSH, "TCOFLUSH" },
{ TCIOFLUSH, "TCIOFLUSH" },
{ 0, NULL },
};
+#endif
static struct xlat baud_options[] = {
{ B0, "B0" },
@@ -173,7 +175,11 @@
long code, arg;
{
struct termios tios;
+#ifndef FREEBSD
struct termio tio;
+#else
+ struct termios tio;
+#endif
struct winsize ws;
#ifdef TIOCGSIZE
struct ttysize ts;
@@ -290,15 +296,18 @@
#endif
/* ioctls with a direct decodable arg */
-
+#ifdef TCXONC
case TCXONC:
tprintf(", ");
printxval(tcxonc_options, arg, "TC???");
return 1;
+#endif
+#ifdef TCLFLSH
case TCFLSH:
tprintf(", ");
printxval(tcflsh_options, arg, "TC???");
return 1;
+#endif
/* ioctls with an indirect parameter displayed as modem flags */
diff --git a/util.c b/util.c
index f0810b4..c0b7cc0 100644
--- a/util.c
+++ b/util.c
@@ -630,7 +630,7 @@
#endif /* !oldway */
#endif /* SUNOS4 */
-#ifdef SVR4
+#ifdef USE_PROCFS
#ifdef HAVE_MP_PROCFS
if (pread(tcp->pfd_as, laddr, len, addr) == -1)
return -1;
@@ -651,7 +651,7 @@
return -1;
#endif /* !HAVE_PREAD */
#endif /* HAVE_MP_PROCFS */
-#endif /* SVR4 */
+#endif /* USE_PROCFS */
return 0;
}
@@ -667,9 +667,9 @@
int len;
char *laddr;
{
-#ifdef SVR4
+#ifdef USE_PROCFS
return umoven(tcp, addr, len, laddr);
-#else /* !SVR4 */
+#else /* !USE_PROCFS */
int started = 0;
int pid = tcp->pid;
int i, n, m;
@@ -719,7 +719,7 @@
addr += sizeof(long), laddr += m, len -= m;
}
return 0;
-#endif /* !SVR4 */
+#endif /* !USE_PROCFS */
}
#ifdef LINUX
@@ -821,7 +821,7 @@
#endif /* SUNOS4 */
-#ifndef SVR4
+#ifndef USE_PROCFS
int
upeek(pid, off, res)
@@ -865,7 +865,7 @@
return 0;
}
-#endif /* !SVR4 */
+#endif /* !USE_PROCFS */
long
getpc(tcp)
@@ -925,6 +925,11 @@
return 0;
#endif /* SVR4 */
+#ifdef FREEBSD
+ struct reg regs;
+ pread(tcp->pfd_reg, ®s, sizeof(regs), 0);
+ return regs.r_eip;
+#endif /* FREEBSD */
}
void
@@ -999,9 +1004,14 @@
tprintf("[????????] ");
#endif
+#ifdef FREEBSD
+ struct reg regs;
+ pread(tcp->pfd_reg, ®s, sizeof(regs), 0);
+ tprintf("[%08x] ", regs.r_eip);
+#endif /* FREEBSD */
}
-#ifndef SVR4
+#ifndef USE_PROCFS
int
setbpt(tcp)
@@ -1388,7 +1398,7 @@
return 0;
}
-#endif /* !SVR4 */
+#endif /* !USE_PROCFS */
#ifdef SUNOS4