Add FreeBSD support

This commit is contained in:
Wichert Akkerman 2000-09-01 21:03:06 +00:00
parent d077c451cd
commit bf79f2e16b
27 changed files with 1608 additions and 193 deletions

View File

@ -39,3 +39,4 @@ porting to new systems:
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>

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

52
defs.h
View File

@ -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 @@ 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

202
file.c
View File

@ -120,7 +120,15 @@ struct stat {
# 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 @@ 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

1
freebsd/.cvsignore Normal file
View File

@ -0,0 +1 @@
Makefile

62
freebsd/ioctlent.sh Normal file
View File

@ -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 '};'

177
freebsd/syscalls.cat Normal file
View File

@ -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

151
freebsd/syscalls.pl Normal file
View File

@ -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";
}
}
}

192
freebsd/syscalls.print Normal file
View File

@ -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

144
io.c
View File

@ -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 <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

13
ioctl.c
View File

@ -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);

8
ipc.c
View File

@ -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 @@ 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) */

20
mem.c
View File

@ -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 */

3
net.c
View File

@ -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>

85
proc.c
View File

@ -186,3 +186,88 @@ int code, arg;
#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

View File

@ -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 @@ 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;
}

View File

@ -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 @@ struct tcb *tcp;
#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 @@ 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 */

View File

@ -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)

212
strace.c
View File

@ -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 @@ 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;

View File

@ -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 <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 @@ struct strbuf {
#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 @@ 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 */

195
syscall.c
View File

@ -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, &regs, 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] = *((&regs.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_LDECIMAL:
tprintf ("= %lld", tcp->u_lrval);
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);
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, &regs, sizeof(regs), 0);
val = regs.r_edx;
#endif
return val;
}

View File

@ -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 <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

11
term.c
View File

@ -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 */

28
util.c
View File

@ -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, &regs, 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, &regs, 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