From bf79f2e16b090ffe59cd1e1820935680a2da7b78 Mon Sep 17 00:00:00 2001 From: Wichert Akkerman Date: Fri, 1 Sep 2000 21:03:06 +0000 Subject: [PATCH] Add FreeBSD support --- CREDITS | 1 + ChangeLog | 5 + Makefile.in | 4 +- acconfig.h | 3 + configure.in | 7 +- defs.h | 52 +++++++++- file.c | 202 ++++++++++++++++++++++++++++++++++++-- freebsd/.cvsignore | 1 + freebsd/ioctlent.sh | 62 ++++++++++++ freebsd/syscalls.cat | 177 ++++++++++++++++++++++++++++++++++ freebsd/syscalls.pl | 151 +++++++++++++++++++++++++++++ freebsd/syscalls.print | 192 ++++++++++++++++++++++++++++++++++++ io.c | 144 +++++++++++++++++---------- ioctl.c | 13 ++- ipc.c | 8 +- mem.c | 20 ++++ net.c | 3 + proc.c | 85 ++++++++++++++++ process.c | 72 ++++++++++++-- resource.c | 22 ++++- signal.c | 40 ++++---- strace.c | 214 +++++++++++++++++++++++++++++++++-------- stream.c | 14 ++- syscall.c | 193 +++++++++++++++++++++++++++++++------ system.c | 77 ++++++++++++--- term.c | 11 ++- util.c | 28 ++++-- 27 files changed, 1608 insertions(+), 193 deletions(-) create mode 100644 freebsd/.cvsignore create mode 100644 freebsd/ioctlent.sh create mode 100644 freebsd/syscalls.cat create mode 100644 freebsd/syscalls.pl create mode 100644 freebsd/syscalls.print diff --git a/CREDITS b/CREDITS index 4ff1bc87..ed03b500 100644 --- a/CREDITS +++ b/CREDITS @@ -39,3 +39,4 @@ porting to new systems: Florian Lohoff D.J. Barrow Topi Miettinen + Gaël Roualland diff --git a/ChangeLog b/ChangeLog index 12050bd2..7f6d4381 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2000-09-01 Wichert Akkerman + + * lots of files: merge patch from Gaël Roualland to add + support for FreeBSD. + 2000-08-09 Wichert Akkerman * file.c: update to reflect that st_ino suddenly became a long long diff --git a/Makefile.in b/Makefile.in index 8b070f94..ca72d1da 100644 --- a/Makefile.in +++ b/Makefile.in @@ -20,7 +20,7 @@ CPPFLAGS = @CPPFLAGS@ 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 @@ SHELL = /bin/sh 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 2a711d90..b86ddfab 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 c59e5834..9f74a54a 100644 --- a/configure.in +++ b/configure.in @@ -22,6 +22,9 @@ sysv5*) irix[56]*) opsys=svr4 ;; +freebsd*) + opsys=freebsd + ;; *) AC_MSG_ERROR(this operating system is not yet supported by strace) ;; @@ -30,7 +33,7 @@ AC_MSG_RESULT($opsys) # 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 @@ if test x$OPSYS != xLINUX; then 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 906d62e2..4dbed044 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 +#include +#include +#endif + +#ifdef USE_PROCFS #include #ifdef HAVE_MP_PROCFS #include #endif -#else /* !SVR4 */ +#ifdef FREEBSD +#include +#endif /* FREEBSD */ +#else /* !USE_PROCFS */ #if defined(LINUXSPARC) && defined(__GLIBC__) #include #else @@ -184,6 +202,22 @@ extern int mp_ioctl (int f, int c, void *a, int s); #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 @@ struct tcb { 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 @@ struct xlat { #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_sortby P((char *)); 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 @@ extern int fixvfork P((struct tcb *)); #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 a53d229b..a74beda9 100644 --- a/file.c +++ b/file.c @@ -120,7 +120,15 @@ struct stat { # include #endif /* SVR4 */ +#ifdef HAVE_SYS_VFS_H #include +#endif + +#ifdef FREEBSD +#include +#include +#include +#endif #ifdef MAJOR_IN_SYSMACROS #include @@ -222,6 +230,12 @@ struct xlat openmodes[] = { #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 @@ int 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 @@ struct tcb *tcp; { 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 @@ sys_ftruncate(tcp) 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 @@ long addr; } #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 @@ struct stat *statbuf; 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 @@ struct tcb *tcp; #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 @@ struct tcb *tcp; 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 @@ struct tcb *tcp; 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 @@ struct tcb *tcp; } #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 00000000..f3c7a7c5 --- /dev/null +++ b/freebsd/.cvsignore @@ -0,0 +1 @@ +Makefile diff --git a/freebsd/ioctlent.sh b/freebsd/ioctlent.sh new file mode 100644 index 00000000..7d8a21c9 --- /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 ' +echo '#include ' +echo '#include ' +echo '#include ' +echo '#include ' +echo '#include ' +echo '#include ' +echo '#include ' +echo '#include ' +echo '#include ' +echo '#include ' +echo '#include ' +echo '#include ' +echo '#include ' +echo '#include ' +echo '#include ' +echo '#include ' +echo '#include ' +echo '#include ' +echo '#include ' +echo '#include ' +echo '#include ' +echo '#include ' +echo '#include ' +echo '#include ' +echo '#include ' +echo '#include ' +echo '#include ' +echo +echo "$ioctl_includes" | sed -e 's/^/#include /' +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 00000000..0dde7b64 --- /dev/null +++ b/freebsd/syscalls.cat @@ -0,0 +1,177 @@ +# +# Copyright (c) 2000, Gaël Roualland +# 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 00000000..0b072a97 --- /dev/null +++ b/freebsd/syscalls.pl @@ -0,0 +1,151 @@ +#!/usr/bin/perl -w +# +# Copyright (c) 2000, Gaël Roualland +# 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_ 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 [] []\n"; + exit 1; +} + +sub readprint ($) { + my($fprint) = @_; + + open (PRINT, "< $fprint") || die "can't open $fprint: $!"; + while() { + 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() { + 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 () { + chomp; + # join broken lines + while (/\\$/) { + my $line; + s/\\$//; + $line = ; + 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 00000000..bc59a6f2 --- /dev/null +++ b/freebsd/syscalls.print @@ -0,0 +1,192 @@ +# +# Copyright (c) 2000, Gaël Roualland +# 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 45c34135..a819c111 100644 --- a/io.c +++ b/io.c @@ -63,13 +63,47 @@ struct tcb *tcp; 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 @@ struct tcb *tcp; 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 @@ int 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 @@ struct tcb *tcp; /* 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 @@ struct tcb *tcp; /* 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 +#include + +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 f4bb784e..ed2a32bc 100644 --- a/ioctl.c +++ b/ioctl.c @@ -105,15 +105,22 @@ long code, arg; #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 e4dacabd..06688f0a 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 #include @@ -98,8 +98,12 @@ static struct xlat shmctl_flags[] = { { 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 @@ struct tcb *tcp; return 0; } -#endif /* defined(LINUX) || defined(SUNOS4) */ +#endif /* defined(LINUX) || defined(SUNOS4) || defined(FREEBSD) */ diff --git a/mem.c b/mem.c index 73a72fcc..0d728703 100644 --- a/mem.c +++ b/mem.c @@ -133,6 +133,22 @@ static struct xlat mmap_flags[] = { #endif #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 @@ long *u_arg; 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 db88c6d6..da061c87 100644 --- a/net.c +++ b/net.c @@ -36,6 +36,9 @@ #include #include #include +#ifdef FREEBSD +#include +#endif #include #if defined(LINUX) #include diff --git a/proc.c b/proc.c index d4969a6c..854657d4 100644 --- a/proc.c +++ b/proc.c @@ -186,3 +186,88 @@ int code, arg; #endif /* HAVE_MP_PROCFS */ #endif /* SVR4 */ +#ifdef FREEBSD +#include + +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 b409fa1f..dda3b9ee 100644 --- a/process.c +++ b/process.c @@ -49,6 +49,10 @@ #include #endif /* SUNOS4 */ +#ifdef FREEBSD +#include +#endif + #ifdef HAVE_SYS_REG_H # include #ifndef PTRACE_PEEKUSR @@ -333,7 +337,7 @@ struct tcb *tcp; return 0; } -#ifdef SVR4 +#ifdef USE_PROCFS int sys_fork(tcp) @@ -372,12 +376,13 @@ struct tcb *tcp; 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 @@ struct tcb *tcp; 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 @@ struct tcb *tcp; return 0; } -#endif /* SUNOS4 || LINUX */ +#endif /* SUNOS4 || LINUX || FREEBSD */ #ifndef LINUX @@ -832,7 +837,7 @@ struct tcb *tcp; return 0; } -#ifdef LINUX +#if defined(LINUX) || defined(FREEBSD) int sys_setresuid(tcp) struct tcb *tcp; @@ -858,7 +863,7 @@ sys_setresgid(tcp) return 0; } -#endif /* LINUX */ +#endif /* LINUX || FREEBSD */ int sys_setgroups(tcp) @@ -1280,6 +1285,25 @@ struct tcb *tcp; #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 @@ struct tcb *tcp; #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 @@ static struct xlat ptrace_cmds[] = { #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 @@ struct xlat struct_user_offsets[] = { { sizeof(struct user), "sizeof(struct user)" }, { 0, NULL }, }; +#endif int sys_ptrace(tcp) @@ -2049,10 +2095,15 @@ struct tcb *tcp; 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 @@ struct tcb *tcp; tprintf("%s, ", x->str); } else +#endif tprintf("%#lx, ", tcp->u_arg[2]); #ifdef LINUX switch (tcp->u_arg[0]) { @@ -2113,6 +2165,10 @@ struct tcb *tcp; } } #endif /* SUNOS4 */ +#ifdef FREEBSD + tprintf("%lu", tcp->u_arg[3]); + } +#endif /* FREEBSD */ return 0; } diff --git a/resource.c b/resource.c index 74222f4d..be776cec 100644 --- a/resource.c +++ b/resource.c @@ -41,7 +41,7 @@ #ifdef SUNOS4 #include #endif /* SUNOS4 */ -#ifdef SVR4 +#if defined(SVR4) || defined(FREEBSD) #include #include #endif @@ -439,14 +439,23 @@ struct tcb *tcp; #endif /* Linux */ -#ifdef SUNOS4 +#if defined(SUNOS4) || defined(FREEBSD) + +#ifdef FREEBSD +#include +#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 @@ struct tcb *tcp; { /* 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 90ac5fe8..1b807d88 100644 --- a/signal.c +++ b/signal.c @@ -146,7 +146,7 @@ int nsignals2 = sizeof signalent2 / sizeof signalent2[0]; char **signalent; int nsignals; -#ifdef SUNOS4 +#if defined(SUNOS4) || defined(FREEBSD) static struct xlat sigvec_flags[] = { { SV_ONSTACK, "SV_ONSTACK" }, @@ -156,7 +156,7 @@ static struct xlat sigvec_flags[] = { { 0, NULL }, }; -#endif /* SUNOS4 */ +#endif /* SUNOS4 || FREEBSD */ #ifdef HAVE_SIGACTION @@ -429,7 +429,7 @@ int sig; #endif /* !SVR4 */ } -#if defined(SUNOS4) +#if defined(SUNOS4) || defined(FREEBSD) int sys_sigvec(tcp) @@ -534,7 +534,7 @@ struct tcb *tcp; return 0; } -#endif /* SUNOS4 */ +#endif /* SUNOS4 || FREEBSD */ #ifndef SVR4 @@ -546,12 +546,14 @@ struct tcb *tcp; 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 @@ struct tcb *tcp; 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 @@ struct tcb *tcp; 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 @@ struct tcb *tcp; #endif /* LINUX */ -#ifdef SVR4 +#if defined(SVR4) || defined(FREEBSD) int sys_sigsuspend(tcp) @@ -976,6 +978,7 @@ struct tcb *tcp; } return 0; } +#ifndef FREEBSD static struct xlat ucontext_flags[] = { { UC_SIGMASK, "UC_SIGMASK" }, { UC_STACK, "UC_STACK" }, @@ -988,10 +991,10 @@ static struct xlat ucontext_flags[] = { #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 @@ typedef struct } 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 @@ struct tcb *tcp; #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 f96eaa04..3e4b4a61 100644 --- a/strace.c +++ b/strace.c @@ -44,9 +44,12 @@ #include #include +#ifdef USE_PROCFS +#include +#endif + #ifdef SVR4 #include -#include #ifdef HAVE_MP_PROCFS #include #endif @@ -87,7 +90,7 @@ static int interrupted; #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 @@ static int proc_poll_pipe[2] = { -1, -1 }; #else #define POLLWANT POLLPRI #endif -#endif /* SVR4 */ +#endif /* USE_PROCFS */ static void usage(ofp, exitval) @@ -334,19 +337,19 @@ char *argv[]; 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 @@ char *argv[]; 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 @@ char *argv[]; 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 @@ char *argv[]; } else setreuid(run_uid, run_uid); -#endif /* !SVR4 */ +#endif /* !USE_PROCFS */ execv(pathname, &argv[optind]); perror("strace: exec"); @@ -472,16 +479,16 @@ char *argv[]; 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 @@ char *argv[]; 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 @@ int pid; return NULL; } -#ifdef SVR4 +#ifdef USE_PROCFS int proc_open(tcp, attaching) struct tcb *tcp; @@ -580,9 +587,11 @@ int attaching; { 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 @@ int attaching; } #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 @@ int attaching; 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 @@ int attaching; 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 @@ int attaching; return -1; } #else /* !PIOCSET */ +#ifndef FREEBSD if (ioctl(tcp->pfd, PIOCSRLC) < 0) { perror("PIOCSRLC"); return -1; @@ -686,7 +722,20 @@ int attaching; 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 @@ int attaching; 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 @@ int attaching; */ 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 @@ int attaching; 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 @@ int attaching; return 0; } -#endif /* SVR4 */ +#endif /* USE_PROCFS */ static struct tcb * pid2tcb(pid) @@ -780,7 +861,7 @@ int pid; return NULL; } -#ifdef SVR4 +#ifdef USE_PROCFS static struct tcb * pfd2tcb(pfd) @@ -798,7 +879,7 @@ int pfd; return NULL; } -#endif /* SVR4 */ +#endif /* USE_PROCFS */ void droptcb(tcp) @@ -812,7 +893,17 @@ struct tcb *tcp; 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 @@ struct tcb *tcp; tcp->outf = 0; } -#ifndef SVR4 +#ifndef USE_PROCFS static int resume(tcp) @@ -852,7 +943,7 @@ struct tcb *tcp; return 0; } -#endif /* !SVR4 */ +#endif /* !USE_PROCFS */ /* detach traced process; continue with sig */ @@ -934,10 +1025,10 @@ int sig; 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 @@ int sig; return error; } -#ifdef SVR4 +#ifdef USE_PROCFS static void reaper(sig) @@ -966,7 +1057,7 @@ int sig; } } -#endif /* SVR4 */ +#endif /* USE_PROCFS */ static void cleanup() @@ -1054,7 +1145,7 @@ int sig; #endif /* HAVE_STRSIGNAL */ -#ifdef SVR4 +#ifdef USE_PROCFS static void rebuild_pollv() @@ -1141,6 +1232,9 @@ int pfd; int i; int n; struct rlimit rl; +#ifdef FREEBSD + struct procfs_status pfs; +#endif /* FREEBSD */ switch (fork()) { case -1: @@ -1180,7 +1274,11 @@ int pfd; 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 @@ trace() 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 @@ trace() case EINTR: case EBADF: continue; +#ifdef FREEBSD + case ENOTTY: +#endif case ENOENT: droptcb(tcp); continue; @@ -1371,15 +1482,27 @@ trace() 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 @@ trace() } } break; +#endif /* !FREEBSD */ case PR_SYSENTRY: #ifdef POLL_HACK in_syscall = tcp; @@ -1414,13 +1538,21 @@ trace() 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 @@ trace() return 0; } -#else /* !SVR4 */ +#else /* !USE_PROCFS */ static int trace() @@ -1667,7 +1799,7 @@ trace() return 0; } -#endif /* !SVR4 */ +#endif /* !USE_PROCFS */ static int curcol; diff --git a/stream.c b/stream.c index 0cc14a03..4abf861b 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 @@ struct strbuf { #else /* linux */ +#ifndef FREEBSD #include #include #include #include #include +#else /* FREEBSD */ +#include +#endif /* FREEBSD */ #endif /* linux */ @@ -62,6 +66,7 @@ struct strbuf { #include #endif /* HAVE_SYS_TIUSER_H */ +#ifndef FREEBSD static struct xlat msgflags[] = { { RS_HIPRI, "RS_HIPRI" }, { 0, NULL }, @@ -252,6 +257,7 @@ struct tcb *tcp; } #endif /* HAVE_PUTPMSG */ +#endif /* !FREEBSD */ #ifdef HAVE_SYS_POLL_H @@ -349,7 +355,7 @@ struct tcb *tcp; } #endif -#ifndef linux +#if !defined(linux) && !defined(FREEBSD) static struct xlat stream_flush_options[] = { { FLUSHR, "FLUSHR" }, @@ -824,7 +830,7 @@ int code, arg; } } -#endif /* linux */ +#endif /* !linux && !FREEBSD */ -#endif /* LINUXSPARC && linux */ +#endif /* HAVE_SYS_STREAM_H || linux || FREEBSD */ diff --git a/syscall.c b/syscall.c index 96424460..e59b16fb 100644 --- a/syscall.c +++ b/syscall.c @@ -410,7 +410,23 @@ struct tcb *tcp; } } +#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 @@ int nsubcalls; 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 @@ enum subcall_style style; 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 @@ struct tcb *tcp; 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 @@ struct tcb *tcp; 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 @@ int 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 @@ struct tcb *tcp; tcp->flags &= ~TCB_INSYSCALL; } } -#endif /* SVR4 */ +#endif /* USE_PROCFS */ #ifdef SUNOS4 if (!(tcp->flags & TCB_INSYSCALL)) { if (scno == 0) { @@ -1054,6 +1110,17 @@ struct tcb *tcp; } #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 @@ struct tcb *tcp; 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 @@ struct tcb *tcp; #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 @@ struct tcb *tcp; 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 @@ struct tcb *tcp; 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 @@ struct tcb *tcp; #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 @@ struct tcb *tcp; #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 @@ struct tcb *tcp; #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 @@ struct tcb *tcp; * 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 @@ struct tcb *tcp; } #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 @@ struct tcb *tcp; } #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 @@ struct tcb *tcp; #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 @@ struct tcb *tcp; 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 @@ struct tcb *tcp; 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 @@ struct tcb *tcp; 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 @@ struct tcb *tcp; 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 @@ struct tcb *tcp; tprintf("= %ld", tcp->u_rval); break; #ifdef HAVE_LONG_LONG + case RVAL_LHEX: + tprintf("= %#llx", tcp->u_lrval); + break; + 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); + tprintf("= %lld", tcp->u_lrval); break; - /* LHEX, LOCTAL, LUDECIMAL... */ #endif default: fprintf(stderr, @@ -1452,6 +1580,13 @@ struct tcb *tcp; 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 @@ struct tcb *tcp; } 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 @@ struct tcb *tcp; 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 @@ struct tcb *tcp; 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 f16b711c..39930b57 100644 --- a/system.c +++ b/system.c @@ -543,6 +543,19 @@ static struct xlat sysconflimits[] = { { 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 @@ static struct xlat pathconflimits[] = { { 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 @@ struct tcb *tcp; 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 @@ struct tcb *tcp; { 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 @@ struct tcb *tcp; } #endif +#ifdef FREEBSD +#include + +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 4cf10a92..db15ef9b 100644 --- a/term.c +++ b/term.c @@ -47,12 +47,14 @@ static struct xlat tcxonc_options[] = { { 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 @@ struct tcb *tcp; 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 @@ long code, arg; #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 f0810b41..c0b7cc0c 100644 --- a/util.c +++ b/util.c @@ -630,7 +630,7 @@ char *laddr; #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 @@ char *laddr; return -1; #endif /* !HAVE_PREAD */ #endif /* HAVE_MP_PROCFS */ -#endif /* SVR4 */ +#endif /* USE_PROCFS */ return 0; } @@ -667,9 +667,9 @@ long addr; 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 @@ char *laddr; addr += sizeof(long), laddr += m, len -= m; } return 0; -#endif /* !SVR4 */ +#endif /* !USE_PROCFS */ } #ifdef LINUX @@ -821,7 +821,7 @@ char *laddr; #endif /* SUNOS4 */ -#ifndef SVR4 +#ifndef USE_PROCFS int upeek(pid, off, res) @@ -865,7 +865,7 @@ long *res; return 0; } -#endif /* !SVR4 */ +#endif /* !USE_PROCFS */ long getpc(tcp) @@ -925,6 +925,11 @@ struct tcb *tcp; 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 @@ struct tcb *tcp; 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 @@ struct tcb *tcp; return 0; } -#endif /* !SVR4 */ +#endif /* !USE_PROCFS */ #ifdef SUNOS4 -- 2.40.0