 dev/null                                     | 7804 ---------------------------
 Makefile.am                                  |    0 
 arch/common-freebsd/Makefile.am              |    0 
 addrcheck/Makefile.am                        |    2 
 auxprogs/Makefile.am                         |    3 
 cachegrind/Makefile.am                       |    2 
 configure.in                                 |   23 
 corecheck/Makefile.am                        |    2 
 coregrind/Makefile.am                        |   33 
 coregrind/arch/Makefile.am                   |    4 
 coregrind/arch/common-freebsd/vg_syscalls.c  |  702 ++
 coregrind/arch/common-freebsd/vg_unsafe.h    |   39 
 coregrind/arch/common-linux/Makefile.am      |    2 
 coregrind/arch/common-linux/vg_syscalls.c    |  907 +++
 coregrind/arch/common-linux/vg_unsafe.h      |   99 
 coregrind/arch/common-unix/Makefile.am       |    2 
 coregrind/arch/common-unix/vg_syscalls.c     | 1438 ++++
 coregrind/arch/i386-common/Makefile.am       |    9 
 coregrind/arch/i386-common/vg_dispatch.S     |  229 
 coregrind/arch/i386-common/vg_helpers.S      |  603 ++
 coregrind/arch/i386-common/vg_proxylwp.c     |  132 
 coregrind/arch/i386-freebsd/Makefile.am      |   27 
 coregrind/arch/i386-freebsd/ume_archdefs.c   |   29 
 coregrind/arch/i386-freebsd/ume_entry.S      |   38 
 coregrind/arch/i386-freebsd/ume_go.c         |   51 
 coregrind/arch/i386-freebsd/vg_helpers.S     |   87 
 coregrind/arch/i386-freebsd/vg_kerneliface.h |  724 ++
 coregrind/arch/i386-freebsd/vg_syscall.S     |  181 
 coregrind/arch/i386-freebsd/vg_syscalls.c    |  263 
 coregrind/arch/i386-freebsd/vg_syscalls.h    |   26 
 coregrind/arch/i386-freebsd/vg_unistd.h      |  353 +
 coregrind/arch/i386-linux/Makefile.am        |   28 
 coregrind/arch/i386-linux/ume_archdefs.c     |   29 
 coregrind/arch/i386-linux/ume_archdefs.h     |   32 
 coregrind/arch/i386-linux/ume_entry.S        |   38 
 coregrind/arch/i386-linux/ume_go.c           |   51 
 coregrind/arch/i386-linux/vg_helpers.S       |   87 
 coregrind/arch/i386-linux/vg_kerneliface.h   |  781 ++
 coregrind/arch/i386-linux/vg_proxylwp.c      |  186 
 coregrind/arch/i386-linux/vg_syscall.S       |  118 
 coregrind/arch/i386-linux/vg_syscalls.c      | 3162 ++++++++++
 coregrind/arch/i386-linux/vg_syscalls.h      |   17 
 coregrind/arch/i386-linux/vg_unistd.h        |  311 +
 coregrind/demangle/Makefile.am               |    8 
 coregrind/ume.h                              |    3 
 coregrind/vg_include.h                       |    3 
 coregrind/vg_proxylwp.c                      |  241 
 coregrind/vg_proxylwp.h                      |   62 
 helgrind/Makefile.am                         |    2 
 include/Makefile.am                          |    3 
 lackey/Makefile.am                           |    2 
 memcheck/Makefile.am                         |    2 
 none/Makefile.am                             |    2 
 53 files changed, 10909 insertions(+), 8073 deletions(-)

diff -puN configure.in~archdep configure.in
--- valgrind/configure.in~archdep	2004-01-27 11:09:02.000000000 -0800
+++ valgrind-jeremy/configure.in	2004-01-27 11:09:02.000000000 -0800
@@ -1,7 +1,7 @@
 # Process this file with autoconf to produce a configure script.
 AC_INIT(coregrind/vg_main.c)   # give me a source file, any source file...
 AM_CONFIG_HEADER(config.h)
-AM_INIT_AUTOMAKE(valgrind, 2.1.0)
+AM_INIT_AUTOMAKE(valgrind, 2.1.1)
 
 AM_MAINTAINER_MODE
 
@@ -78,12 +78,17 @@ case "${host_cpu}" in
 esac
 
 AC_MSG_CHECKING([for a supported OS])
+AC_SUBST(VG_PLAT_ARCH)
+AC_SUBST(VG_PLAT_OS)
+AC_SUBST(VG_PLAT_DIRS)
+AC_SUBST(VG_PLAT_INCLUDES)
 AC_SUBST(VG_PLATFORM)
 
 case "${host_os}" in
      *linux*)
 	AC_MSG_RESULT([ok (${host_os})])
-        VG_PLATFORM="x86-linux"
+	VG_PLAT_ARCH=`uname -i`
+	VG_PLAT_OS=linux
 
         # Ok, this is linux. Check the kernel version
         AC_MSG_CHECKING([for the kernel version])
@@ -116,8 +121,8 @@ case "${host_os}" in
 
      *freebsd*)
         AC_MSG_RESULT([ok (${host_os})])
-        VG_PLATFORM="x86-freebsd"
-
+	VG_PLAT_ARCH=i386
+	VG_PLAT_OS=freebsd
         ;;
 
      *) 
@@ -126,6 +131,9 @@ case "${host_os}" in
 	;;
 esac
 
+VG_PLATFORM="$VG_PLAT_ARCH-$VG_PLAT_OS"
+VG_PLAT_DIRS="$VG_PLATFORM common-$VG_PLAT_OS $VG_PLAT_ARCH-common common-unix"
+VG_PLAT_INCLUDES=`[echo $VG_PLAT_DIRS | sed "s,\([^ ]*\),-I\\$(top_srcdir)/coregrind/arch/\1,g"]`
 
 AC_SUBST(DEFAULT_SUPP)
 
@@ -358,8 +366,11 @@ AC_OUTPUT(
    auxprogs/Makefile
    coregrind/Makefile 
    coregrind/arch/Makefile
-   coregrind/arch/x86-linux/Makefile
-   coregrind/arch/x86-freebsd/Makefile
+   coregrind/arch/i386-linux/Makefile
+   coregrind/arch/common-linux/Makefile
+   coregrind/arch/i386-freebsd/Makefile
+   coregrind/arch/common-freebsd/Makefile
+   coregrind/arch/i386-common/Makefile
    coregrind/demangle/Makefile 
    coregrind/docs/Makefile
    coregrind/x86/Makefile
diff -puN Makefile.am~archdep Makefile.am
diff -puN coregrind/Makefile.am~archdep coregrind/Makefile.am
--- valgrind/coregrind/Makefile.am~archdep	2004-01-27 11:09:02.000000000 -0800
+++ valgrind-jeremy/coregrind/Makefile.am	2004-01-27 11:11:43.000000000 -0800
@@ -1,7 +1,11 @@
 
-SUBDIRS = x86 demangle . docs
+SUBDIRS = arch demangle . docs
 
-add_includes = -I$(srcdir)/demangle -I$(top_srcdir)/include -I$(srcdir)/x86
+archdirs=$(addprefix $(srcdir)/arch/,$(VG_PLAT_DIRS))
+archlibs=$(wildcard $(addsuffix /libarch.a,$(archdirs)))
+
+add_includes = -I$(srcdir)/demangle -I$(top_srcdir)/include \
+	$(VG_PLAT_INCLUDES)
 
 valdir = $(libdir)/valgrind
 inplacedir = $(top_srcdir)/.in_place
@@ -31,27 +35,21 @@ CLEANFILES = vg_toolint.c vg_toolint.h
 
 valgrind_SOURCES = \
 	stage1.c \
-	ume.c \
-	x86/ume_entry.S \
-	x86/ume_go.c 
+	ume.c
 valgrind_DEPENDENCIES =
 valgrind_LDFLAGS=-static -g -Wl,-e,_ume_entry
-valgrind_LDADD=
+valgrind_LDADD=$(archlibs)
 
 stage2_SOURCES = \
 	ume.c \
-	x86/ume_entry.S \
-	x86/ume_go.c \
 	\
 	vg_scheduler.c \
 	vg_default.c \
 	vg_demangle.c \
-	vg_dispatch.S \
 	vg_errcontext.c \
 	vg_execontext.c \
 	vg_from_ucode.c \
 	vg_hashtable.c \
-	vg_helpers.S \
 	vg_instrument.c \
 	vg_main.c \
 	vg_malloc2.c \
@@ -69,23 +67,22 @@ stage2_SOURCES = \
 	vg_stabs.c \
 	vg_skiplist.c \
 	vg_symtypes.c \
-	vg_syscalls.c \
-	vg_syscall.S \
 	vg_to_ucode.c \
 	vg_toolint.c \
 	vg_translate.c \
 	vg_transtab.c \
 	vg_ldt.c
-stage2_DEPENDENCIES = $(srcdir)/valgrind.vs $(srcdir)/x86/stage2.lds
+stage2_DEPENDENCIES = $(srcdir)/valgrind.vs $(srcdir)/arch/$(VG_PLATFORM)/stage2.lds
 stage2_LDFLAGS=-Wl,--export-dynamic -Wl,-e,_ume_entry  -g \
 	-Wl,-defsym,kickstart_base=0xb8000000 \
-	-Wl,-T,$(srcdir)/x86/stage2.lds \
+	-Wl,-T,$(srcdir)/arch/$(VG_PLATFORM)/stage2.lds \
 	-Wl,-version-script $(srcdir)/valgrind.vs 
 stage2_LDADD= \
 	demangle/cp-demangle.o \
 	demangle/cplus-dem.o \
 	demangle/dyn-string.o \
 	demangle/safe-ctype.o \
+	$(archlibs) \
 	-ldl
 
 vg_toolint.c: $(srcdir)/gen_toolint.pl $(srcdir)/toolfuncs.def $(srcdir)/Makefile
@@ -103,14 +100,14 @@ vg_toolint.h:  $(srcdir)/gen_toolint.pl 
 
 libpthread_so_SOURCES = \
 	vg_libpthread.c \
-	vg_libpthread_unimp.c \
-	vg_syscall.S
+	vg_libpthread_unimp.c
 libpthread_so_DEPENDENCIES = $(srcdir)/vg_libpthread.vs
 libpthread_so_LDFLAGS	   = -Werror -fno-omit-frame-pointer -UVG_LIBDIR \
 	-shared -fpic -ldl \
 	-Wl,-version-script $(srcdir)/vg_libpthread.vs \
 	-Wl,-z,nodelete \
 	-Wl,--soname=libpthread.so.0
+libpthread_so_LDADD = $(archlibs)
 
 vg_inject_so_SOURCES = \
 	vg_intercept.c 
@@ -130,10 +127,8 @@ noinst_HEADERS = \
         vg_include.h            \
         vg_constants.h          \
 	vg_symtab2.h		\
-        vg_unistd.h             \
 	vg_symtypes.h		\
-	vg_toolint.h		\
-	vg_unsafe.h
+	vg_toolint.h
 
 MANUAL_DEPS = $(noinst_HEADERS) $(include_HEADERS) $(inplacedir)/libpthread.so.0
 
diff -puN coregrind/arch/Makefile.am~archdep coregrind/arch/Makefile.am
--- valgrind/coregrind/arch/Makefile.am~archdep	2004-01-27 11:09:02.000000000 -0800
+++ valgrind-jeremy/coregrind/arch/Makefile.am	2004-01-27 11:09:02.000000000 -0800
@@ -1,2 +1,2 @@
-DIST_SUBDIRS=x86-linux x86-freebsd
-SUBDIRS=$(VG_PLATFORM)
+DIST_SUBDIRS=i386-linux i386-freebsd common-linux common-freebsd i386-common
+SUBDIRS=$(VG_PLAT_DIRS)
diff -puN coregrind/arch/common-freebsd/Makefile.am~archdep coregrind/arch/common-freebsd/Makefile.am
diff -puN /dev/null coregrind/arch/i386-freebsd/Makefile.am
--- /dev/null	2003-01-30 02:24:37.000000000 -0800
+++ valgrind-jeremy/coregrind/arch/i386-freebsd/Makefile.am	2004-01-27 11:09:02.000000000 -0800
@@ -0,0 +1,27 @@
+BUILT_SOURCES = stage2.lds 
+CLEANFILES = stage2.lds
+
+AM_CPPFLAGS=-I$(top_srcdir)/coregrind -I$(top_srcdir)/include $(VG_PLAT_INCLUDES)
+AM_CCASFLAGS=$(AM_CPPFLAGS)
+
+noinst_HEADERS = vg_unistd.h ume_archdefs.h
+
+noinst_LIBRARIES = libarch.a
+
+libarch_a_SOURCES = \
+	ume_archdefs.c \
+	ume_entry.S \
+	ume_go.c \
+	vg_helpers.S \
+	vg_syscall.S \
+	vg_syscalls.c
+
+# Extract ld's default linker script and hack it to our needs
+stage2.lds: Makefile
+	$(CC) -Wl,--verbose -nostdlib 2>&1 | sed \
+		-e '1,/^=====\+$$/d' \
+		-e '/^=====\+$$/d' \
+		-e 's/ENTRY(_start)/ENTRY(_ume_entry)/' \
+		-e 's/0x08048000/kickstart_base/g' > $@ || rm -f $@
+
+
diff -puN /dev/null coregrind/arch/i386-freebsd/vg_unistd.h
--- /dev/null	2003-01-30 02:24:37.000000000 -0800
+++ valgrind-jeremy/coregrind/arch/i386-freebsd/vg_unistd.h	2004-01-27 11:09:02.000000000 -0800
@@ -0,0 +1,353 @@
+#ifndef _VG_FREEBSD_UNISTD_H
+#define _VG_FREEBSD_UNISTD_H
+
+#define	__NR_syscall	0	/* XXX JSGF hm, syscall 0 might be a problem */
+#define	__NR_exit	1
+#define __NR_exit_group	__NR_exit /* match Linux */
+#define	__NR_fork	2
+#define	__NR_read	3
+#define	__NR_write	4
+#define	__NR_open	5
+#define	__NR_close	6
+#define	__NR_wait4	7
+				/* 8 is old creat */
+#define	__NR_link	9
+#define	__NR_unlink	10
+				/* 11 is obsolete execv */
+#define	__NR_chdir	12
+#define	__NR_fchdir	13
+#define	__NR_mknod	14
+#define	__NR_chmod	15
+#define	__NR_chown	16
+#define	__NR_brk	17
+#define	__NR_getfsstat	18
+				/* 19 is old lseek */
+#define	__NR_getpid	20
+#define	__NR_mount	21
+#define	__NR_unmount	22
+#define	__NR_setuid	23
+#define	__NR_getuid	24
+#define	__NR_geteuid	25
+#define	__NR_ptrace	26
+#define	__NR_recvmsg	27
+#define	__NR_sendmsg	28
+#define	__NR_recvfrom	29
+#define	__NR_accept	30
+#define	__NR_getpeername	31
+#define	__NR_getsockname	32
+#define	__NR_access	33
+#define	__NR_chflags	34
+#define	__NR_fchflags	35
+#define	__NR_sync	36
+#define	__NR_kill	37
+				/* 38 is old stat */
+#define	__NR_getppid	39
+				/* 40 is old lstat */
+#define	__NR_dup	41
+#define	__NR_pipe	42
+#define	__NR_getegid	43
+#define	__NR_profil	44
+#define	__NR_ktrace	45
+				/* 46 is old sigaction */
+#define	__NR_getgid	47
+				/* 48 is old sigprocmask */
+#define	__NR_getlogin	49
+#define	__NR_setlogin	50
+#define	__NR_acct	51
+				/* 52 is old sigpending */
+#define	__NR_sigaltstack	53
+#define	__NR_ioctl	54
+#define	__NR_reboot	55
+#define	__NR_revoke	56
+#define	__NR_symlink	57
+#define	__NR_readlink	58
+#define	__NR_execve	59
+#define	__NR_umask	60
+#define	__NR_chroot	61
+				/* 62 is old fstat */
+				/* 63 is old getkerninfo */
+				/* 64 is old getpagesize */
+#define	__NR_msync	65
+#define	__NR_vfork	66
+				/* 67 is obsolete vread */
+				/* 68 is obsolete vwrite */
+#define	__NR_sbrk	69
+#define	__NR_sstk	70
+				/* 71 is old mmap */
+#define	__NR_vadvise	72
+#define	__NR_munmap	73
+#define	__NR_mprotect	74
+#define	__NR_madvise	75
+				/* 76 is obsolete vhangup */
+				/* 77 is obsolete vlimit */
+#define	__NR_mincore	78
+#define	__NR_getgroups	79
+#define	__NR_setgroups	80
+#define	__NR_getpgrp	81
+#define	__NR_setpgid	82
+#define	__NR_setitimer	83
+				/* 84 is old wait */
+#define	__NR_swapon	85
+#define	__NR_getitimer	86
+				/* 87 is old gethostname */
+				/* 88 is old sethostname */
+#define	__NR_getdtablesize	89
+#define	__NR_dup2	90
+#define	__NR_fcntl	92
+#define	__NR_select	93
+#define	__NR_fsync	95
+#define	__NR_setpriority	96
+#define	__NR_socket	97
+#define	__NR_connect	98
+				/* 99 is old accept */
+#define	__NR_getpriority	100
+				/* 101 is old send */
+				/* 102 is old recv */
+				/* 103 is old sigreturn */
+#define	__NR_bind	104
+#define	__NR_setsockopt	105
+#define	__NR_listen	106
+				/* 107 is obsolete vtimes */
+				/* 108 is old sigvec */
+				/* 109 is old sigblock */
+				/* 110 is old sigsetmask */
+				/* 111 is old sigsuspend */
+				/* 112 is old sigstack */
+				/* 113 is old recvmsg */
+				/* 114 is old sendmsg */
+				/* 115 is obsolete vtrace */
+#define	__NR_gettimeofday	116
+#define	__NR_getrusage	117
+#define	__NR_getsockopt	118
+#define	__NR_readv	120
+#define	__NR_writev	121
+#define	__NR_settimeofday	122
+#define	__NR_fchown	123
+#define	__NR_fchmod	124
+				/* 125 is old recvfrom */
+#define	__NR_setreuid	126
+#define	__NR_setregid	127
+#define	__NR_rename	128
+				/* 129 is old truncate */
+				/* 130 is old ftruncate */
+#define	__NR_flock	131
+#define	__NR_mkfifo	132
+#define	__NR_sendto	133
+#define	__NR_shutdown	134
+#define	__NR_socketpair	135
+#define	__NR_mkdir	136
+#define	__NR_rmdir	137
+#define	__NR_utimes	138
+				/* 139 is obsolete 4.2 sigreturn */
+#define	__NR_adjtime	140
+				/* 141 is old getpeername */
+				/* 142 is old gethostid */
+				/* 143 is old sethostid */
+				/* 144 is old getrlimit */
+				/* 145 is old setrlimit */
+				/* 146 is old killpg */
+#define	__NR_setsid	147
+#define	__NR_quotactl	148
+				/* 149 is old quota */
+				/* 150 is old getsockname */
+#define	__NR_nfssvc	155
+				/* 156 is old getdirentries */
+#define	__NR_statfs	157
+#define	__NR_fstatfs	158
+#define	__NR_lgetfh	160
+#define	__NR_getfh	161
+#define	__NR_getdomainname	162
+#define	__NR_setdomainname	163
+#define	__NR_uname	164
+#define	__NR_sysarch	165
+#define	__NR_rtprio	166
+#define	__NR_semsys	169
+#define	__NR_msgsys	170
+#define	__NR_shmsys	171
+#define	__NR_pread	173
+#define	__NR_pwrite	174
+#define	__NR_ntp_adjtime	176
+#define	__NR_setgid	181
+#define	__NR_setegid	182
+#define	__NR_seteuid	183
+#define	__NR_stat	188
+#define	__NR_fstat	189
+#define	__NR_lstat	190
+#define	__NR_pathconf	191
+#define	__NR_fpathconf	192
+#define	__NR_getrlimit	194
+#define	__NR_setrlimit	195
+#define	__NR_getdirentries	196
+#define	__NR_mmap	197
+#define	__NR___syscall	198
+#define	__NR_lseek	199
+#define	__NR_truncate	200
+#define	__NR_ftruncate	201
+#define	__NR___sysctl	202
+#define	__NR_mlock	203
+#define	__NR_munlock	204
+#define	__NR_undelete	205
+#define	__NR_futimes	206
+#define	__NR_getpgid	207
+#define	__NR_poll	209
+#define	__NR___semctl	220
+#define	__NR_semget	221
+#define	__NR_semop	222
+#define	__NR_msgctl	224
+#define	__NR_msgget	225
+#define	__NR_msgsnd	226
+#define	__NR_msgrcv	227
+#define	__NR_shmat	228
+#define	__NR_shmctl	229
+#define	__NR_shmdt	230
+#define	__NR_shmget	231
+#define	__NR_clock_gettime	232
+#define	__NR_clock_settime	233
+#define	__NR_clock_getres	234
+#define	__NR_nanosleep	240
+#define	__NR_minherit	250
+#define	__NR_rfork	251
+#define	__NR_openbsd_poll	252
+#define	__NR_issetugid	253
+#define	__NR_lchown	254
+#define	__NR_getdents	272
+#define	__NR_lchmod	274
+#define	__NR_netbsd_lchown	275
+#define	__NR_lutimes	276
+#define	__NR_netbsd_msync	277
+#define	__NR_nstat	278
+#define	__NR_nfstat	279
+#define	__NR_nlstat	280
+#define	__NR_fhstatfs	297
+#define	__NR_fhopen	298
+#define	__NR_fhstat	299
+#define	__NR_modnext	300
+#define	__NR_modstat	301
+#define	__NR_modfnext	302
+#define	__NR_modfind	303
+#define	__NR_kldload	304
+#define	__NR_kldunload	305
+#define	__NR_kldfind	306
+#define	__NR_kldnext	307
+#define	__NR_kldstat	308
+#define	__NR_kldfirstmod	309
+#define	__NR_getsid	310
+#define	__NR_setresuid	311
+#define	__NR_setresgid	312
+				/* 313 is obsolete signanosleep */
+#define	__NR_aio_return	314
+#define	__NR_aio_suspend	315
+#define	__NR_aio_cancel	316
+#define	__NR_aio_error	317
+#define	__NR_aio_read	318
+#define	__NR_aio_write	319
+#define	__NR_lio_listio	320
+#define	__NR_yield	321
+				/* 322 is obsolete thr_sleep */
+				/* 323 is obsolete thr_wakeup */
+#define	__NR_mlockall	324
+#define	__NR_munlockall	325
+#define	__NR___getcwd	326
+#define	__NR_sched_setparam	327
+#define	__NR_sched_getparam	328
+#define	__NR_sched_setscheduler	329
+#define	__NR_sched_getscheduler	330
+#define	__NR_sched_yield	331
+#define	__NR_sched_get_priority_max	332
+#define	__NR_sched_get_priority_min	333
+#define	__NR_sched_rr_get_interval	334
+#define	__NR_utrace	335
+				/* 336 is old sendfile */
+#define	__NR_kldsym	337
+#define	__NR_jail	338
+#define	__NR_sigprocmask	340
+#define	__NR_sigsuspend	341
+				/* 342 is old sigaction */
+#define	__NR_sigpending	343
+				/* 344 is old sigreturn */
+#define	__NR_sigtimedwait	345
+#define __NR_rt_sigtimedwait	__NR_sigtimedwait /* match Linux */
+#define	__NR_sigwaitinfo	346
+#define	__NR___acl_get_file	347
+#define	__NR___acl_set_file	348
+#define	__NR___acl_get_fd	349
+#define	__NR___acl_set_fd	350
+#define	__NR___acl_delete_file	351
+#define	__NR___acl_delete_fd	352
+#define	__NR___acl_aclcheck_file	353
+#define	__NR___acl_aclcheck_fd	354
+#define	__NR_extattrctl	355
+#define	__NR_extattr_set_file	356
+#define	__NR_extattr_get_file	357
+#define	__NR_extattr_delete_file	358
+#define	__NR_aio_waitcomplete	359
+#define	__NR_getresuid	360
+#define	__NR_getresgid	361
+#define	__NR_kqueue	362
+#define	__NR_kevent	363
+#define	__NR_extattr_set_fd	371
+#define	__NR_extattr_get_fd	372
+#define	__NR_extattr_delete_fd	373
+#define	__NR___setugid	374
+#define	__NR_nfsclnt	375
+#define	__NR_eaccess	376
+#define	__NR_nmount	378
+#define	__NR_kse_exit	379
+#define	__NR_kse_wakeup	380
+#define	__NR_kse_create	381
+#define	__NR_kse_thr_interrupt	382
+#define	__NR_kse_release	383
+#define	__NR___mac_get_proc	384
+#define	__NR___mac_set_proc	385
+#define	__NR___mac_get_fd	386
+#define	__NR___mac_get_file	387
+#define	__NR___mac_set_fd	388
+#define	__NR___mac_set_file	389
+#define	__NR_kenv	390
+#define	__NR_lchflags	391
+#define	__NR_uuidgen	392
+#define	__NR_sendfile	393
+#define	__NR_mac_syscall	394
+#define	__NR_ksem_close	400
+#define	__NR_ksem_post	401
+#define	__NR_ksem_wait	402
+#define	__NR_ksem_trywait	403
+#define	__NR_ksem_init	404
+#define	__NR_ksem_open	405
+#define	__NR_ksem_unlink	406
+#define	__NR_ksem_getvalue	407
+#define	__NR_ksem_destroy	408
+#define	__NR___mac_get_pid	409
+#define	__NR___mac_get_link	410
+#define	__NR___mac_set_link	411
+#define	__NR_extattr_set_link	412
+#define	__NR_extattr_get_link	413
+#define	__NR_extattr_delete_link	414
+#define	__NR___mac_execve	415
+#define	__NR_sigaction	416
+#define	__NR_sigreturn	417
+#define	__NR_getcontext	421
+#define	__NR_setcontext	422
+#define	__NR_swapcontext	423
+#define	__NR_swapoff	424
+#define	__NR___acl_get_link	425
+#define	__NR___acl_set_link	426
+#define	__NR___acl_delete_link	427
+#define	__NR___acl_aclcheck_link	428
+#define	__NR_sigwait	429
+#define	__NR_thr_create	430
+#define	__NR_thr_exit	431
+#define	__NR_thr_self	432
+#define	__NR_thr_kill	433
+#define	__NR__umtx_lock	434
+#define	__NR__umtx_unlock	435
+#define	__NR_jail_attach	436
+#define	__NR_extattr_list_fd	437
+#define	__NR_extattr_list_file	438
+#define	__NR_extattr_list_link	439
+
+#define	__NR_adjtimex	176
+
+#define NR_syscalls 440
+
+#endif /* _VG_FREEBSD_UNISTD_H */
diff -puN /dev/null coregrind/arch/i386-linux/Makefile.am
--- /dev/null	2003-01-30 02:24:37.000000000 -0800
+++ valgrind-jeremy/coregrind/arch/i386-linux/Makefile.am	2004-01-27 11:09:02.000000000 -0800
@@ -0,0 +1,28 @@
+BUILT_SOURCES = stage2.lds 
+CLEANFILES = stage2.lds
+
+AM_CPPFLAGS=-I$(top_srcdir)/coregrind -I$(top_srcdir)/include $(VG_PLAT_INCLUDES)
+AM_CCASFLAGS=$(AM_CPPFLAGS)
+
+noinst_HEADERS = vg_unistd.h ume_archdefs.h vg_syscalls.h
+
+noinst_LIBRARIES = libarch.a
+
+libarch_a_SOURCES = \
+	ume_archdefs.c \
+	ume_entry.S \
+	ume_go.c \
+	vg_helpers.S \
+	vg_proxylwp.c \
+	vg_syscall.S \
+	vg_syscalls.c
+
+# Extract ld's default linker script and hack it to our needs
+stage2.lds: Makefile
+	$(CC) -Wl,--verbose -nostdlib 2>&1 | sed \
+		-e '1,/^=====\+$$/d' \
+		-e '/^=====\+$$/d' \
+		-e 's/ENTRY(_start)/ENTRY(_ume_entry)/' \
+		-e 's/0x08048000/kickstart_base/g' > $@ || rm -f $@
+
+
diff -puN /dev/null coregrind/arch/i386-linux/vg_unistd.h
--- /dev/null	2003-01-30 02:24:37.000000000 -0800
+++ valgrind-jeremy/coregrind/arch/i386-linux/vg_unistd.h	2004-01-27 11:09:02.000000000 -0800
@@ -0,0 +1,311 @@
+
+/*
+   This file is part of Valgrind, an extensible x86 protected-mode
+   emulator for monitoring program execution on x86-Unixes.
+
+   Copyright (C) 2000-2004 Julian Seward 
+      jseward@acm.org
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef _VG_ASM_I386_UNISTD_H_
+#define _VG_ASM_I386_UNISTD_H_
+/* Taken from Linux 2.6.0-test1 include/asm-i386/unistd.h */
+
+/*
+ * This file contains the system call numbers.
+ */
+
+#define __NR_restart_syscall      0
+#define __NR_exit		  1
+#define __NR_fork		  2
+#define __NR_read		  3
+#define __NR_write		  4
+#define __NR_open		  5
+#define __NR_close		  6
+#define __NR_waitpid		  7
+#define __NR_creat		  8
+#define __NR_link		  9
+#define __NR_unlink		 10
+#define __NR_execve		 11
+#define __NR_chdir		 12
+#define __NR_time		 13
+#define __NR_mknod		 14
+#define __NR_chmod		 15
+#define __NR_lchown		 16
+#define __NR_break		 17
+#define __NR_oldstat		 18
+#define __NR_lseek		 19
+#define __NR_getpid		 20
+#define __NR_mount		 21
+#define __NR_umount		 22
+#define __NR_setuid		 23
+#define __NR_getuid		 24
+#define __NR_stime		 25
+#define __NR_ptrace		 26
+#define __NR_alarm		 27
+#define __NR_oldfstat		 28
+#define __NR_pause		 29
+#define __NR_utime		 30
+#define __NR_stty		 31
+#define __NR_gtty		 32
+#define __NR_access		 33
+#define __NR_nice		 34
+#define __NR_ftime		 35
+#define __NR_sync		 36
+#define __NR_kill		 37
+#define __NR_rename		 38
+#define __NR_mkdir		 39
+#define __NR_rmdir		 40
+#define __NR_dup		 41
+#define __NR_pipe		 42
+#define __NR_times		 43
+#define __NR_prof		 44
+#define __NR_brk		 45
+#define __NR_setgid		 46
+#define __NR_getgid		 47
+#define __NR_signal		 48
+#define __NR_geteuid		 49
+#define __NR_getegid		 50
+#define __NR_acct		 51
+#define __NR_umount2		 52
+#define __NR_lock		 53
+#define __NR_ioctl		 54
+#define __NR_fcntl		 55
+#define __NR_mpx		 56
+#define __NR_setpgid		 57
+#define __NR_ulimit		 58
+#define __NR_oldolduname	 59
+#define __NR_umask		 60
+#define __NR_chroot		 61
+#define __NR_ustat		 62
+#define __NR_dup2		 63
+#define __NR_getppid		 64
+#define __NR_getpgrp		 65
+#define __NR_setsid		 66
+#define __NR_sigaction		 67
+#define __NR_sgetmask		 68
+#define __NR_ssetmask		 69
+#define __NR_setreuid		 70
+#define __NR_setregid		 71
+#define __NR_sigsuspend		 72
+#define __NR_sigpending		 73
+#define __NR_sethostname	 74
+#define __NR_setrlimit		 75
+#define __NR_getrlimit		 76	/* Back compatible 2Gig limited rlimit */
+#define __NR_getrusage		 77
+#define __NR_gettimeofday	 78
+#define __NR_settimeofday	 79
+#define __NR_getgroups		 80
+#define __NR_setgroups		 81
+#define __NR_select		 82
+#define __NR_symlink		 83
+#define __NR_oldlstat		 84
+#define __NR_readlink		 85
+#define __NR_uselib		 86
+#define __NR_swapon		 87
+#define __NR_reboot		 88
+#define __NR_readdir		 89
+#define __NR_mmap		 90
+#define __NR_munmap		 91
+#define __NR_truncate		 92
+#define __NR_ftruncate		 93
+#define __NR_fchmod		 94
+#define __NR_fchown		 95
+#define __NR_getpriority	 96
+#define __NR_setpriority	 97
+#define __NR_profil		 98
+#define __NR_statfs		 99
+#define __NR_fstatfs		100
+#define __NR_ioperm		101
+#define __NR_socketcall		102
+#define __NR_syslog		103
+#define __NR_setitimer		104
+#define __NR_getitimer		105
+#define __NR_stat		106
+#define __NR_lstat		107
+#define __NR_fstat		108
+#define __NR_olduname		109
+#define __NR_iopl		110
+#define __NR_vhangup		111
+#define __NR_idle		112
+#define __NR_vm86old		113
+#define __NR_wait4		114
+#define __NR_swapoff		115
+#define __NR_sysinfo		116
+#define __NR_ipc		117
+#define __NR_fsync		118
+#define __NR_sigreturn		119
+#define __NR_clone		120
+#define __NR_setdomainname	121
+#define __NR_uname		122
+#define __NR_modify_ldt		123
+#define __NR_adjtimex		124
+#define __NR_mprotect		125
+#define __NR_sigprocmask	126
+#define __NR_create_module	127
+#define __NR_init_module	128
+#define __NR_delete_module	129
+#define __NR_get_kernel_syms	130
+#define __NR_quotactl		131
+#define __NR_getpgid		132
+#define __NR_fchdir		133
+#define __NR_bdflush		134
+#define __NR_sysfs		135
+#define __NR_personality	136
+#define __NR_afs_syscall	137 /* Syscall for Andrew File System */
+#define __NR_setfsuid		138
+#define __NR_setfsgid		139
+#define __NR__llseek		140
+#define __NR_getdents		141
+#define __NR__newselect		142
+#define __NR_flock		143
+#define __NR_msync		144
+#define __NR_readv		145
+#define __NR_writev		146
+#define __NR_getsid		147
+#define __NR_fdatasync		148
+#define __NR__sysctl		149
+#define __NR_mlock		150
+#define __NR_munlock		151
+#define __NR_mlockall		152
+#define __NR_munlockall		153
+#define __NR_sched_setparam		154
+#define __NR_sched_getparam		155
+#define __NR_sched_setscheduler		156
+#define __NR_sched_getscheduler		157
+#define __NR_sched_yield		158
+#define __NR_sched_get_priority_max	159
+#define __NR_sched_get_priority_min	160
+#define __NR_sched_rr_get_interval	161
+#define __NR_nanosleep		162
+#define __NR_mremap		163
+#define __NR_setresuid		164
+#define __NR_getresuid		165
+#define __NR_vm86		166
+#define __NR_query_module	167
+#define __NR_poll		168
+#define __NR_nfsservctl		169
+#define __NR_setresgid		170
+#define __NR_getresgid		171
+#define __NR_prctl              172
+#define __NR_rt_sigreturn	173
+#define __NR_rt_sigaction	174
+#define __NR_rt_sigprocmask	175
+#define __NR_rt_sigpending	176
+#define __NR_rt_sigtimedwait	177
+#define __NR_rt_sigqueueinfo	178
+#define __NR_rt_sigsuspend	179
+#define __NR_pread64		180
+#define __NR_pwrite64		181
+#define __NR_chown		182
+#define __NR_getcwd		183
+#define __NR_capget		184
+#define __NR_capset		185
+#define __NR_sigaltstack	186
+#define __NR_sendfile		187
+#define __NR_getpmsg		188	/* some people actually want streams */
+#define __NR_putpmsg		189	/* some people actually want streams */
+#define __NR_vfork		190
+#define __NR_ugetrlimit		191	/* SuS compliant getrlimit */
+#define __NR_mmap2		192
+#define __NR_truncate64		193
+#define __NR_ftruncate64	194
+#define __NR_stat64		195
+#define __NR_lstat64		196
+#define __NR_fstat64		197
+#define __NR_lchown32		198
+#define __NR_getuid32		199
+#define __NR_getgid32		200
+#define __NR_geteuid32		201
+#define __NR_getegid32		202
+#define __NR_setreuid32		203
+#define __NR_setregid32		204
+#define __NR_getgroups32	205
+#define __NR_setgroups32	206
+#define __NR_fchown32		207
+#define __NR_setresuid32	208
+#define __NR_getresuid32	209
+#define __NR_setresgid32	210
+#define __NR_getresgid32	211
+#define __NR_chown32		212
+#define __NR_setuid32		213
+#define __NR_setgid32		214
+#define __NR_setfsuid32		215
+#define __NR_setfsgid32		216
+#define __NR_pivot_root		217
+#define __NR_mincore		218
+#define __NR_madvise		219
+#define __NR_madvise1		219	/* delete when C lib stub is removed */
+#define __NR_getdents64		220
+#define __NR_fcntl64		221
+/* 223 is unused */
+#define __NR_gettid		224
+#define __NR_readahead		225
+#define __NR_setxattr		226
+#define __NR_lsetxattr		227
+#define __NR_fsetxattr		228
+#define __NR_getxattr		229
+#define __NR_lgetxattr		230
+#define __NR_fgetxattr		231
+#define __NR_listxattr		232
+#define __NR_llistxattr		233
+#define __NR_flistxattr		234
+#define __NR_removexattr	235
+#define __NR_lremovexattr	236
+#define __NR_fremovexattr	237
+#define __NR_tkill		238
+#define __NR_sendfile64		239
+#define __NR_futex		240
+#define __NR_sched_setaffinity	241
+#define __NR_sched_getaffinity	242
+#define __NR_set_thread_area	243
+#define __NR_get_thread_area	244
+#define __NR_io_setup		245
+#define __NR_io_destroy		246
+#define __NR_io_getevents	247
+#define __NR_io_submit		248
+#define __NR_io_cancel		249
+#define __NR_fadvise64		250
+
+#define __NR_exit_group		252
+#define __NR_lookup_dcookie	253
+#define __NR_epoll_create	254
+#define __NR_epoll_ctl		255
+#define __NR_epoll_wait		256
+#define __NR_remap_file_pages	257
+#define __NR_set_tid_address	258
+#define __NR_timer_create	259
+#define __NR_timer_settime	(__NR_timer_create+1)
+#define __NR_timer_gettime	(__NR_timer_create+2)
+#define __NR_timer_getoverrun	(__NR_timer_create+3)
+#define __NR_timer_delete	(__NR_timer_create+4)
+#define __NR_clock_settime	(__NR_timer_create+5)
+#define __NR_clock_gettime	(__NR_timer_create+6)
+#define __NR_clock_getres	(__NR_timer_create+7)
+#define __NR_clock_nanosleep	(__NR_timer_create+8)
+#define __NR_statfs64		268
+#define __NR_fstatfs64		269
+#define __NR_tgkill		270
+#define __NR_utimes		271
+#define __NR_mknod64		272
+
+#define NR_syscalls 273
+
+#endif /* _VG_ASM_I386_UNISTD_H_ */
diff -puN /dev/null coregrind/arch/common-linux/Makefile.am
--- /dev/null	2003-01-30 02:24:37.000000000 -0800
+++ valgrind-jeremy/coregrind/arch/common-linux/Makefile.am	2004-01-27 11:09:02.000000000 -0800
@@ -0,0 +1,2 @@
+EXTRA_DIST = \
+	vg_syscalls.c
diff -puN /dev/null coregrind/arch/i386-common/Makefile.am
--- /dev/null	2003-01-30 02:24:37.000000000 -0800
+++ valgrind-jeremy/coregrind/arch/i386-common/Makefile.am	2004-01-27 11:09:02.000000000 -0800
@@ -0,0 +1,9 @@
+AM_CPPFLAGS=-I$(top_srcdir)/coregrind -I$(top_srcdir)/include $(VG_PLAT_INCLUDES)
+AM_CCASFLAGS=$(AM_CPPFLAGS)
+
+noinst_LIBRARIES = libarch.a
+
+libarch_a_SOURCES = \
+	vg_proxylwp.c \
+	vg_dispatch.S \
+	vg_helpers.S
diff -puN /dev/null coregrind/arch/common-unix/Makefile.am
--- /dev/null	2003-01-30 02:24:37.000000000 -0800
+++ valgrind-jeremy/coregrind/arch/common-unix/Makefile.am	2004-01-27 11:09:02.000000000 -0800
@@ -0,0 +1,2 @@
+EXTRA_DIST = \
+	vg_syscalls.c
diff -puN -L coregrind/vg_unistd.h coregrind/vg_unistd.h~archdep /dev/null
--- valgrind/coregrind/vg_unistd.h
+++ /dev/null	2003-01-30 02:24:37.000000000 -0800
@@ -1,311 +0,0 @@
-
-/*
-   This file is part of Valgrind, an extensible x86 protected-mode
-   emulator for monitoring program execution on x86-Unixes.
-
-   Copyright (C) 2000-2004 Julian Seward 
-      jseward@acm.org
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307, USA.
-
-   The GNU General Public License is contained in the file COPYING.
-*/
-
-#ifndef _VG_ASM_I386_UNISTD_H_
-#define _VG_ASM_I386_UNISTD_H_
-/* Taken from Linux 2.6.0-test1 include/asm-i386/unistd.h */
-
-/*
- * This file contains the system call numbers.
- */
-
-#define __NR_restart_syscall      0
-#define __NR_exit		  1
-#define __NR_fork		  2
-#define __NR_read		  3
-#define __NR_write		  4
-#define __NR_open		  5
-#define __NR_close		  6
-#define __NR_waitpid		  7
-#define __NR_creat		  8
-#define __NR_link		  9
-#define __NR_unlink		 10
-#define __NR_execve		 11
-#define __NR_chdir		 12
-#define __NR_time		 13
-#define __NR_mknod		 14
-#define __NR_chmod		 15
-#define __NR_lchown		 16
-#define __NR_break		 17
-#define __NR_oldstat		 18
-#define __NR_lseek		 19
-#define __NR_getpid		 20
-#define __NR_mount		 21
-#define __NR_umount		 22
-#define __NR_setuid		 23
-#define __NR_getuid		 24
-#define __NR_stime		 25
-#define __NR_ptrace		 26
-#define __NR_alarm		 27
-#define __NR_oldfstat		 28
-#define __NR_pause		 29
-#define __NR_utime		 30
-#define __NR_stty		 31
-#define __NR_gtty		 32
-#define __NR_access		 33
-#define __NR_nice		 34
-#define __NR_ftime		 35
-#define __NR_sync		 36
-#define __NR_kill		 37
-#define __NR_rename		 38
-#define __NR_mkdir		 39
-#define __NR_rmdir		 40
-#define __NR_dup		 41
-#define __NR_pipe		 42
-#define __NR_times		 43
-#define __NR_prof		 44
-#define __NR_brk		 45
-#define __NR_setgid		 46
-#define __NR_getgid		 47
-#define __NR_signal		 48
-#define __NR_geteuid		 49
-#define __NR_getegid		 50
-#define __NR_acct		 51
-#define __NR_umount2		 52
-#define __NR_lock		 53
-#define __NR_ioctl		 54
-#define __NR_fcntl		 55
-#define __NR_mpx		 56
-#define __NR_setpgid		 57
-#define __NR_ulimit		 58
-#define __NR_oldolduname	 59
-#define __NR_umask		 60
-#define __NR_chroot		 61
-#define __NR_ustat		 62
-#define __NR_dup2		 63
-#define __NR_getppid		 64
-#define __NR_getpgrp		 65
-#define __NR_setsid		 66
-#define __NR_sigaction		 67
-#define __NR_sgetmask		 68
-#define __NR_ssetmask		 69
-#define __NR_setreuid		 70
-#define __NR_setregid		 71
-#define __NR_sigsuspend		 72
-#define __NR_sigpending		 73
-#define __NR_sethostname	 74
-#define __NR_setrlimit		 75
-#define __NR_getrlimit		 76	/* Back compatible 2Gig limited rlimit */
-#define __NR_getrusage		 77
-#define __NR_gettimeofday	 78
-#define __NR_settimeofday	 79
-#define __NR_getgroups		 80
-#define __NR_setgroups		 81
-#define __NR_select		 82
-#define __NR_symlink		 83
-#define __NR_oldlstat		 84
-#define __NR_readlink		 85
-#define __NR_uselib		 86
-#define __NR_swapon		 87
-#define __NR_reboot		 88
-#define __NR_readdir		 89
-#define __NR_mmap		 90
-#define __NR_munmap		 91
-#define __NR_truncate		 92
-#define __NR_ftruncate		 93
-#define __NR_fchmod		 94
-#define __NR_fchown		 95
-#define __NR_getpriority	 96
-#define __NR_setpriority	 97
-#define __NR_profil		 98
-#define __NR_statfs		 99
-#define __NR_fstatfs		100
-#define __NR_ioperm		101
-#define __NR_socketcall		102
-#define __NR_syslog		103
-#define __NR_setitimer		104
-#define __NR_getitimer		105
-#define __NR_stat		106
-#define __NR_lstat		107
-#define __NR_fstat		108
-#define __NR_olduname		109
-#define __NR_iopl		110
-#define __NR_vhangup		111
-#define __NR_idle		112
-#define __NR_vm86old		113
-#define __NR_wait4		114
-#define __NR_swapoff		115
-#define __NR_sysinfo		116
-#define __NR_ipc		117
-#define __NR_fsync		118
-#define __NR_sigreturn		119
-#define __NR_clone		120
-#define __NR_setdomainname	121
-#define __NR_uname		122
-#define __NR_modify_ldt		123
-#define __NR_adjtimex		124
-#define __NR_mprotect		125
-#define __NR_sigprocmask	126
-#define __NR_create_module	127
-#define __NR_init_module	128
-#define __NR_delete_module	129
-#define __NR_get_kernel_syms	130
-#define __NR_quotactl		131
-#define __NR_getpgid		132
-#define __NR_fchdir		133
-#define __NR_bdflush		134
-#define __NR_sysfs		135
-#define __NR_personality	136
-#define __NR_afs_syscall	137 /* Syscall for Andrew File System */
-#define __NR_setfsuid		138
-#define __NR_setfsgid		139
-#define __NR__llseek		140
-#define __NR_getdents		141
-#define __NR__newselect		142
-#define __NR_flock		143
-#define __NR_msync		144
-#define __NR_readv		145
-#define __NR_writev		146
-#define __NR_getsid		147
-#define __NR_fdatasync		148
-#define __NR__sysctl		149
-#define __NR_mlock		150
-#define __NR_munlock		151
-#define __NR_mlockall		152
-#define __NR_munlockall		153
-#define __NR_sched_setparam		154
-#define __NR_sched_getparam		155
-#define __NR_sched_setscheduler		156
-#define __NR_sched_getscheduler		157
-#define __NR_sched_yield		158
-#define __NR_sched_get_priority_max	159
-#define __NR_sched_get_priority_min	160
-#define __NR_sched_rr_get_interval	161
-#define __NR_nanosleep		162
-#define __NR_mremap		163
-#define __NR_setresuid		164
-#define __NR_getresuid		165
-#define __NR_vm86		166
-#define __NR_query_module	167
-#define __NR_poll		168
-#define __NR_nfsservctl		169
-#define __NR_setresgid		170
-#define __NR_getresgid		171
-#define __NR_prctl              172
-#define __NR_rt_sigreturn	173
-#define __NR_rt_sigaction	174
-#define __NR_rt_sigprocmask	175
-#define __NR_rt_sigpending	176
-#define __NR_rt_sigtimedwait	177
-#define __NR_rt_sigqueueinfo	178
-#define __NR_rt_sigsuspend	179
-#define __NR_pread64		180
-#define __NR_pwrite64		181
-#define __NR_chown		182
-#define __NR_getcwd		183
-#define __NR_capget		184
-#define __NR_capset		185
-#define __NR_sigaltstack	186
-#define __NR_sendfile		187
-#define __NR_getpmsg		188	/* some people actually want streams */
-#define __NR_putpmsg		189	/* some people actually want streams */
-#define __NR_vfork		190
-#define __NR_ugetrlimit		191	/* SuS compliant getrlimit */
-#define __NR_mmap2		192
-#define __NR_truncate64		193
-#define __NR_ftruncate64	194
-#define __NR_stat64		195
-#define __NR_lstat64		196
-#define __NR_fstat64		197
-#define __NR_lchown32		198
-#define __NR_getuid32		199
-#define __NR_getgid32		200
-#define __NR_geteuid32		201
-#define __NR_getegid32		202
-#define __NR_setreuid32		203
-#define __NR_setregid32		204
-#define __NR_getgroups32	205
-#define __NR_setgroups32	206
-#define __NR_fchown32		207
-#define __NR_setresuid32	208
-#define __NR_getresuid32	209
-#define __NR_setresgid32	210
-#define __NR_getresgid32	211
-#define __NR_chown32		212
-#define __NR_setuid32		213
-#define __NR_setgid32		214
-#define __NR_setfsuid32		215
-#define __NR_setfsgid32		216
-#define __NR_pivot_root		217
-#define __NR_mincore		218
-#define __NR_madvise		219
-#define __NR_madvise1		219	/* delete when C lib stub is removed */
-#define __NR_getdents64		220
-#define __NR_fcntl64		221
-/* 223 is unused */
-#define __NR_gettid		224
-#define __NR_readahead		225
-#define __NR_setxattr		226
-#define __NR_lsetxattr		227
-#define __NR_fsetxattr		228
-#define __NR_getxattr		229
-#define __NR_lgetxattr		230
-#define __NR_fgetxattr		231
-#define __NR_listxattr		232
-#define __NR_llistxattr		233
-#define __NR_flistxattr		234
-#define __NR_removexattr	235
-#define __NR_lremovexattr	236
-#define __NR_fremovexattr	237
-#define __NR_tkill		238
-#define __NR_sendfile64		239
-#define __NR_futex		240
-#define __NR_sched_setaffinity	241
-#define __NR_sched_getaffinity	242
-#define __NR_set_thread_area	243
-#define __NR_get_thread_area	244
-#define __NR_io_setup		245
-#define __NR_io_destroy		246
-#define __NR_io_getevents	247
-#define __NR_io_submit		248
-#define __NR_io_cancel		249
-#define __NR_fadvise64		250
-
-#define __NR_exit_group		252
-#define __NR_lookup_dcookie	253
-#define __NR_epoll_create	254
-#define __NR_epoll_ctl		255
-#define __NR_epoll_wait		256
-#define __NR_remap_file_pages	257
-#define __NR_set_tid_address	258
-#define __NR_timer_create	259
-#define __NR_timer_settime	(__NR_timer_create+1)
-#define __NR_timer_gettime	(__NR_timer_create+2)
-#define __NR_timer_getoverrun	(__NR_timer_create+3)
-#define __NR_timer_delete	(__NR_timer_create+4)
-#define __NR_clock_settime	(__NR_timer_create+5)
-#define __NR_clock_gettime	(__NR_timer_create+6)
-#define __NR_clock_getres	(__NR_timer_create+7)
-#define __NR_clock_nanosleep	(__NR_timer_create+8)
-#define __NR_statfs64		268
-#define __NR_fstatfs64		269
-#define __NR_tgkill		270
-#define __NR_utimes		271
-#define __NR_mknod64		272
-
-#define NR_syscalls 273
-
-#endif /* _VG_ASM_I386_UNISTD_H_ */
diff -puN coregrind/demangle/Makefile.am~archdep coregrind/demangle/Makefile.am
--- valgrind/coregrind/demangle/Makefile.am~archdep	2004-01-27 11:09:02.000000000 -0800
+++ valgrind-jeremy/coregrind/demangle/Makefile.am	2004-01-27 11:09:02.000000000 -0800
@@ -1,6 +1,10 @@
 
-AM_CPPFLAGS = -I$(top_srcdir)/coregrind -I$(top_srcdir)/include
-AM_CFLAGS = $(WERROR) -Winline -Wall -Wshadow -O -fomit-frame-pointer -g
+AM_CPPFLAGS = -I$(top_srcdir)/coregrind -I$(top_srcdir)/include \
+	$(addprefix -I$(top_srcdir)/coregrind/arch/,$(VG_PLAT_DIRS))
+
+AM_CFLAGS = $(WERROR) -Winline -Wall -Wshadow -O -fomit-frame-pointer -g \
+	$(addprefix -I$(top_srcdir)/coregrind/arch/,$(VG_PLAT_DIRS))
+
 
 noinst_HEADERS = \
 	ansidecl.h     \
diff -puN /dev/null coregrind/arch/i386-linux/ume_archdefs.h
--- /dev/null	2003-01-30 02:24:37.000000000 -0800
+++ valgrind-jeremy/coregrind/arch/i386-linux/ume_archdefs.h	2004-01-27 11:09:02.000000000 -0800
@@ -0,0 +1,32 @@
+
+/*
+   This file is part of Valgrind, an extensible x86 protected-mode
+   emulator for monitoring program execution on x86-Unixes.
+
+   Copyright (C) 2000-2004 Julian Seward 
+      jseward@acm.org
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef UME_ARCHDEFS_H
+#define UME_ARCHDEFS_H
+
+#define CLIENT_BASE	0x00000000ul			/* base address of client address space */
+
+#endif /* UME_ARCHDEFS_H */
diff -puN -L coregrind/x86/ume_archdefs.h coregrind/x86/ume_archdefs.h~archdep /dev/null
--- valgrind/coregrind/x86/ume_archdefs.h
+++ /dev/null	2003-01-30 02:24:37.000000000 -0800
@@ -1,32 +0,0 @@
-
-/*
-   This file is part of Valgrind, an extensible x86 protected-mode
-   emulator for monitoring program execution on x86-Unixes.
-
-   Copyright (C) 2000-2004 Julian Seward 
-      jseward@acm.org
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307, USA.
-
-   The GNU General Public License is contained in the file COPYING.
-*/
-
-#ifndef UME_ARCHDEFS_H
-#define UME_ARCHDEFS_H
-
-#define CLIENT_BASE	0x00000000ul			/* base address of client address space */
-
-#endif /* UME_ARCHDEFS_H */
diff -puN /dev/null coregrind/arch/common-linux/vg_unsafe.h
--- /dev/null	2003-01-30 02:24:37.000000000 -0800
+++ valgrind-jeremy/coregrind/arch/common-linux/vg_unsafe.h	2004-01-27 11:09:02.000000000 -0800
@@ -0,0 +1,99 @@
+
+/*--------------------------------------------------------------------*/
+/*--- A header file for making sense of syscalls.  Unsafe in the   ---*/
+/*--- sense that we don't call any functions mentioned herein.     ---*/
+/*---                                                  vg_unsafe.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+   This file is part of Valgrind, an extensible x86 protected-mode
+   emulator for monitoring program execution on x86-Unixes.
+
+   Copyright (C) 2000-2004 Julian Seward 
+      jseward@acm.org
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+
+/* These includes are only used for making sense of the args for
+   system calls. */
+#include "vg_unistd.h"    /* for system call numbers */
+#include <sys/mman.h>     /* for PROT_* */
+#include <sys/utsname.h>  /* for uname */
+#include <sys/time.h>     /* for struct timeval & struct timezone */
+#if defined(KERNEL_2_6) || defined(KERNEL_2_4)
+/* ugly hack to avoid that kernel headers redefine stuff from sys/time.h */
+#define _LINUX_TIME_H
+#endif
+#include <linux/net.h>    /* for the SYS_* constants */
+#include <sys/resource.h> /* for struct rlimit */
+#include <linux/shm.h>    /* for struct shmid_ds & struct ipc_perm */
+#include <sys/socket.h>   /* for struct msghdr */
+#include <linux/sockios.h>/* for SIOCOUTQ */
+#include <sys/un.h>       /* for sockaddr_un */
+#include <net/if.h>       /* for struct ifreq et al */
+#include <net/if_arp.h>   /* for struct arpreq */
+#include <net/route.h>    /* for struct rtentry */
+#ifdef KERNEL_2_6
+#include <linux/compiler.h> /* for __user definition */
+#endif
+#include <asm/ipc.h>      /* for struct ipc_kludge */
+#include <linux/msg.h>    /* for struct msgbuf */
+#include <linux/sem.h>    /* for struct sembuf */
+
+#include <scsi/sg.h>      /* for the SG_* ioctls */
+#include <sched.h>        /* for struct sched_param */
+#include <linux/sysctl.h> /* for struct __sysctl_args */
+#include <linux/cdrom.h>  /* for cd-rom ioctls */
+#include <sys/user.h>     /* for struct user_regs_struct et al */
+#include <signal.h>       /* for siginfo_t */
+#include <linux/timex.h>  /* for adjtimex */
+
+#define __USE_LARGEFILE64
+//#include <sys/stat.h>     /* for struct stat */
+#undef __USE_LARGEFILE64
+
+#include <asm/ioctls.h>   /* for stuff for dealing with ioctl :( */
+#include <sys/soundcard.h> /* for various soundcard ioctl constants :( */
+
+#ifndef GLIBC_2_1
+#  include <linux/rtc.h>   /* for RTC_* ioctls */
+#endif
+
+#include <termios.h>
+#include <pty.h>
+
+/* 2.2 stuff ... */
+#include <sys/uio.h>
+
+/* Both */
+#include <utime.h>
+#include <sys/times.h>    /* for struct tms */
+
+/* 2.0 at least, for gid_t and loff_t */
+#include <sys/types.h>
+
+#include <sys/sysinfo.h>
+
+#include <sys/poll.h>
+
+
+/*--------------------------------------------------------------------*/
+/*--- end                                              vg_unsafe.h ---*/
+/*--------------------------------------------------------------------*/
diff -puN -L coregrind/vg_unsafe.h coregrind/vg_unsafe.h~archdep /dev/null
--- valgrind/coregrind/vg_unsafe.h
+++ /dev/null	2003-01-30 02:24:37.000000000 -0800
@@ -1,99 +0,0 @@
-
-/*--------------------------------------------------------------------*/
-/*--- A header file for making sense of syscalls.  Unsafe in the   ---*/
-/*--- sense that we don't call any functions mentioned herein.     ---*/
-/*---                                                  vg_unsafe.h ---*/
-/*--------------------------------------------------------------------*/
-
-/*
-   This file is part of Valgrind, an extensible x86 protected-mode
-   emulator for monitoring program execution on x86-Unixes.
-
-   Copyright (C) 2000-2004 Julian Seward 
-      jseward@acm.org
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307, USA.
-
-   The GNU General Public License is contained in the file COPYING.
-*/
-
-
-/* These includes are only used for making sense of the args for
-   system calls. */
-#include "vg_unistd.h"    /* for system call numbers */
-#include <sys/mman.h>     /* for PROT_* */
-#include <sys/utsname.h>  /* for uname */
-#include <sys/time.h>     /* for struct timeval & struct timezone */
-#if defined(KERNEL_2_6) || defined(KERNEL_2_4)
-/* ugly hack to avoid that kernel headers redefine stuff from sys/time.h */
-#define _LINUX_TIME_H
-#endif
-#include <linux/net.h>    /* for the SYS_* constants */
-#include <sys/resource.h> /* for struct rlimit */
-#include <linux/shm.h>    /* for struct shmid_ds & struct ipc_perm */
-#include <sys/socket.h>   /* for struct msghdr */
-#include <linux/sockios.h>/* for SIOCOUTQ */
-#include <sys/un.h>       /* for sockaddr_un */
-#include <net/if.h>       /* for struct ifreq et al */
-#include <net/if_arp.h>   /* for struct arpreq */
-#include <net/route.h>    /* for struct rtentry */
-#ifdef KERNEL_2_6
-#include <linux/compiler.h> /* for __user definition */
-#endif
-#include <asm/ipc.h>      /* for struct ipc_kludge */
-#include <linux/msg.h>    /* for struct msgbuf */
-#include <linux/sem.h>    /* for struct sembuf */
-
-#include <scsi/sg.h>      /* for the SG_* ioctls */
-#include <sched.h>        /* for struct sched_param */
-#include <linux/sysctl.h> /* for struct __sysctl_args */
-#include <linux/cdrom.h>  /* for cd-rom ioctls */
-#include <sys/user.h>     /* for struct user_regs_struct et al */
-#include <signal.h>       /* for siginfo_t */
-#include <linux/timex.h>  /* for adjtimex */
-
-#define __USE_LARGEFILE64
-#include <sys/stat.h>     /* for struct stat */
-#undef __USE_LARGEFILE64
-
-#include <asm/ioctls.h>   /* for stuff for dealing with ioctl :( */
-#include <sys/soundcard.h> /* for various soundcard ioctl constants :( */
-
-#ifndef GLIBC_2_1
-#  include <linux/rtc.h>   /* for RTC_* ioctls */
-#endif
-
-#include <termios.h>
-#include <pty.h>
-
-/* 2.2 stuff ... */
-#include <sys/uio.h>
-
-/* Both */
-#include <utime.h>
-#include <sys/times.h>    /* for struct tms */
-
-/* 2.0 at least, for gid_t and loff_t */
-#include <sys/types.h>
-
-#include <sys/sysinfo.h>
-
-#include <sys/poll.h>
-
-
-/*--------------------------------------------------------------------*/
-/*--- end                                              vg_unsafe.h ---*/
-/*--------------------------------------------------------------------*/
diff -puN /dev/null coregrind/arch/common-freebsd/vg_unsafe.h
--- /dev/null	2003-01-30 02:24:37.000000000 -0800
+++ valgrind-jeremy/coregrind/arch/common-freebsd/vg_unsafe.h	2004-01-27 11:09:02.000000000 -0800
@@ -0,0 +1,39 @@
+#ifndef _COMMON_FREEBSD_UNSAFE_H
+#define _COMMON_FREEBSD_UNSAFE_H
+
+#include <sys/param.h>
+#include <sys/mman.h>
+#include <sys/msg.h>
+#define _KERNEL
+#include <sys/shm.h>
+#undef _KERNEL
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <sys/un.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/mount.h>
+#include <sys/resource.h>
+#include <sys/termios.h>
+#include <sys/ttycom.h>
+#include <sys/filio.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/soundcard.h>
+#include <sys/poll.h>
+#include <sys/utsname.h>
+#include <sys/times.h>
+#include <sys/timex.h>
+#include <sys/event.h>
+#include <posix4/sched.h>
+#include <net/if.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <machine/reg.h>
+#include <string.h>		/* strlen */
+
+#define	CMSG_ALIGN(n)	_ALIGN(n)
+#define user_regs_struct	reg
+#define user_fpregs_struct	fpreg
+
+#endif /* _COMMON_FREEBSD_UNSAFE_H */
diff -puN -L coregrind/vg_syscall.S coregrind/vg_syscall.S~archdep /dev/null
--- valgrind/coregrind/vg_syscall.S
+++ /dev/null	2003-01-30 02:24:37.000000000 -0800
@@ -1,118 +0,0 @@
-
-##--------------------------------------------------------------------##
-##--- Support for doing system calls.                              ---##
-##---                                                 vg_syscall.S ---##
-##--------------------------------------------------------------------##
-
-/*
-  This file is part of Valgrind, an extensible x86 protected-mode
-  emulator for monitoring program execution on x86-Unixes.
-
-  Copyright (C) 2000-2004 Julian Seward 
-     jseward@acm.org
-
-  This program is free software; you can redistribute it and/or
-  modify it under the terms of the GNU General Public License as
-  published by the Free Software Foundation; either version 2 of the
-  License, or (at your option) any later version.
-
-  This program is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with this program; if not, write to the Free Software
-  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-  02111-1307, USA.
-
-  The GNU General Public License is contained in the file COPYING.
-*/
-
-#include "vg_constants.h"
-#include "vg_unistd.h"
-
-.globl	VG_(do_syscall)
-
-/*
-	Perform a Linux syscall with int 0x80
-	
-	Syscall args are passed on the stack
-	Int VG_(do_syscall)(Int syscall_no, ...)
-
-	This has no effect on the virtual machine; the expectation is
-	that the syscall mechanism makes no useful changes to any
-	register except %eax, which is returned.
- */
-VG_(do_syscall):
-	push	%esi
-	push	%edi
-	push	%ebx
-	push	%ebp
-	movl	16+ 4(%esp),%eax
-	movl	16+ 8(%esp),%ebx
-	movl	16+12(%esp),%ecx
-	movl	16+16(%esp),%edx
-	movl	16+20(%esp),%esi
-	movl	16+24(%esp),%edi
-	movl	16+28(%esp),%ebp
-	int	$0x80
-	popl	%ebp
-	popl	%ebx
-	popl	%edi
-	popl	%esi
-	ret
-
-/*
-	Perform a clone system call.  clone is strange because it has
-	fork()-like return-twice semantics, so it needs special
-	handling here.
-
-	int VG_(clone)(int (*fn)(void *), void *child_stack, int flags, void *arg, 
-	               0                  4                  8          12
-		       pid_t *child_tid, pid_t *parent_tid)
-		       16                20
-
- */
-.globl VG_(clone)
-VG_(clone):
-#define FSZ	(4+4+4)			/* frame size = retaddr+ebx+edi */
-	push	%ebx
-	push	%edi
-	/* set up child stack with function and arg */
-	movl	 4+FSZ(%esp), %ecx	/* child stack */
-	movl	12+FSZ(%esp), %ebx	/* fn arg */
-	movl	 0+FSZ(%esp), %eax	/* fn */
-	lea	-8(%ecx), %ecx		/* make space on stack */
-	movl	%ebx, 4(%ecx)		/*   fn arg */
-	movl	%eax, 0(%ecx)		/*   fn */
-
-	/* get other args to clone */
-	movl	 8+FSZ(%esp), %ebx	/* flags */
-	movl	20+FSZ(%esp), %edx	/* parent tid * */
-	movl	16+FSZ(%esp), %edi	/* child tid * */
-	movl	$__NR_clone, %eax
-	int	$0x80
-	testl	%eax, %eax
-	jnz	1f
-
-	/* CHILD - call thread function */
-	popl	%eax
-	call	*%eax
-
-	/* exit with result */
-	movl	%eax, %ebx
-	movl	$__NR_exit, %eax
-	int	$0x80
-
-	/* Hm, exit returned */
-	ud2
-		
-1:	/* PARENT or ERROR */
-	pop	%edi
-	pop	%ebx
-	ret
-	
-##--------------------------------------------------------------------##
-##--- end                                             vg_syscall.S ---##
-##--------------------------------------------------------------------##
diff -puN /dev/null coregrind/arch/i386-linux/vg_syscall.S
--- /dev/null	2003-01-30 02:24:37.000000000 -0800
+++ valgrind-jeremy/coregrind/arch/i386-linux/vg_syscall.S	2004-01-27 11:09:02.000000000 -0800
@@ -0,0 +1,118 @@
+
+##--------------------------------------------------------------------##
+##--- Support for doing system calls.                              ---##
+##---                                                 vg_syscall.S ---##
+##--------------------------------------------------------------------##
+
+/*
+  This file is part of Valgrind, an extensible x86 protected-mode
+  emulator for monitoring program execution on x86-Unixes.
+
+  Copyright (C) 2000-2004 Julian Seward 
+     jseward@acm.org
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "vg_constants.h"
+#include "vg_unistd.h"
+
+.globl	VG_(do_syscall)
+
+/*
+	Perform a Linux syscall with int 0x80
+	
+	Syscall args are passed on the stack
+	Int VG_(do_syscall)(Int syscall_no, ...)
+
+	This has no effect on the virtual machine; the expectation is
+	that the syscall mechanism makes no useful changes to any
+	register except %eax, which is returned.
+ */
+VG_(do_syscall):
+	push	%esi
+	push	%edi
+	push	%ebx
+	push	%ebp
+	movl	16+ 4(%esp),%eax
+	movl	16+ 8(%esp),%ebx
+	movl	16+12(%esp),%ecx
+	movl	16+16(%esp),%edx
+	movl	16+20(%esp),%esi
+	movl	16+24(%esp),%edi
+	movl	16+28(%esp),%ebp
+	int	$0x80
+	popl	%ebp
+	popl	%ebx
+	popl	%edi
+	popl	%esi
+	ret
+
+/*
+	Perform a clone system call.  clone is strange because it has
+	fork()-like return-twice semantics, so it needs special
+	handling here.
+
+	int VG_(clone)(int (*fn)(void *), void *child_stack, int flags, void *arg, 
+	               0                  4                  8          12
+		       pid_t *child_tid, pid_t *parent_tid)
+		       16                20
+
+ */
+.globl VG_(clone)
+VG_(clone):
+#define FSZ	(4+4+4)			/* frame size = retaddr+ebx+edi */
+	push	%ebx
+	push	%edi
+	/* set up child stack with function and arg */
+	movl	 4+FSZ(%esp), %ecx	/* child stack */
+	movl	12+FSZ(%esp), %ebx	/* fn arg */
+	movl	 0+FSZ(%esp), %eax	/* fn */
+	lea	-8(%ecx), %ecx		/* make space on stack */
+	movl	%ebx, 4(%ecx)		/*   fn arg */
+	movl	%eax, 0(%ecx)		/*   fn */
+
+	/* get other args to clone */
+	movl	 8+FSZ(%esp), %ebx	/* flags */
+	movl	20+FSZ(%esp), %edx	/* parent tid * */
+	movl	16+FSZ(%esp), %edi	/* child tid * */
+	movl	$__NR_clone, %eax
+	int	$0x80
+	testl	%eax, %eax
+	jnz	1f
+
+	/* CHILD - call thread function */
+	popl	%eax
+	call	*%eax
+
+	/* exit with result */
+	movl	%eax, %ebx
+	movl	$__NR_exit, %eax
+	int	$0x80
+
+	/* Hm, exit returned */
+	ud2
+		
+1:	/* PARENT or ERROR */
+	pop	%edi
+	pop	%ebx
+	ret
+	
+##--------------------------------------------------------------------##
+##--- end                                             vg_syscall.S ---##
+##--------------------------------------------------------------------##
diff -puN -L coregrind/x86/ume_archdefs.c coregrind/x86/ume_archdefs.c~archdep /dev/null
--- valgrind/coregrind/x86/ume_archdefs.c
+++ /dev/null	2003-01-30 02:24:37.000000000 -0800
@@ -1,29 +0,0 @@
-
-/*
-   This file is part of Valgrind, an extensible x86 protected-mode
-   emulator for monitoring program execution on x86-Unixes.
-
-   Copyright (C) 2000-2004 Julian Seward 
-      jseward@acm.org
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307, USA.
-
-   The GNU General Public License is contained in the file COPYING.
-*/
-
-#include "ume_archdefs.h"
-
-const unsigned long CLIENT_START = 0;
diff -puN -L coregrind/x86/ume_entry.S coregrind/x86/ume_entry.S~archdep /dev/null
--- valgrind/coregrind/x86/ume_entry.S
+++ /dev/null	2003-01-30 02:24:37.000000000 -0800
@@ -1,38 +0,0 @@
-
-/*
-   This file is part of Valgrind, an extensible x86 protected-mode
-   emulator for monitoring program execution on x86-Unixes.
-
-   Copyright (C) 2000-2004 Julian Seward 
-      jseward@acm.org
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307, USA.
-
-   The GNU General Public License is contained in the file COPYING.
-*/
-
-	.text
-	.globl _ume_entry
-
-	/* Record the very initial value of %esp before starting the
-	   rest of the executable */
-_ume_entry:
-	movl	%esp, ume_exec_esp
-	jmp	_start
-
-	.data
-	.globl ume_exec_esp
-ume_exec_esp:	.long 0
diff -puN -L coregrind/x86/ume_go.c coregrind/x86/ume_go.c~archdep /dev/null
--- valgrind/coregrind/x86/ume_go.c
+++ /dev/null	2003-01-30 02:24:37.000000000 -0800
@@ -1,51 +0,0 @@
-
-/*
-   This file is part of Valgrind, an extensible x86 protected-mode
-   emulator for monitoring program execution on x86-Unixes.
-
-   Copyright (C) 2000-2004 Julian Seward 
-      jseward@acm.org
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307, USA.
-
-   The GNU General Public License is contained in the file COPYING.
-*/
-
-#include "ume_arch.h"
-
-/* 
-   Jump to a particular EIP with a particular ESP.  This is intended
-   to simulate the initial CPU state when the kernel starts an program
-   after exec; it therefore also clears all the other registers.
- */
-void ume_go(addr_t eip, addr_t esp)
-{
-   asm volatile ("movl %1, %%esp;"	/* set esp */
-		 "pushl %%eax;"		/* push esp */
-		 "xorl	%%eax,%%eax;"	/* clear registers */
-		 "xorl	%%ebx,%%ebx;"
-		 "xorl	%%ecx,%%ecx;"
-		 "xorl	%%edx,%%edx;"
-		 "xorl	%%esi,%%esi;"
-		 "xorl	%%edi,%%edi;"
-		 "xorl	%%ebp,%%ebp;"
-
-		 "ret"			/* return into entry */
-		 : : "a" (eip), "r" (esp));
-   /* we should never get here */
-   for(;;)
-	   asm volatile("ud2");
-} 
diff -puN /dev/null coregrind/arch/i386-linux/ume_go.c
--- /dev/null	2003-01-30 02:24:37.000000000 -0800
+++ valgrind-jeremy/coregrind/arch/i386-linux/ume_go.c	2004-01-27 11:09:02.000000000 -0800
@@ -0,0 +1,51 @@
+
+/*
+   This file is part of Valgrind, an extensible x86 protected-mode
+   emulator for monitoring program execution on x86-Unixes.
+
+   Copyright (C) 2000-2004 Julian Seward 
+      jseward@acm.org
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "ume_arch.h"
+
+/* 
+   Jump to a particular EIP with a particular ESP.  This is intended
+   to simulate the initial CPU state when the kernel starts an program
+   after exec; it therefore also clears all the other registers.
+ */
+void ume_go(addr_t eip, addr_t esp)
+{
+   asm volatile ("movl %1, %%esp;"	/* set esp */
+		 "pushl %%eax;"		/* push esp */
+		 "xorl	%%eax,%%eax;"	/* clear registers */
+		 "xorl	%%ebx,%%ebx;"
+		 "xorl	%%ecx,%%ecx;"
+		 "xorl	%%edx,%%edx;"
+		 "xorl	%%esi,%%esi;"
+		 "xorl	%%edi,%%edi;"
+		 "xorl	%%ebp,%%ebp;"
+
+		 "ret"			/* return into entry */
+		 : : "a" (eip), "r" (esp));
+   /* we should never get here */
+   for(;;)
+	   asm volatile("ud2");
+} 
diff -puN /dev/null coregrind/arch/i386-linux/ume_entry.S
--- /dev/null	2003-01-30 02:24:37.000000000 -0800
+++ valgrind-jeremy/coregrind/arch/i386-linux/ume_entry.S	2004-01-27 11:09:02.000000000 -0800
@@ -0,0 +1,38 @@
+
+/*
+   This file is part of Valgrind, an extensible x86 protected-mode
+   emulator for monitoring program execution on x86-Unixes.
+
+   Copyright (C) 2000-2004 Julian Seward 
+      jseward@acm.org
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+	.text
+	.globl _ume_entry
+
+	/* Record the very initial value of %esp before starting the
+	   rest of the executable */
+_ume_entry:
+	movl	%esp, ume_exec_esp
+	jmp	_start
+
+	.data
+	.globl ume_exec_esp
+ume_exec_esp:	.long 0
diff -puN /dev/null coregrind/arch/i386-linux/ume_archdefs.c
--- /dev/null	2003-01-30 02:24:37.000000000 -0800
+++ valgrind-jeremy/coregrind/arch/i386-linux/ume_archdefs.c	2004-01-27 11:09:02.000000000 -0800
@@ -0,0 +1,29 @@
+
+/*
+   This file is part of Valgrind, an extensible x86 protected-mode
+   emulator for monitoring program execution on x86-Unixes.
+
+   Copyright (C) 2000-2004 Julian Seward 
+      jseward@acm.org
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "ume_archdefs.h"
+
+const unsigned long CLIENT_START = 0;
diff -puN coregrind/ume.h~archdep coregrind/ume.h
--- valgrind/coregrind/ume.h~archdep	2004-01-27 11:09:02.000000000 -0800
+++ valgrind-jeremy/coregrind/ume.h	2004-01-27 11:09:02.000000000 -0800
@@ -30,6 +30,9 @@
 #include <elf.h>
 #include <sys/types.h>
 
+/* XXX FIXME - this needs to be done better */
+#define ELFSZ	32
+
 #if	ELFSZ == 64
 #define ESZ(x)	Elf64_##x
 #elif	ELFSZ == 32
diff -puN -L coregrind/vg_dispatch.S coregrind/vg_dispatch.S~archdep /dev/null
--- valgrind/coregrind/vg_dispatch.S
+++ /dev/null	2003-01-30 02:24:37.000000000 -0800
@@ -1,229 +0,0 @@
-
-##--------------------------------------------------------------------##
-##--- The core dispatch loop, for jumping to a code address.       ---##
-##---                                                vg_dispatch.S ---##
-##--------------------------------------------------------------------##
-
-/*
-  This file is part of Valgrind, an extensible x86 protected-mode
-  emulator for monitoring program execution on x86-Unixes.
-
-  Copyright (C) 2000-2004 Julian Seward 
-     jseward@acm.org
-
-  This program is free software; you can redistribute it and/or
-  modify it under the terms of the GNU General Public License as
-  published by the Free Software Foundation; either version 2 of the
-  License, or (at your option) any later version.
-
-  This program is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with this program; if not, write to the Free Software
-  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-  02111-1307, USA.
-
-  The GNU General Public License is contained in the file COPYING.
-*/
-
-#include "vg_constants.h"
-
-
-/*------------------------------------------------------------*/
-/*--- The normal-case dispatch machinery.                  ---*/
-/*------------------------------------------------------------*/
-	
-/* To transfer to an (original) code address, load it into %eax and
-   jump to vg_dispatch.  This fragment of code tries to find the
-   address of the corresponding translation by searching the translation
-   table.   If it fails, a new translation is made, added to the
-   translation table, and then jumped to.  Almost all the hard
-   work is done by C routines; this code simply handles the
-   common case fast -- when the translation address is found in
-   the translation cache.
-
-   At entry, %eax is the only live (real-machine) register; the
-   entire simulated state is tidily saved in vg_m_state.  
-*/
-
-	
-#define TT_LOOKUP(reg, fail)				\
-	movl %eax, reg;					\
-	andl $VG_TT_FAST_MASK, reg;			\
-	movl VG_(tt_fast)(,reg,4), reg;			\
-	cmpl %eax, (reg);				\
-	jnz  fail
-	
-/* The C world needs a way to get started simulating.  So we provide
-   a function void vg_run_innerloop ( void ), which starts running
-   from vg_m_eip, and exits when the counter reaches zero.  This loop
-   can also exit if vg_oursignalhandler() catches a non-resumable
-   signal, for example SIGSEGV.  It then longjmp()s back past here.
-*/
-
-.globl VG_(run_innerloop)
-VG_(run_innerloop):
-	/* OYNK(1000) */
-
-	/* ----- entry point to VG_(run_innerloop) ----- */
-	pushl	%ebx
-	pushl	%ecx
-	pushl	%edx
-	pushl	%esi
-	pushl	%edi
-	pushl	%ebp
-
-	/* check to see if we're doing pointer checking */
-	movb	VG_(clo_pointercheck), %al
-	testb	%al,%al
-	jz	1f
-	
-	pushl	%fs						/* save %fs     */
-	mov	$(VG_POINTERCHECK_SEGIDX << 3) + 7, %eax	/* load new %fs */
-	movw	%ax,%fs
-
-1:	
-	/* Set up the baseBlock pointer */
-	movl	$VG_(baseBlock), %ebp
-
-	/* fetch m_eip into %eax */
-	movl	VGOFF_(m_eip), %esi
-	movl	(%ebp, %esi, 4), %eax
-	
-dispatch_main:
-	/* Jump here to do a new dispatch.
-	   %eax holds destination (original) address.
-	   %ebp indicates further details of the control transfer
-	   requested to the address in %eax.
-	
-	   If ebp == & VG_(baseBlock), just jump next to %eax.
-	 
-	   If ebp == VG_EBP_JMP_SYSCALL, do a system call before 
-	   continuing at eax.
-	
-	   If ebp == VG_EBP_JMP_CLIENTREQ, do a client request before 
-	   continuing at eax.
-	
-	   If %ebp has any other value, we panic.
-	*/
-	/*cmpl	$VG_(baseBlock), %ebp*/
-	/*jnz	dispatch_exceptional*/
-	/* fall into main loop */
-
-
-dispatch_boring:
-	/* save the jump address at VG_(baseBlock)[VGOFF_(m_eip)] */
-	movl	VGOFF_(m_eip), %esi
-	movl	%eax, (%ebp, %esi, 4)
-
-	/* Are we out of timeslice?  If yes, defer to scheduler. */
-	cmpl	$0, VG_(dispatch_ctr)
-	jz	counter_is_zero
-	/* try a fast lookup in the translation cache */
-	TT_LOOKUP(%ebx, fast_lookup_failed)
-
-	/* Found a match.  Call the tce.payload field (+VG_CODE_OFFSET) */
-	addl	$VG_CODE_OFFSET, %ebx
-	incl	VG_(unchained_jumps_done)	      /* update stats */
-	call	*%ebx
-	
-	cmpl	$VG_(baseBlock), %ebp
-	jz	dispatch_boring
-
-	jmp	dispatch_exceptional
-
-	
-fast_lookup_failed:
-	/* %EIP is up to date here since dispatch_boring dominates */
-	movl	$VG_TRC_INNER_FASTMISS, %eax
-	jmp	run_innerloop_exit
-
-counter_is_zero:
-	/* %EIP is up to date here since dispatch_boring dominates */
-	movl	$VG_TRC_INNER_COUNTERZERO, %eax
-	jmp	run_innerloop_exit
-	
-run_innerloop_exit:
-	movb	VG_(clo_pointercheck), %bl
-	testb	%bl,%bl
-	jz	1f
-
-	/* restore %fs */
-	popl	%fs
-	
-1:	popl	%ebp
-	popl	%edi
-	popl	%esi
-	popl	%edx
-	popl	%ecx
-	popl	%ebx
-	ret	
-
-
-
-/* Other ways of getting out of the inner loop.  Placed out-of-line to
-   make it look cleaner. 
-*/
-dispatch_exceptional:
-	/* this is jumped to only, not fallen-through from above */
-	cmpl	$VG_TRC_INNER_COUNTERZERO, %ebp
-	jz	counter_is_zero
-
-	/* save %eax in %EIP and defer to sched */
-	movl	VGOFF_(m_eip), %esi
-	movl	%eax, VG_(baseBlock)(,%esi, 4)
-	movl	%ebp, %eax
-	jmp	run_innerloop_exit
-
-
-/*
-	This is the translation chainer, our run-time linker, if you like.
-
-	VG_(patch_me) patches the call instruction in the jump site
-	with a jump to the generated code for the branch target.  %eax
-	contains the original program's EIP - if we get a hit in
-	tt_fast, then the call is patched into a jump; otherwise it
-	simply drops back into the dispatch loop for normal
-	processing.
-
-	The callsite is expected to look like:
-		call	VG_(patch_me)
-	it will be transformed into
-		jmp	$TARGETADDR
-
-	The environment we're expecting on entry is:
-		%eax    = branch target address (original code EIP)
-		*(%esp) = just after call
-*/
-.globl VG_(patch_me)
-VG_(patch_me):
-	/* try a fast lookup in the translation cache */
-	TT_LOOKUP(%ebx, 1f)
-
-	/* Patch call instruction at callsite into a chained jmp */
-	popl	%eax	    /* eax = just after (VG_PATCHME_CALLSZ byte) call */
-	addl	$VG_CODE_OFFSET, %ebx	/* ebx = target eip */
-	subl	%eax, %ebx		/* ebx = delta */
-	movb	$0xE9, -(VG_PATCHME_CALLSZ-0)(%eax)		/* 0xe9 = jmp */
-	movl	%ebx,  -(VG_PATCHME_CALLSZ-1)(%eax)	       /* store delta */
-	addl	%eax, %ebx
-	incl	VG_(bb_enchain_count)			      /* update stats */
-	jmp	*%ebx					       /* jmp to dest */
-
-	/* tt_fast miss: return into main dispatch loop */
-1:	addl	$4, %esp	/* remove our call address */
-	ret			/* return into main dispatch loop above */
-	
-.data
-panic_msg_ebp:
-.ascii	"vg_dispatch: %ebp has invalid value!"
-.byte	0
-.text	
-
-
-##--------------------------------------------------------------------##
-##--- end                                            vg_dispatch.S ---##
-##--------------------------------------------------------------------##
diff -puN /dev/null coregrind/arch/i386-common/vg_dispatch.S
--- /dev/null	2003-01-30 02:24:37.000000000 -0800
+++ valgrind-jeremy/coregrind/arch/i386-common/vg_dispatch.S	2004-01-27 11:12:02.000000000 -0800
@@ -0,0 +1,229 @@
+
+##--------------------------------------------------------------------##
+##--- The core dispatch loop, for jumping to a code address.       ---##
+##---                                                vg_dispatch.S ---##
+##--------------------------------------------------------------------##
+
+/*
+  This file is part of Valgrind, an extensible x86 protected-mode
+  emulator for monitoring program execution on x86-Unixes.
+
+  Copyright (C) 2000-2004 Julian Seward 
+     jseward@acm.org
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "vg_constants.h"
+
+
+/*------------------------------------------------------------*/
+/*--- The normal-case dispatch machinery.                  ---*/
+/*------------------------------------------------------------*/
+	
+/* To transfer to an (original) code address, load it into %eax and
+   jump to vg_dispatch.  This fragment of code tries to find the
+   address of the corresponding translation by searching the translation
+   table.   If it fails, a new translation is made, added to the
+   translation table, and then jumped to.  Almost all the hard
+   work is done by C routines; this code simply handles the
+   common case fast -- when the translation address is found in
+   the translation cache.
+
+   At entry, %eax is the only live (real-machine) register; the
+   entire simulated state is tidily saved in vg_m_state.  
+*/
+
+	
+#define TT_LOOKUP(reg, fail)				\
+	movl %eax, reg;					\
+	andl $VG_TT_FAST_MASK, reg;			\
+	movl VG_(tt_fast)(,reg,4), reg;			\
+	cmpl %eax, (reg);				\
+	jnz  fail
+	
+/* The C world needs a way to get started simulating.  So we provide
+   a function void vg_run_innerloop ( void ), which starts running
+   from vg_m_eip, and exits when the counter reaches zero.  This loop
+   can also exit if vg_oursignalhandler() catches a non-resumable
+   signal, for example SIGSEGV.  It then longjmp()s back past here.
+*/
+
+.globl VG_(run_innerloop)
+VG_(run_innerloop):
+	/* OYNK(1000) */
+
+	/* ----- entry point to VG_(run_innerloop) ----- */
+	pushl	%ebx
+	pushl	%ecx
+	pushl	%edx
+	pushl	%esi
+	pushl	%edi
+	pushl	%ebp
+
+	/* check to see if we're doing pointer checking */
+	movb	VG_(clo_pointercheck), %al
+	testb	%al,%al
+	jz	1f
+	
+	pushl	%fs						/* save %fs     */
+	mov	$(VG_POINTERCHECK_SEGIDX << 3) + 7, %eax	/* load new %fs */
+	movw	%ax,%fs
+
+1:	
+	/* Set up the baseBlock pointer */
+	movl	$VG_(baseBlock), %ebp
+
+	/* fetch m_eip into %eax */
+	movl	VGOFF_(m_eip), %esi
+	movl	(%ebp, %esi, 4), %eax
+	
+dispatch_main:
+	/* Jump here to do a new dispatch.
+	   %eax holds destination (original) address.
+	   %ebp indicates further details of the control transfer
+	   requested to the address in %eax.
+	
+	   If ebp == & VG_(baseBlock), just jump next to %eax.
+	 
+	   If ebp == VG_EBP_JMP_SYSCALL, do a system call before 
+	   continuing at eax.
+	
+	   If ebp == VG_EBP_JMP_CLIENTREQ, do a client request before 
+	   continuing at eax.
+	
+	   If %ebp has any other value, we panic.
+	*/
+	/*cmpl	$VG_(baseBlock), %ebp*/
+	/*jnz	dispatch_exceptional*/
+	/* fall into main loop */
+
+
+dispatch_boring:
+	/* save the jump address at VG_(baseBlock)[VGOFF_(m_eip)] */
+	movl	VGOFF_(m_eip), %esi
+	movl	%eax, (%ebp, %esi, 4)
+
+	/* Are we out of timeslice?  If yes, defer to scheduler. */
+	cmpl	$0, VG_(dispatch_ctr)
+	jz	counter_is_zero
+	/* try a fast lookup in the translation cache */
+	TT_LOOKUP(%ebx, fast_lookup_failed)
+
+	/* Found a match.  Call the tce.payload field (+VG_CODE_OFFSET) */
+	addl	$VG_CODE_OFFSET, %ebx
+	incl	VG_(unchained_jumps_done)	      /* update stats */
+	call	*%ebx
+	
+	cmpl	$VG_(baseBlock), %ebp
+	jz	dispatch_boring
+
+	jmp	dispatch_exceptional
+
+	
+fast_lookup_failed:
+	/* %EIP is up to date here since dispatch_boring dominates */
+	movl	$VG_TRC_INNER_FASTMISS, %eax
+	jmp	run_innerloop_exit
+
+counter_is_zero:
+	/* %EIP is up to date here since dispatch_boring dominates */
+	movl	$VG_TRC_INNER_COUNTERZERO, %eax
+	jmp	run_innerloop_exit
+	
+run_innerloop_exit:
+	movb	VG_(clo_pointercheck), %bl
+	testb	%bl,%bl
+	jz	1f
+
+	/* restore %fs */
+	popl	%fs
+	
+1:	popl	%ebp
+	popl	%edi
+	popl	%esi
+	popl	%edx
+	popl	%ecx
+	popl	%ebx
+	ret	
+
+
+
+/* Other ways of getting out of the inner loop.  Placed out-of-line to
+   make it look cleaner. 
+*/
+dispatch_exceptional:
+	/* this is jumped to only, not fallen-through from above */
+	cmpl	$VG_TRC_INNER_COUNTERZERO, %ebp
+	jz	counter_is_zero
+
+	/* save %eax in %EIP and defer to sched */
+	movl	VGOFF_(m_eip), %esi
+	movl	%eax, VG_(baseBlock)(,%esi, 4)
+	movl	%ebp, %eax
+	jmp	run_innerloop_exit
+
+
+/*
+	This is the translation chainer, our run-time linker, if you like.
+
+	VG_(patch_me) patches the call instruction in the jump site
+	with a jump to the generated code for the branch target.  %eax
+	contains the original program's EIP - if we get a hit in
+	tt_fast, then the call is patched into a jump; otherwise it
+	simply drops back into the dispatch loop for normal
+	processing.
+
+	The callsite is expected to look like:
+		call	VG_(patch_me)
+	it will be transformed into
+		jmp	$TARGETADDR
+
+	The environment we're expecting on entry is:
+		%eax    = branch target address (original code EIP)
+		*(%esp) = just after call
+*/
+.globl VG_(patch_me)
+VG_(patch_me):
+	/* try a fast lookup in the translation cache */
+	TT_LOOKUP(%ebx, 1f)
+
+	/* Patch call instruction at callsite into a chained jmp */
+	popl	%eax	    /* eax = just after (VG_PATCHME_CALLSZ byte) call */
+	addl	$VG_CODE_OFFSET, %ebx	/* ebx = target eip */
+	subl	%eax, %ebx		/* ebx = delta */
+	movb	$0xE9, -(VG_PATCHME_CALLSZ-0)(%eax)		/* 0xe9 = jmp */
+	movl	%ebx,  -(VG_PATCHME_CALLSZ-1)(%eax)	       /* store delta */
+	addl	%eax, %ebx
+	incl	VG_(bb_enchain_count)			      /* update stats */
+	jmp	*%ebx					       /* jmp to dest */
+
+	/* tt_fast miss: return into main dispatch loop */
+1:	addl	$4, %esp	/* remove our call address */
+	ret			/* return into main dispatch loop above */
+	
+.data
+panic_msg_ebp:
+.ascii	"vg_dispatch: %ebp has invalid value!"
+.byte	0
+.text	
+
+
+##--------------------------------------------------------------------##
+##--- end                                            vg_dispatch.S ---##
+##--------------------------------------------------------------------##
diff -puN -L coregrind/vg_helpers.S coregrind/vg_helpers.S~archdep /dev/null
--- valgrind/coregrind/vg_helpers.S
+++ /dev/null	2003-01-30 02:24:37.000000000 -0800
@@ -1,656 +0,0 @@
-##--------------------------------------------------------------------##
-##--- Support routines for the JITter output.                      ---##
-##---                                                 vg_helpers.S ---##
-##--------------------------------------------------------------------##
-
-/*
-  This file is part of Valgrind, an extensible x86 protected-mode
-  emulator for monitoring program execution on x86-Unixes.
-
-  Copyright (C) 2000-2004 Julian Seward 
-     jseward@acm.org
-
-  This program is free software; you can redistribute it and/or
-  modify it under the terms of the GNU General Public License as
-  published by the Free Software Foundation; either version 2 of the
-  License, or (at your option) any later version.
-
-  This program is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with this program; if not, write to the Free Software
-  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-  02111-1307, USA.
-
-  The GNU General Public License is contained in the file COPYING.
-*/
-
-#include "vg_constants.h"
-
-/* ------------------ SIMULATED CPU HELPERS ------------------ */
-/* A stubs for a return which we want to catch: a signal return.
-   returns and pthread returns.  In the latter case, the thread's
-   return value is in %EAX, so we pass this as the first argument
-   to the request.  In both cases we use the user request mechanism.
-   You need to to read the definition of VALGRIND_MAGIC_SEQUENCE
-   in valgrind.h to make sense of this.
-
-   This isn't used in-place.  It is copied into the client address space
-   at an arbitary address.  Therefore, this code must be completely
-   position-independent.
-*/
-.global VG_(trampoline_code_start)
-.global VG_(trampoline_code_length)
-.global VG_(tramp_sigreturn_offset)
-.global VG_(tramp_syscall_offset)
-	
-VG_(trampoline_code_start):
-sigreturn_start:	
-	subl	$20, %esp	# allocate arg block
-	movl	%esp, %edx	# %edx == &_zzq_args[0]
-	movl	$VG_USERREQ__SIGNAL_RETURNS, 0(%edx)	# request
-	movl	$0, 4(%edx)	# arg1
-	movl	$0, 8(%edx)	# arg2
-	movl	$0, 12(%edx)	# arg3
-	movl	$0, 16(%edx)	# arg4
-	movl	%edx, %eax
-	# and now the magic sequence itself:
-	roll $29, %eax
-	roll $3, %eax
-	rorl $27, %eax
-	rorl $5, %eax
-	roll $13, %eax
-	roll $19, %eax
-	# should never get here
-	ud2
-
-	# We can point our sysinfo stuff here
-	.align 16
-syscall_start:	
-	int	$0x80
-	ret
-tramp_code_end:
-			
-.data
-VG_(trampoline_code_length):
-	.long tramp_code_end - VG_(trampoline_code_start)
-VG_(tramp_sigreturn_offset):
-	.long sigreturn_start - VG_(trampoline_code_start)
-VG_(tramp_syscall_offset):
-	.long syscall_start - VG_(trampoline_code_start)
-.text
-
-	
-/* ------------------ REAL CPU HELPERS ------------------ */
-/* The rest of this lot run on the real CPU. */
-	
-/* Various helper routines, for instructions which are just too
-   darn tedious for the JITter to output code in-line:
-	
-	* integer division
-	* integer multiplication
-        * setting and getting obscure eflags
-	* double-length shifts
-        * eight byte compare and exchange
-	
-   All routines use a standard calling convention designed for
-   calling from translations, in which the incoming args are
-   underneath the return address, the callee saves _all_ registers,
-   and the incoming parameters can be modified, to return results.
-*/
-
-/* Fetch the time-stamp-ctr reg.
-   On entry:
-	dummy, replaced by %EAX value
-	dummy, replaced by %EDX value
-	RA   <- %esp
-*/
-.global VG_(helper_RDTSC)
-VG_(helper_RDTSC):
-	pushl	%eax
-	pushl	%edx
-	rdtsc
-	movl	%edx, 12(%esp)
-	movl	%eax, 16(%esp)
-	popl	%edx
-	popl	%eax
-	ret
-
-/* 
-   Fetch a byte/word/dword from given port
-   On entry:
-         size     1, 2 or 4
-         port, replaced by result
-         RA
-*/
-.global VG_(helper_IN)
-VG_(helper_IN):
-	pushl	%eax
-	pushl   %edx
-	movl	16(%esp), %eax
-	movl	12(%esp), %edx
-	cmpl	$4, %eax
-	je	in_dword
-	cmpl	$2, %eax
-	je	in_word
-in_byte:
-	inb	(%dx), %al
-	jmp	in_done
-in_word:
-	in	(%dx), %ax
-	jmp	in_done
-in_dword:
-	inl	(%dx),%eax
-in_done:
-	movl	%eax,12(%esp)
-	popl	%edx
-	popl	%eax
-	ret
-
-/* 
-   Write a byte/word/dword to given port
-   On entry:
-         size     1, 2 or 4
-         port
-         value
-         RA
-*/
-.global VG_(helper_OUT)
-VG_(helper_OUT):
-	pushl	%eax
-	pushl   %edx
-	movl	16(%esp), %edx
-	movl	12(%esp), %eax
-	cmpl	$4, 20(%esp)
-	je	out_dword
-	cmpl	$2, 20(%esp)
-	je	out_word
-out_byte:
-	outb	%al,(%dx)
-	jmp	out_done
-out_word:
-	out	%ax,(%dx)
-	jmp	out_done
-out_dword:
-	outl	%eax,(%dx)
-out_done:
-	popl	%edx
-	popl	%eax
-	ret
-
-
-/* Do the CPUID instruction.
-   On entry:
-	dummy, replaced by %EAX value
-	dummy, replaced by %EBX value
-	dummy, replaced by %ECX value
-	dummy, replaced by %EDX value
-	RA   <- %esp
-
-   We save registers and package up the args so we can call a C helper
-   for all this.
-*/
-.global VG_(helper_CPUID)
-VG_(helper_CPUID):
-	pushl	%ebp
-	movl	%esp,%ebp
-	pushl	%eax
-	pushl	%ebx
-	pushl	%ecx
-	pushl	%edx
-	pushl	%esi
-	pushl	%edi
-	pushf
-	
-	lea	2*4(%ebp),%eax	/* &edx */
-	pushl	%eax
-	addl	$4,%eax		/* &ecx */
-	pushl	%eax
-	addl	$4,%eax		/* &ebx */
-	pushl	%eax
-	addl	$4,%eax		/* &eax */
-	pushl	%eax
-	pushl	(%eax)		/* eax */
-
-	call	VG_(helperc_CPUID)
-	addl	$20,%esp
-
-	popf
-	popl	%edi
-	popl	%esi
-	popl	%edx
-	popl	%ecx
-	popl	%ebx
-	popl	%eax
-	popl	%ebp
-	ret
-
-/* Fetch the FPU status register.
-   On entry:
-	dummy, replaced by result
-	RA   <- %esp
-*/
-.global VG_(helper_fstsw_AX)
-VG_(helper_fstsw_AX):
-	pushl	%eax
-	pushl	%esi
-	movl	VGOFF_(m_ssestate), %esi
-
-	pushfl
-	cmpb	$0, VG_(have_ssestate)
-	jz	aa1nosse
-	fxrstor	(%ebp, %esi, 4)
-	jmp	aa1merge
-aa1nosse:
-	frstor	(%ebp, %esi, 4)
-aa1merge:
-	popfl
-
-	fstsw	%ax
-	popl	%esi
-	movw	%ax, 8(%esp)
-	popl	%eax
-	ret
-
-
-/* Copy %ah into %eflags.
-   On entry:
-	value of %eax
-	RA   <- %esp
-*/
-.global VG_(helper_SAHF)
-VG_(helper_SAHF):
-	pushl	%eax
-	movl	8(%esp), %eax
-	sahf
-	popl	%eax
-	ret
-
-/* Copy %eflags into %ah.
-   On entry:
-	value of %eax
-	RA   <- %esp
-*/
-.global VG_(helper_LAHF)
-VG_(helper_LAHF):
-	pushl	%eax
-	movl	8(%esp), %eax
-	lahf
-	movl	%eax, 8(%esp)
-	popl	%eax
-	ret
-
-
-/* Do %al = DAS(%al).  Note that the passed param has %AL as the least
-   significant 8 bits, since it was generated with GETB %AL,
-   some-temp.  Fortunately %al is the least significant 8 bits of
-   %eax anyway, which is why it's safe to work with %eax as a
-   whole. 
- 
-   On entry:
-	value of %eax
-	RA   <- %esp
-*/
-.global VG_(helper_DAS)
-VG_(helper_DAS):
-	pushl	%eax
-	movl	8(%esp), %eax
-	das
- 	movl	%eax, 8(%esp)
-	popl	%eax
-	ret
-
-
-/* Similarly, do %al = DAA(%al). */
-.global VG_(helper_DAA)
-VG_(helper_DAA):
-       pushl   %eax
-       movl    8(%esp), %eax
-       daa
-       movl    %eax, 8(%esp)
-       popl    %eax
-       ret
-	
-
-/* Bit scan forwards/reverse.  Sets flags (??).
-   On entry:
-	value, replaced by result
-	RA   <- %esp
-*/
-.global VG_(helper_bsr)
-VG_(helper_bsr):
-	pushl	%eax
-	movl	12(%esp), %eax
-	bsrl	8(%esp), %eax
-	movl	%eax, 12(%esp)
-	popl	%eax
-	ret
-
-.global VG_(helper_bsf)
-VG_(helper_bsf):
-	pushl	%eax
-	movl	12(%esp), %eax
-	bsfl	8(%esp), %eax
-	movl	%eax, 12(%esp)
-	popl	%eax
-	ret
-
-
-/* 32-bit double-length shift left/right.
-   On entry:
-	amount
-	src
-	dst
-	RA   <- %esp
-*/
-.global VG_(helper_shldl)
-VG_(helper_shldl):
-	pushl	%eax
-	pushl	%ebx
-	pushl	%ecx
-
-	movb	24(%esp), %cl
-	movl	20(%esp), %ebx
-	movl	16(%esp), %eax
-	shldl	%cl, %ebx, %eax
-	movl	%eax, 16(%esp)
-	
-	popl	%ecx
-	popl	%ebx
-	popl	%eax
-	ret
-
-.global VG_(helper_shldw)
-VG_(helper_shldw):
-	pushl	%eax
-	pushl	%ebx
-	pushl	%ecx
-
-	movb	24(%esp), %cl
-	movw	20(%esp), %bx
-	movw	16(%esp), %ax
-	shldw	%cl, %bx, %ax
-	movw	%ax, 16(%esp)
-	
-	popl	%ecx
-	popl	%ebx
-	popl	%eax
-	ret
-
-.global VG_(helper_shrdl)
-VG_(helper_shrdl):
-	pushl	%eax
-	pushl	%ebx
-	pushl	%ecx
-
-	movb	24(%esp), %cl
-	movl	20(%esp), %ebx
-	movl	16(%esp), %eax
-	shrdl	%cl, %ebx, %eax
-	movl	%eax, 16(%esp)
-	
-	popl	%ecx
-	popl	%ebx
-	popl	%eax
-	ret
-
-.global VG_(helper_shrdw)
-VG_(helper_shrdw):
-	pushl	%eax
-	pushl	%ebx
-	pushl	%ecx
-
-	movb	24(%esp), %cl
-	movw	20(%esp), %bx
-	movw	16(%esp), %ax
-	shrdw	%cl, %bx, %ax
-	movw	%ax, 16(%esp)
-	
-	popl	%ecx
-	popl	%ebx
-	popl	%eax
-	ret
-
-	
-/* Get the direction flag, and return either 1 or -1. */
-.global VG_(helper_get_dirflag)
-VG_(helper_get_dirflag):
-	pushl	%eax
-
-	movl	VGOFF_(m_dflag), %eax
-	movl	(%ebp, %eax, 4), %eax
-	movl	%eax, 8(%esp)
-
-	popl	%eax
-	ret
-
-/* Clear/set the direction flag. */
-.global VG_(helper_CLD)
-VG_(helper_CLD):
-	pushl	%eax
-
-	movl	VGOFF_(m_dflag), %eax
-	movl	$1, (%ebp, %eax, 4)
-
-	popl	%eax
-	ret
-
-.global VG_(helper_STD)
-VG_(helper_STD):
-	pushl	%eax
-
-	movl	VGOFF_(m_dflag), %eax
-	movl	$-1, (%ebp, %eax, 4)
-
-	popl	%eax
-	ret
-
-/* Clear/set the carry flag. */
-.global VG_(helper_CLC)
-VG_(helper_CLC):
-        clc
-        ret
-
-.global VG_(helper_STC)  
-VG_(helper_STC):
-        stc
-        ret
-
-/* Signed 32-to-64 multiply. */
-.globl VG_(helper_imul_32_64)
-VG_(helper_imul_32_64):
-	pushl	%eax
-	pushl	%edx
-	movl	16(%esp), %eax
-	imull	12(%esp)
-	movl	%eax, 16(%esp)
-	movl	%edx, 12(%esp)
-	popl	%edx
-	popl	%eax
-	ret
-	
-/* Signed 16-to-32 multiply. */
-.globl VG_(helper_imul_16_32)
-VG_(helper_imul_16_32):
-	pushl	%eax
-	pushl	%edx
-	movw	16(%esp), %ax
-	imulw	12(%esp)
-	movw	%ax, 16(%esp)
-	movw	%dx, 12(%esp)
-	popl	%edx
-	popl	%eax
-	ret
-	
-/* Signed 8-to-16 multiply. */
-.globl VG_(helper_imul_8_16)
-VG_(helper_imul_8_16):
-	pushl	%eax
-	pushl	%edx
-	movb	16(%esp), %al
-	imulb	12(%esp)
-	movw	%ax, 16(%esp)
-	popl	%edx
-	popl	%eax
-	ret
-	
-
-	
-	
-	
-	
-/* Unsigned 32-to-64 multiply. */
-.globl VG_(helper_mul_32_64)
-VG_(helper_mul_32_64):
-	pushl	%eax
-	pushl	%edx
-	movl	16(%esp), %eax
-	mull	12(%esp)
-	movl	%eax, 16(%esp)
-	movl	%edx, 12(%esp)
-	popl	%edx
-	popl	%eax
-	ret
-	
-/* Unsigned 16-to-32 multiply. */
-.globl VG_(helper_mul_16_32)
-VG_(helper_mul_16_32):
-	pushl	%eax
-	pushl	%edx
-	movw	16(%esp), %ax
-	mulw	12(%esp)
-	movw	%ax, 16(%esp)
-	movw	%dx, 12(%esp)
-	popl	%edx
-	popl	%eax
-	ret
-	
-/* Unsigned 8-to-16 multiply. */
-.globl VG_(helper_mul_8_16)
-VG_(helper_mul_8_16):
-	pushl	%eax
-	pushl	%edx
-	movb	16(%esp), %al
-	mulb	12(%esp)
-	movw	%ax, 16(%esp)
-	popl	%edx
-	popl	%eax
-	ret
-	
-	
-	
-		
-/* Unsigned 64-into-32 divide. */
-.globl	VG_(helper_div_64_32)
-VG_(helper_div_64_32):
-	pushl	%eax
-	pushl	%edx
-	movl	16(%esp),%eax
-	movl	12(%esp),%edx
-	divl	20(%esp)
-	movl	%eax,16(%esp)
-	movl	%edx,12(%esp)
-	popl	%edx
-	popl	%eax
-	ret
-
-/* Signed 64-into-32 divide. */
-.globl	VG_(helper_idiv_64_32)
-VG_(helper_idiv_64_32):
-	pushl	%eax
-	pushl	%edx
-	movl	16(%esp),%eax
-	movl	12(%esp),%edx
-	idivl	20(%esp)
-	movl	%eax,16(%esp)
-	movl	%edx,12(%esp)
-	popl	%edx
-	popl	%eax
-	ret
-
-/* Unsigned 32-into-16 divide. */
-.globl	VG_(helper_div_32_16)
-VG_(helper_div_32_16):
-	pushl	%eax
-	pushl	%edx
-	movw	16(%esp),%ax
-	movw	12(%esp),%dx
-	divw	20(%esp)
-	movw	%ax,16(%esp)
-	movw	%dx,12(%esp)
-	popl	%edx
-	popl	%eax
-	ret
-
-/* Signed 32-into-16 divide. */
-.globl	VG_(helper_idiv_32_16)
-VG_(helper_idiv_32_16):
-	pushl	%eax
-	pushl	%edx
-	movw	16(%esp),%ax
-	movw	12(%esp),%dx
-	idivw	20(%esp)
-	movw	%ax,16(%esp)
-	movw	%dx,12(%esp)
-	popl	%edx
-	popl	%eax
-	ret
-
-/* Unsigned 16-into-8 divide. */
-.globl	VG_(helper_div_16_8)
-VG_(helper_div_16_8):
-	pushl	%eax
-	movw	12(%esp),%ax
-	divb	16(%esp)
-	movb	%ah,12(%esp)
-	movb	%al,8(%esp)
-	popl	%eax
-	ret
-
-/* Signed 16-into-8 divide. */
-.globl	VG_(helper_idiv_16_8)
-VG_(helper_idiv_16_8):
-	pushl	%eax
-	movw	12(%esp),%ax
-	idivb	16(%esp)
-	movb	%ah,12(%esp)
-	movb	%al,8(%esp)
-	popl	%eax
-	ret
-
-
-/* Eight byte compare and exchange. */
-.globl VG_(helper_cmpxchg8b)
-VG_(helper_cmpxchg8b):
-        pushl %eax
-        pushl %ebx
-        pushl %ecx
-        pushl %edx
-        movl 20(%esp), %eax
-        movl 24(%esp), %edx
-        movl 28(%esp), %ebx
-        movl 32(%esp), %ecx
-        cmpxchg8b 36(%esp)
-        movl %eax, 20(%esp)
-        movl %edx, 24(%esp)
-        movl %ebx, 28(%esp)
-        movl %ecx, 32(%esp)
-        popl %edx
-        popl %ecx
-        popl %ebx
-        popl %eax
-        ret
-
-
-/* Undefined instruction (generates SIGILL) */
-.globl VG_(helper_undefined_instruction)
-VG_(helper_undefined_instruction):
-1:	ud2
-	jmp	1b
-			
-##--------------------------------------------------------------------##
-##--- end                                             vg_helpers.S ---##
-##--------------------------------------------------------------------##
diff -puN /dev/null coregrind/arch/i386-common/vg_helpers.S
--- /dev/null	2003-01-30 02:24:37.000000000 -0800
+++ valgrind-jeremy/coregrind/arch/i386-common/vg_helpers.S	2004-01-27 11:12:52.000000000 -0800
@@ -0,0 +1,603 @@
+##--------------------------------------------------------------------##
+##--- Support routines for the JITter output.                      ---##
+##---                                                 vg_helpers.S ---##
+##--------------------------------------------------------------------##
+
+/*
+  This file is part of Valgrind, an extensible x86 protected-mode
+  emulator for monitoring program execution on x86-Unixes.
+
+  Copyright (C) 2000-2004 Julian Seward 
+     jseward@acm.org
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "vg_constants.h"
+
+/* ------------------ REAL CPU HELPERS ------------------ */
+/* The rest of this lot run on the real CPU. */
+	
+/* Various helper routines, for instructions which are just too
+   darn tedious for the JITter to output code in-line:
+	
+	* integer division
+	* integer multiplication
+        * setting and getting obscure eflags
+	* double-length shifts
+        * eight byte compare and exchange
+	
+   All routines use a standard calling convention designed for
+   calling from translations, in which the incoming args are
+   underneath the return address, the callee saves _all_ registers,
+   and the incoming parameters can be modified, to return results.
+*/
+
+/* Fetch the time-stamp-ctr reg.
+   On entry:
+	dummy, replaced by %EAX value
+	dummy, replaced by %EDX value
+	RA   <- %esp
+*/
+.global VG_(helper_RDTSC)
+VG_(helper_RDTSC):
+	pushl	%eax
+	pushl	%edx
+	rdtsc
+	movl	%edx, 12(%esp)
+	movl	%eax, 16(%esp)
+	popl	%edx
+	popl	%eax
+	ret
+
+/* 
+   Fetch a byte/word/dword from given port
+   On entry:
+         size     1, 2 or 4
+         port, replaced by result
+         RA
+*/
+.global VG_(helper_IN)
+VG_(helper_IN):
+	pushl	%eax
+	pushl   %edx
+	movl	16(%esp), %eax
+	movl	12(%esp), %edx
+	cmpl	$4, %eax
+	je	in_dword
+	cmpl	$2, %eax
+	je	in_word
+in_byte:
+	inb	(%dx), %al
+	jmp	in_done
+in_word:
+	in	(%dx), %ax
+	jmp	in_done
+in_dword:
+	inl	(%dx),%eax
+in_done:
+	movl	%eax,12(%esp)
+	popl	%edx
+	popl	%eax
+	ret
+
+/* 
+   Write a byte/word/dword to given port
+   On entry:
+         size     1, 2 or 4
+         port
+         value
+         RA
+*/
+.global VG_(helper_OUT)
+VG_(helper_OUT):
+	pushl	%eax
+	pushl   %edx
+	movl	16(%esp), %edx
+	movl	12(%esp), %eax
+	cmpl	$4, 20(%esp)
+	je	out_dword
+	cmpl	$2, 20(%esp)
+	je	out_word
+out_byte:
+	outb	%al,(%dx)
+	jmp	out_done
+out_word:
+	out	%ax,(%dx)
+	jmp	out_done
+out_dword:
+	outl	%eax,(%dx)
+out_done:
+	popl	%edx
+	popl	%eax
+	ret
+
+
+/* Do the CPUID instruction.
+   On entry:
+	dummy, replaced by %EAX value
+	dummy, replaced by %EBX value
+	dummy, replaced by %ECX value
+	dummy, replaced by %EDX value
+	RA   <- %esp
+
+   We save registers and package up the args so we can call a C helper
+   for all this.
+*/
+.global VG_(helper_CPUID)
+VG_(helper_CPUID):
+	pushl	%ebp
+	movl	%esp,%ebp
+	pushl	%eax
+	pushl	%ebx
+	pushl	%ecx
+	pushl	%edx
+	pushl	%esi
+	pushl	%edi
+	pushf
+	
+	lea	2*4(%ebp),%eax	/* &edx */
+	pushl	%eax
+	addl	$4,%eax		/* &ecx */
+	pushl	%eax
+	addl	$4,%eax		/* &ebx */
+	pushl	%eax
+	addl	$4,%eax		/* &eax */
+	pushl	%eax
+	pushl	(%eax)		/* eax */
+
+	call	VG_(helperc_CPUID)
+	addl	$20,%esp
+
+	popf
+	popl	%edi
+	popl	%esi
+	popl	%edx
+	popl	%ecx
+	popl	%ebx
+	popl	%eax
+	popl	%ebp
+	ret
+
+
+/* Fetch the FPU status register.
+   On entry:
+	dummy, replaced by result
+	RA   <- %esp
+*/
+.global VG_(helper_fstsw_AX)
+VG_(helper_fstsw_AX):
+	pushl	%eax
+	pushl	%esi
+	movl	VGOFF_(m_ssestate), %esi
+
+	pushfl
+	cmpb	$0, VG_(have_ssestate)
+	jz	aa1nosse
+	fxrstor	(%ebp, %esi, 4)
+	jmp	aa1merge
+aa1nosse:
+	frstor	(%ebp, %esi, 4)
+aa1merge:
+	popfl
+
+	fstsw	%ax
+	popl	%esi
+	movw	%ax, 8(%esp)
+	popl	%eax
+	ret
+
+
+/* Copy %ah into %eflags.
+   On entry:
+	value of %eax
+	RA   <- %esp
+*/
+.global VG_(helper_SAHF)
+VG_(helper_SAHF):
+	pushl	%eax
+	movl	8(%esp), %eax
+	sahf
+	popl	%eax
+	ret
+
+/* Copy %eflags into %ah.
+   On entry:
+	value of %eax
+	RA   <- %esp
+*/
+.global VG_(helper_LAHF)
+VG_(helper_LAHF):
+	pushl	%eax
+	movl	8(%esp), %eax
+	lahf
+	movl	%eax, 8(%esp)
+	popl	%eax
+	ret
+
+
+/* Do %al = DAS(%al).  Note that the passed param has %AL as the least
+   significant 8 bits, since it was generated with GETB %AL,
+   some-temp.  Fortunately %al is the least significant 8 bits of
+   %eax anyway, which is why it's safe to work with %eax as a
+   whole. 
+ 
+   On entry:
+	value of %eax
+	RA   <- %esp
+*/
+.global VG_(helper_DAS)
+VG_(helper_DAS):
+	pushl	%eax
+	movl	8(%esp), %eax
+	das
+ 	movl	%eax, 8(%esp)
+	popl	%eax
+	ret
+
+
+/* Similarly, do %al = DAA(%al). */
+.global VG_(helper_DAA)
+VG_(helper_DAA):
+       pushl   %eax
+       movl    8(%esp), %eax
+       daa
+       movl    %eax, 8(%esp)
+       popl    %eax
+       ret
+	
+
+/* Bit scan forwards/reverse.  Sets flags (??).
+   On entry:
+	value, replaced by result
+	RA   <- %esp
+*/
+.global VG_(helper_bsr)
+VG_(helper_bsr):
+	pushl	%eax
+	movl	12(%esp), %eax
+	bsrl	8(%esp), %eax
+	movl	%eax, 12(%esp)
+	popl	%eax
+	ret
+
+.global VG_(helper_bsf)
+VG_(helper_bsf):
+	pushl	%eax
+	movl	12(%esp), %eax
+	bsfl	8(%esp), %eax
+	movl	%eax, 12(%esp)
+	popl	%eax
+	ret
+
+
+/* 32-bit double-length shift left/right.
+   On entry:
+	amount
+	src
+	dst
+	RA   <- %esp
+*/
+.global VG_(helper_shldl)
+VG_(helper_shldl):
+	pushl	%eax
+	pushl	%ebx
+	pushl	%ecx
+
+	movb	24(%esp), %cl
+	movl	20(%esp), %ebx
+	movl	16(%esp), %eax
+	shldl	%cl, %ebx, %eax
+	movl	%eax, 16(%esp)
+	
+	popl	%ecx
+	popl	%ebx
+	popl	%eax
+	ret
+
+.global VG_(helper_shldw)
+VG_(helper_shldw):
+	pushl	%eax
+	pushl	%ebx
+	pushl	%ecx
+
+	movb	24(%esp), %cl
+	movw	20(%esp), %bx
+	movw	16(%esp), %ax
+	shldw	%cl, %bx, %ax
+	movw	%ax, 16(%esp)
+	
+	popl	%ecx
+	popl	%ebx
+	popl	%eax
+	ret
+
+.global VG_(helper_shrdl)
+VG_(helper_shrdl):
+	pushl	%eax
+	pushl	%ebx
+	pushl	%ecx
+
+	movb	24(%esp), %cl
+	movl	20(%esp), %ebx
+	movl	16(%esp), %eax
+	shrdl	%cl, %ebx, %eax
+	movl	%eax, 16(%esp)
+	
+	popl	%ecx
+	popl	%ebx
+	popl	%eax
+	ret
+
+.global VG_(helper_shrdw)
+VG_(helper_shrdw):
+	pushl	%eax
+	pushl	%ebx
+	pushl	%ecx
+
+	movb	24(%esp), %cl
+	movw	20(%esp), %bx
+	movw	16(%esp), %ax
+	shrdw	%cl, %bx, %ax
+	movw	%ax, 16(%esp)
+	
+	popl	%ecx
+	popl	%ebx
+	popl	%eax
+	ret
+
+	
+/* Get the direction flag, and return either 1 or -1. */
+.global VG_(helper_get_dirflag)
+VG_(helper_get_dirflag):
+	pushl	%eax
+
+	movl	VGOFF_(m_dflag), %eax
+	movl	(%ebp, %eax, 4), %eax
+	movl	%eax, 8(%esp)
+
+	popl	%eax
+	ret
+
+/* Clear/set the direction flag. */
+.global VG_(helper_CLD)
+VG_(helper_CLD):
+	pushl	%eax
+
+	movl	VGOFF_(m_dflag), %eax
+	movl	$1, (%ebp, %eax, 4)
+
+	popl	%eax
+	ret
+
+.global VG_(helper_STD)
+VG_(helper_STD):
+	pushl	%eax
+
+	movl	VGOFF_(m_dflag), %eax
+	movl	$-1, (%ebp, %eax, 4)
+
+	popl	%eax
+	ret
+
+/* Clear/set the carry flag. */
+.global VG_(helper_CLC)
+VG_(helper_CLC):
+        clc
+        ret
+
+.global VG_(helper_STC)  
+VG_(helper_STC):
+        stc
+        ret
+
+/* Signed 32-to-64 multiply. */
+.globl VG_(helper_imul_32_64)
+VG_(helper_imul_32_64):
+	pushl	%eax
+	pushl	%edx
+	movl	16(%esp), %eax
+	imull	12(%esp)
+	movl	%eax, 16(%esp)
+	movl	%edx, 12(%esp)
+	popl	%edx
+	popl	%eax
+	ret
+	
+/* Signed 16-to-32 multiply. */
+.globl VG_(helper_imul_16_32)
+VG_(helper_imul_16_32):
+	pushl	%eax
+	pushl	%edx
+	movw	16(%esp), %ax
+	imulw	12(%esp)
+	movw	%ax, 16(%esp)
+	movw	%dx, 12(%esp)
+	popl	%edx
+	popl	%eax
+	ret
+	
+/* Signed 8-to-16 multiply. */
+.globl VG_(helper_imul_8_16)
+VG_(helper_imul_8_16):
+	pushl	%eax
+	pushl	%edx
+	movb	16(%esp), %al
+	imulb	12(%esp)
+	movw	%ax, 16(%esp)
+	popl	%edx
+	popl	%eax
+	ret
+	
+
+	
+	
+	
+	
+/* Unsigned 32-to-64 multiply. */
+.globl VG_(helper_mul_32_64)
+VG_(helper_mul_32_64):
+	pushl	%eax
+	pushl	%edx
+	movl	16(%esp), %eax
+	mull	12(%esp)
+	movl	%eax, 16(%esp)
+	movl	%edx, 12(%esp)
+	popl	%edx
+	popl	%eax
+	ret
+	
+/* Unsigned 16-to-32 multiply. */
+.globl VG_(helper_mul_16_32)
+VG_(helper_mul_16_32):
+	pushl	%eax
+	pushl	%edx
+	movw	16(%esp), %ax
+	mulw	12(%esp)
+	movw	%ax, 16(%esp)
+	movw	%dx, 12(%esp)
+	popl	%edx
+	popl	%eax
+	ret
+	
+/* Unsigned 8-to-16 multiply. */
+.globl VG_(helper_mul_8_16)
+VG_(helper_mul_8_16):
+	pushl	%eax
+	pushl	%edx
+	movb	16(%esp), %al
+	mulb	12(%esp)
+	movw	%ax, 16(%esp)
+	popl	%edx
+	popl	%eax
+	ret
+	
+	
+	
+		
+/* Unsigned 64-into-32 divide. */
+.globl	VG_(helper_div_64_32)
+VG_(helper_div_64_32):
+	pushl	%eax
+	pushl	%edx
+	movl	16(%esp),%eax
+	movl	12(%esp),%edx
+	divl	20(%esp)
+	movl	%eax,16(%esp)
+	movl	%edx,12(%esp)
+	popl	%edx
+	popl	%eax
+	ret
+
+/* Signed 64-into-32 divide. */
+.globl	VG_(helper_idiv_64_32)
+VG_(helper_idiv_64_32):
+	pushl	%eax
+	pushl	%edx
+	movl	16(%esp),%eax
+	movl	12(%esp),%edx
+	idivl	20(%esp)
+	movl	%eax,16(%esp)
+	movl	%edx,12(%esp)
+	popl	%edx
+	popl	%eax
+	ret
+
+/* Unsigned 32-into-16 divide. */
+.globl	VG_(helper_div_32_16)
+VG_(helper_div_32_16):
+	pushl	%eax
+	pushl	%edx
+	movw	16(%esp),%ax
+	movw	12(%esp),%dx
+	divw	20(%esp)
+	movw	%ax,16(%esp)
+	movw	%dx,12(%esp)
+	popl	%edx
+	popl	%eax
+	ret
+
+/* Signed 32-into-16 divide. */
+.globl	VG_(helper_idiv_32_16)
+VG_(helper_idiv_32_16):
+	pushl	%eax
+	pushl	%edx
+	movw	16(%esp),%ax
+	movw	12(%esp),%dx
+	idivw	20(%esp)
+	movw	%ax,16(%esp)
+	movw	%dx,12(%esp)
+	popl	%edx
+	popl	%eax
+	ret
+
+/* Unsigned 16-into-8 divide. */
+.globl	VG_(helper_div_16_8)
+VG_(helper_div_16_8):
+	pushl	%eax
+	movw	12(%esp),%ax
+	divb	16(%esp)
+	movb	%ah,12(%esp)
+	movb	%al,8(%esp)
+	popl	%eax
+	ret
+
+/* Signed 16-into-8 divide. */
+.globl	VG_(helper_idiv_16_8)
+VG_(helper_idiv_16_8):
+	pushl	%eax
+	movw	12(%esp),%ax
+	idivb	16(%esp)
+	movb	%ah,12(%esp)
+	movb	%al,8(%esp)
+	popl	%eax
+	ret
+
+
+/* Eight byte compare and exchange. */
+.globl VG_(helper_cmpxchg8b)
+VG_(helper_cmpxchg8b):
+        pushl %eax
+        pushl %ebx
+        pushl %ecx
+        pushl %edx
+        movl 20(%esp), %eax
+        movl 24(%esp), %edx
+        movl 28(%esp), %ebx
+        movl 32(%esp), %ecx
+        cmpxchg8b 36(%esp)
+        movl %eax, 20(%esp)
+        movl %edx, 24(%esp)
+        movl %ebx, 28(%esp)
+        movl %ecx, 32(%esp)
+        popl %edx
+        popl %ecx
+        popl %ebx
+        popl %eax
+        ret
+
+
+/* Undefined instruction (generates SIGILL) */
+.globl VG_(helper_undefined_instruction)
+VG_(helper_undefined_instruction):
+1:	ud2
+	jmp	1b
+			
+##--------------------------------------------------------------------##
+##--- end                                             vg_helpers.S ---##
+##--------------------------------------------------------------------##
diff -puN /dev/null coregrind/arch/i386-linux/vg_helpers.S
--- /dev/null	2003-01-30 02:24:37.000000000 -0800
+++ valgrind-jeremy/coregrind/arch/i386-linux/vg_helpers.S	2004-01-27 11:09:09.000000000 -0800
@@ -0,0 +1,87 @@
+##--------------------------------------------------------------------##
+##--- Support routines for the JITter output.                      ---##
+##---                                                 vg_helpers.S ---##
+##--------------------------------------------------------------------##
+
+/*
+  This file is part of Valgrind, an extensible x86 protected-mode
+  emulator for monitoring program execution on x86-Unixes.
+
+  Copyright (C) 2000-2004 Julian Seward 
+     jseward@acm.org
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "vg_constants.h"
+
+/* A stubs for a return which we want to catch: a signal return.
+   returns and pthread returns.  In the latter case, the thread's
+   return value is in %EAX, so we pass this as the first argument
+   to the request.  In both cases we use the user request mechanism.
+   You need to to read the definition of VALGRIND_MAGIC_SEQUENCE
+   in valgrind.h to make sense of this.
+
+   This isn't used in-place.  It is copied into the client address space
+   at an arbitary address.  Therefore, this code must be completely
+   position-independent.
+*/
+.global VG_(trampoline_code_start)
+.global VG_(trampoline_code_length)
+.global VG_(tramp_sigreturn_offset)
+.global VG_(tramp_syscall_offset)
+	
+VG_(trampoline_code_start):
+sigreturn_start:	
+	subl	$20, %esp	# allocate arg block
+	movl	%esp, %edx	# %edx == &_zzq_args[0]
+	movl	$VG_USERREQ__SIGNAL_RETURNS, 0(%edx)	# request
+	movl	$0, 4(%edx)	# arg1
+	movl	$0, 8(%edx)	# arg2
+	movl	$0, 12(%edx)	# arg3
+	movl	$0, 16(%edx)	# arg4
+	movl	%edx, %eax
+	# and now the magic sequence itself:
+	roll $29, %eax
+	roll $3, %eax
+	rorl $27, %eax
+	rorl $5, %eax
+	roll $13, %eax
+	roll $19, %eax
+	# should never get here
+	ud2
+
+	.align 16
+	# We can point our sysinfo stuff here
+syscall_start:	
+	int	$0x80
+	ret
+tramp_code_end:
+			
+.data
+VG_(trampoline_code_length):
+	.long tramp_code_end - VG_(trampoline_code_start)
+VG_(tramp_sigreturn_offset):
+	.long sigreturn_start - VG_(trampoline_code_start)
+VG_(tramp_syscall_offset):
+	.long syscall_start - VG_(trampoline_code_start)
+.text
+
+##--------------------------------------------------------------------##
+##--- end                                             vg_helpers.S ---##
+##--------------------------------------------------------------------##
diff -puN /dev/null coregrind/arch/i386-freebsd/vg_syscall.S
--- /dev/null	2003-01-30 02:24:37.000000000 -0800
+++ valgrind-jeremy/coregrind/arch/i386-freebsd/vg_syscall.S	2004-01-27 11:09:09.000000000 -0800
@@ -0,0 +1,181 @@
+
+##--------------------------------------------------------------------##
+##--- Support for doing system calls.                              ---##
+##---                                                 vg_syscall.S ---##
+##--------------------------------------------------------------------##
+
+/*
+  This file is part of Valgrind, an extensible x86 protected-mode
+  emulator for monitoring program execution on x86-Unixes.
+
+  Copyright (C) 2000-2004 Julian Seward 
+     jseward@acm.org
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "vg_constants.h"
+#include "vg_unistd.h"
+
+.globl	VG_(do_syscall)
+
+/*
+	Perform a Linux syscall with int 0x80
+	
+	Syscall args are passed on the stack
+	Int VG_(do_syscall)(Int syscall_no, ...)
+
+	This has no effect on the virtual machine; the expectation is
+	that the syscall mechanism makes no useful changes to any
+	register except %eax, which is returned.
+
+	XXX JSGF - where do we get the error code from?
+ */
+VG_(do_syscall):
+	pop	%ecx
+	pop	%eax
+	push	%ecx
+	int	$0x80
+	push	%ecx
+	jae	1f
+	movl	$-1,%eax
+1:	
+	ret
+	
+/*
+	Perform a FreeBSD syscall with int 0x80, returning error flag
+	
+	Syscall args are passed on the stack
+	Int VG_(do_syscall_err)(Int syscall_no, UInt edx, UInt* eflags, ...)
+				4               8         12
+	This has no effect on the virtual machine; the expectation is
+	that the syscall mechanism makes no useful changes to any
+	register except %eax and %edx, which are returned.
+ */
+.globl	VG_(do_syscall_err)
+VG_(do_syscall_err):
+	movl	12(%esp),%ecx
+	andb	$254,(%ecx)
+	movl	(%esp),%eax
+	movl	%eax,12(%esp)
+	movl	4(%esp),%eax
+	movl	8(%esp),%edx
+	addl	$12,%esp
+	int	$0x80
+	jae	1f
+	orb	$1,(%ecx)
+1:	
+	movl	(%esp),%ecx
+	push	%ecx
+	push	%ecx
+	push	%ecx
+	ret
+
+/*
+ *                8      12          16         20
+ * rfork_thread(flags, stack_addr, start_fnc, start_arg);
+ *
+ * flags:		Flags to rfork system call.  See rfork(2).
+ * stack_addr:		Top of stack for thread.
+ * start_fnc:		Address of thread function to call in child.
+ * start_arg:		Argument to pass to the thread function in child.
+ */
+
+.globl VG_(rfork_thread)
+VG_(rfork_thread):
+	pushl	%ebp
+	movl	%esp, %ebp
+	pushl	%esi
+
+	/*
+	 * Push thread info onto the new thread's stack
+	 */
+	movl	12(%ebp), %esi	# get stack addr
+
+	subl	$4, %esi
+	movl	20(%ebp), %eax	# get start argument
+	movl	%eax, (%esi)
+
+	subl	$4, %esi
+	movl	16(%ebp), %eax	# get start thread address
+	movl	%eax, (%esi)
+
+	/*
+	 * Prepare and execute the thread creation syscall
+	 */
+	pushl	8(%ebp)
+	pushl	$0
+	movl	$__NR_rfork, %eax
+	int	$0x80
+	jb 	2f
+
+	/*
+	 * Check to see if we are in the parent or child
+	 */
+	cmpl	$0, %edx
+	jnz	1f
+	addl	$8, %esp
+	popl	%esi
+	movl	%ebp, %esp
+	popl	%ebp
+	ret
+	.p2align 2
+
+	/*
+	 * If we are in the child (new thread), then
+	 * set-up the call to the internal subroutine.  If it
+	 * returns, then call __exit.
+	 */
+1:
+	movl	%esi,%esp
+	popl	%eax 
+	call	*%eax
+	addl	$4, %esp
+
+	/*
+	 * Exit system call
+	 */
+	pushl	%eax
+	pushl	$0
+	movl	$__NR_exit, %eax
+	int	$0x80
+
+	/*
+	 * Branch here if the thread creation fails:
+	 */
+2:
+	movl	$-1,%eax
+	ret	
+	
+.globl VG_(pipe)
+VG_(pipe):
+	mov	$__NR_pipe,%eax
+	int	$0x80
+	jb	1f
+	movl	4(%esp),%ecx
+	movl	%eax,(%ecx)
+	movl	%edx,4(%ecx)
+	movl	$0,%eax
+	ret
+1:
+	negl	%eax
+	ret
+
+##--------------------------------------------------------------------##
+##--- end                                             vg_syscall.S ---##
+##--------------------------------------------------------------------##
diff -puN /dev/null coregrind/arch/common-linux/vg_syscalls.c
--- /dev/null	2003-01-30 02:24:37.000000000 -0800
+++ valgrind-jeremy/coregrind/arch/common-linux/vg_syscalls.c	2004-01-27 11:09:10.000000000 -0800
@@ -0,0 +1,907 @@
+
+static 
+Addr mremap_segment ( Addr old_addr, UInt old_size,
+		      Addr new_addr, UInt new_size,
+		      UInt flags, ThreadId tid)
+{
+   Addr ret;
+   Segment *seg, *next;
+
+   old_size = PGROUNDUP(old_size);
+   new_size = PGROUNDUP(new_size);
+
+   if (PGROUNDDN(old_addr) != old_addr)
+      return -VKI_EINVAL;
+
+   if (!valid_client_addr(old_addr, old_size, tid, "mremap(old_addr)"))
+      return -VKI_EFAULT;
+
+   /* fixed at the current address means we don't move it */
+   if ((flags & VKI_MREMAP_FIXED) && (old_addr == new_addr))
+      flags &= ~(VKI_MREMAP_FIXED|VKI_MREMAP_MAYMOVE);
+
+   if (flags & VKI_MREMAP_FIXED) {
+      if (PGROUNDDN(new_addr) != new_addr)
+	 return -VKI_EINVAL;
+
+      if (!valid_client_addr(new_addr, new_size, tid, "mremap(new_addr)"))
+	 return -VKI_ENOMEM;
+
+      /* check for overlaps */
+      if ((old_addr < (new_addr+new_size) &&
+	   (old_addr+old_size) > new_addr) ||
+	  (new_addr < (old_addr+new_size) &&
+	   (new_addr+new_size) > old_addr))
+	 return -VKI_EINVAL;
+   }
+
+   /* Do nothing */
+   if (!(flags & VKI_MREMAP_FIXED) && new_size == old_size)
+      return old_addr;
+
+   seg = VG_(find_segment)(old_addr);
+
+   /* range must be contained within segment */
+   if (seg == NULL || !VG_(seg_contains)(seg, old_addr, old_size))
+      return -VKI_EINVAL;
+
+   next = VG_(next_segment)(seg);
+
+   if (0)
+      VG_(printf)("mremap: old_addr+new_size=%p next->addr=%p flags=%d\n",
+		  old_addr+new_size, next->addr, flags);
+   
+   if ((flags & VKI_MREMAP_FIXED) ||
+       (next != NULL && (old_addr+new_size) > next->addr)) {
+      /* we're moving the block */
+      Addr a;
+      
+      if ((flags & (VKI_MREMAP_FIXED|VKI_MREMAP_MAYMOVE)) == 0)
+	 return -VKI_ENOMEM;	/* not allowed to move */
+
+      if ((flags & VKI_MREMAP_FIXED) == 0)
+	  new_addr = 0;
+
+      a = VG_(find_map_space)(new_addr, new_size, True);
+
+      if ((flags & VKI_MREMAP_FIXED) && a != new_addr)
+	 return -VKI_ENOMEM;	/* didn't find the place we wanted */
+
+      new_addr = a;
+      ret = a;
+
+      /* we've nailed down the location */
+      flags |=  VKI_MREMAP_FIXED|VKI_MREMAP_MAYMOVE;
+
+      ret = VG_(do_syscall)(__NR_mremap, old_addr, old_size, new_size, 
+			    flags, new_addr);
+
+      if (ret != new_addr) {
+	 vg_assert(VG_(is_kerror)(ret));
+	 return ret;
+      }
+
+      VG_TRACK(copy_mem_remap, old_addr, new_addr, 
+	       (old_size < new_size) ? old_size : new_size);
+
+      if (new_size > old_size)
+	 VG_TRACK(new_mem_mmap, new_addr+old_size, new_size-old_size,
+		  seg->prot & VKI_PROT_READ, 
+		  seg->prot & VKI_PROT_WRITE, 
+		  seg->prot & VKI_PROT_EXEC);
+      VG_TRACK(die_mem_munmap, old_addr, old_size);
+
+      VG_(map_file_segment)(new_addr, new_size,
+			    seg->prot, 
+			    seg->flags,
+			    seg->dev, seg->ino,
+			    seg->offset, seg->filename);
+
+      VG_(munmap)((void *)old_addr, old_size);
+   } else {
+      /* staying in place */
+      ret = old_addr;
+
+      if (new_size < old_size) {
+	 VG_TRACK(die_mem_munmap, old_addr+new_size, old_size-new_size);
+	 VG_(munmap)((void *)(old_addr+new_size), old_size-new_size);
+      } else {
+	 /* we've nailed down the location */
+	 flags &= ~VKI_MREMAP_MAYMOVE;
+
+	 if (0)
+	    VG_(printf)("mremap: old_addr=%p old_size=%d new_size=%d flags=%d\n",
+			old_addr, old_size, new_size, flags);
+
+	 ret = VG_(do_syscall)(__NR_mremap, old_addr, old_size, new_size, 
+			       flags, 0);
+
+	 if (ret != old_addr)
+	    return ret;
+
+	 VG_TRACK(new_mem_mmap, old_addr+old_size, new_size-old_size,
+		  seg->prot & VKI_PROT_READ, 
+		  seg->prot & VKI_PROT_WRITE, 
+		  seg->prot & VKI_PROT_EXEC);
+
+	 VG_(map_file_segment)(old_addr+old_size, new_size-old_size,
+			       seg->prot, 
+			       seg->flags,
+			       seg->dev, seg->ino,
+			       seg->offset, seg->filename);	 
+      }
+   }
+
+   return ret;
+}
+
+/* ---------------------------------------------------------------------
+   FD tracking
+   ------------------------------------------------------------------ */
+
+/* Given a file descriptor, attempt to deduce it's filename.  To do this,
+   we use /proc/self/fd/<FD>.  If this doesn't point to a file, or if it
+   doesn't exist, we just return NULL.  Otherwise, we return a pointer
+   to the file name, which the caller is responsible for freeing. */
+
+Char *VG_(resolve_filename)(Int fd)
+{
+   char tmp[28], buf[PATH_MAX];
+
+   VG_(sprintf)(tmp, "/proc/self/fd/%d", fd);
+   VG_(memset)(buf, 0, PATH_MAX);
+
+   if(VG_(readlink)(tmp, buf, PATH_MAX) == -1)
+      return NULL;
+
+   return ((buf[0] == '/') ? VG_(arena_strdup)(VG_AR_CORE, buf) : NULL);
+}
+
+/* If /proc/self/fd doesn't exist for some weird reason (like you've
+   got a kernel that doesn't have /proc support compiled in), then we
+   need to find out what file descriptors we inherited from our parent
+   process the hard way - by checking each fd in turn. */
+
+static
+void do_hacky_preopened()
+{
+   struct vki_rlimit lim;
+   unsigned int count;
+   int i;
+
+   if(VG_(getrlimit) (VKI_RLIMIT_NOFILE, &lim) == -1) {
+      /* Hmm.  getrlimit() failed.  Now we're screwed, so just choose
+         an arbitrarily high number.  1024 happens to be the limit in
+         the 2.4 kernels. */
+      count = 1024;
+   } else {
+      count = lim.rlim_cur;
+   }
+
+   for (i = 0; i < count; i++)
+      if(VG_(fcntl)(i, VKI_F_GETFL, 0) != -1)
+         record_fd_open(-1, i, NULL);
+}
+
+/* Initialize the list of open file descriptors with the file descriptors
+   we inherited from out parent process. */
+
+void VG_(init_preopened_fds)()
+{
+   int f, ret;
+   struct vki_dirent d;
+
+   f = VG_(open)("/proc/self/fd", VKI_O_RDONLY, 0);
+   if(f == -1) {
+      do_hacky_preopened();
+      return;
+   }
+
+   while((ret = VG_(getdents)(f, &d, sizeof(d))) != 0) {
+      if(ret == -1)
+         goto out;
+
+      if(VG_(strcmp)(d.d_name, ".") && VG_(strcmp)(d.d_name, "..")) {
+         int fno = VG_(atoll)(d.d_name);
+
+         if(fno != f)
+            if(VG_(clo_track_fds))
+               record_fd_open(-1, fno, VG_(resolve_filename)(fno));
+      }
+
+      VG_(lseek)(f, d.d_off, VKI_SEEK_SET);
+   }
+
+out:
+   VG_(close)(f);
+}
+
+/* ---------------------------------------------------------------------
+   The Main Entertainment ...
+   ------------------------------------------------------------------ */
+
+PRE(exit_group)
+{
+   VG_(core_panic)("syscall exit_group() not caught by the scheduler?!");
+}
+
+PRE(clone)
+{
+   MAYBE_PRINTF("clone ( %d, %p, %p, %p, %p )\n",ARG(1),ARG(2),ARG(3),ARG(4),ARG(5));
+
+   if (ARG(2) == 0 &&
+       ARG(1) == (VKI_CLONE_CHILD_CLEARTID|VKI_CLONE_CHILD_SETTID|VKI_SIGCHLD)) {
+      before_fork(tid, tst);
+      RES = VG_(do_syscall)(SYSNO, ARG(1), ARG(2), ARG(3), ARG(4), ARG(5));
+      after_fork(tid, tst);
+   } else {
+      VG_(unimplemented)
+         ("clone(): not supported by Valgrind.\n   "
+          "We do now support programs linked against\n   "
+          "libpthread.so, though.  Re-run with -v and ensure that\n   "
+          "you are picking up Valgrind's implementation of libpthread.so.");
+   }
+}
+
+PRE(futex)
+{
+    /* int futex(void *futex, int op, int val, const struct timespec *timeout); */
+    MAYBE_PRINTF("futex ( %p, %d, %d, %p, %p )\n", ARG(1),ARG(2),ARG(3),ARG(4),ARG(5));
+    SYSCALL_TRACK( pre_mem_read, tid, "futex(futex)", ARG(1), sizeof(int) );
+    if (ARG(2) == VKI_FUTEX_WAIT && ARG(4) != (UInt)NULL)
+       SYSCALL_TRACK( pre_mem_read, tid, "futex(timeout)", ARG(4),
+                      sizeof(struct timespec) );
+    if (ARG(2) == VKI_FUTEX_REQUEUE)
+       SYSCALL_TRACK( pre_mem_read, tid, "futex(futex2)", ARG(4), sizeof(int) );
+}
+
+POST(futex)
+{
+   if (!VG_(is_kerror)(RES)) {
+      VG_TRACK( post_mem_write, ARG(1), sizeof(int) );
+      if (ARG(2) == VKI_FUTEX_FD && VG_(clo_track_fds))
+         record_fd_open(tid, RES, NULL);
+   }
+}
+
+PRE(_sysctl)
+{
+   /* int _sysctl(struct __sysctl_args *args); */
+   MAYBE_PRINTF("_sysctl ( %p )\n", ARG(1) );
+   SYSCALL_TRACK( pre_mem_write, tid, "_sysctl(args)", ARG(1), 
+		  sizeof(struct __sysctl_args) );
+}
+
+POST(_sysctl)
+{
+   VG_TRACK( post_mem_write, ARG(1), sizeof(struct __sysctl_args) );
+
+}
+
+PRE(sendfile64)
+{
+   /* ssize_t sendfile64(int out_df, int in_fd, loff_t *offset,
+      size_t count); */
+   MAYBE_PRINTF("sendfile64 ( %d, %d, %p, %d )\n",ARG(1),ARG(2),ARG(3),ARG(4));
+   if (ARG(3) != (UInt)NULL)
+      SYSCALL_TRACK( pre_mem_write, tid, "sendfile64(offset)",
+		     ARG(3), sizeof(loff_t) );
+}
+
+POST(sendfile64)
+{
+   if (ARG(3) != (UInt)NULL ) {
+      VG_TRACK( post_mem_write, ARG(3), sizeof(loff_t) );
+   }
+}
+
+PRE(getdents)
+{
+   /* int getdents(unsigned int fd, struct dirent *dirp, 
+      unsigned int count); */
+   MAYBE_PRINTF("getdents ( %d, %p, %d )\n",ARG(1),ARG(2),ARG(3));
+   SYSCALL_TRACK( pre_mem_write, tid, "getdents(dirp)", ARG(2), ARG(3) );
+}
+
+POST(getdents)
+{
+   VG_TRACK( post_mem_write, ARG(2), RES );
+}
+
+PRE(getdents64)
+{
+   /* int getdents(unsigned int fd, struct dirent64 *dirp, 
+      unsigned int count); */
+   MAYBE_PRINTF("getdents64 ( %d, %p, %d )\n",ARG(1),ARG(2),ARG(3));
+   SYSCALL_TRACK( pre_mem_write, tid, "getdents64(dirp)", ARG(2), ARG(3) );
+}
+
+POST(getdents64)
+{
+   VG_TRACK( post_mem_write, ARG(2), RES );
+}
+
+
+PRE(lstat64)
+{
+   /* int lstat64(const char *file_name, struct stat64 *buf); */
+   MAYBE_PRINTF("lstat64 ( %p \"%s\", %p )\n",ARG(1),ARG(1),ARG(2));
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "lstat64(file_name)", ARG(1) );
+   SYSCALL_TRACK( pre_mem_write, tid, "lstat64(buf)", ARG(2), 
+		  sizeof(struct vki_stat64) );
+}
+
+POST(lstat64)
+{
+   VG_TRACK( post_mem_write, ARG(2), sizeof(struct vki_stat64) );
+}
+
+PRE(_llseek)
+{
+   /* int _llseek(unsigned int fd, unsigned long offset_high,       
+      unsigned long  offset_low, 
+      loff_t * result, unsigned int whence); */
+   MAYBE_PRINTF("llseek ( %d, 0x%x, 0x%x, %p, %d )\n",
+		ARG(1),ARG(2),ARG(3),ARG(4),ARG(5));
+   SYSCALL_TRACK( pre_mem_write, tid, "llseek(result)", ARG(4), 
+		  sizeof(loff_t));
+}
+
+POST(_llseek)
+{
+   VG_TRACK( post_mem_write, ARG(4), sizeof(loff_t) );
+}
+
+PRE(pipe)
+{
+   /* int pipe(int filedes[2]); */
+   MAYBE_PRINTF("pipe ( %p ) ...\n", ARG(1));
+   SYSCALL_TRACK( pre_mem_write, tid, "pipe(filedes)", 
+		  ARG(1), 2*sizeof(int) );
+}
+
+POST(pipe)
+{
+   Int *p = (Int *)ARG(1);
+
+   if (!fd_allowed(p[0], "pipe", tid) ||
+       !fd_allowed(p[1], "pipe", tid)) {
+      VG_(close)(p[0]);
+      VG_(close)(p[1]);
+      SETERROR(tst, VKI_EMFILE);
+   } else {
+      VG_TRACK( post_mem_write, ARG(1), 2*sizeof(int) );
+      if(VG_(clo_track_fds)) {
+         record_fd_open(tid, p[0], NULL);
+         record_fd_open(tid, p[1], NULL);
+      }
+   }
+
+   MAYBE_PRINTF("SYSCALL[%d]       pipe --> %d (rd %d, wr %d)\n", 
+		VG_(getpid)(), RES,
+		((UInt*)ARG(1))[0], ((UInt*)ARG(1))[1] );
+}
+
+PRE(socketcall)
+{
+   /* int socketcall(int call, unsigned long *args); */
+   MAYBE_PRINTF("socketcall ( %d, %p )\n",ARG(1),ARG(2));
+   switch (ARG(1) /* request */) {
+
+   case SYS_SOCKETPAIR:
+      /* int socketpair(int d, int type, int protocol, int sv[2]); */
+      SYSCALL_TRACK( pre_mem_read, tid, "socketcall.socketpair(args)", 
+		     ARG(2), 4*sizeof(Addr) );
+      SYSCALL_TRACK( pre_mem_write, tid, "socketcall.socketpair(sv)", 
+		     ((UInt*)ARG(2))[3], 2*sizeof(int) );
+      break;
+
+   case SYS_SOCKET:
+      /* int socket(int domain, int type, int protocol); */
+      SYSCALL_TRACK( pre_mem_read, tid, "socketcall.socket(args)", 
+		     ARG(2), 3*sizeof(Addr) );
+      break;
+
+   case SYS_BIND:
+      /* int bind(int sockfd, struct sockaddr *my_addr, 
+	 int addrlen); */
+      SYSCALL_TRACK( pre_mem_read, tid, "socketcall.bind(args)", 
+		     ARG(2), 3*sizeof(Addr) );
+      pre_mem_read_sockaddr( tid, "socketcall.bind(my_addr.%s)",
+			     (struct sockaddr *) (((UInt*)ARG(2))[1]), ((UInt*)ARG(2))[2]);
+      break;
+               
+   case SYS_LISTEN:
+      /* int listen(int s, int backlog); */
+      SYSCALL_TRACK( pre_mem_read, tid, "socketcall.listen(args)", 
+		     ARG(2), 2*sizeof(Addr) );
+      break;
+
+   case SYS_ACCEPT: {
+      /* int accept(int s, struct sockaddr *addr, int *addrlen); */
+      SYSCALL_TRACK( pre_mem_read, tid, "socketcall.accept(args)", 
+		     ARG(2), 3*sizeof(Addr) );
+      {
+	 Addr addr_p     = ((UInt*)ARG(2))[1];
+	 Addr addrlen_p  = ((UInt*)ARG(2))[2];
+	 if (addr_p != (Addr)NULL) 
+	    buf_and_len_pre_check ( tid, addr_p, addrlen_p,
+				    "socketcall.accept(addr)",
+				    "socketcall.accept(addrlen_in)" );
+      }
+      break;
+   }
+
+   case SYS_SENDTO:
+      /* int sendto(int s, const void *msg, int len, 
+	 unsigned int flags, 
+	 const struct sockaddr *to, int tolen); */
+      SYSCALL_TRACK( pre_mem_read, tid, "socketcall.sendto(args)", ARG(2), 
+		     6*sizeof(Addr) );
+      SYSCALL_TRACK( pre_mem_read, tid, "socketcall.sendto(msg)",
+		     ((UInt*)ARG(2))[1], /* msg */
+		     ((UInt*)ARG(2))[2]  /* len */ );
+      pre_mem_read_sockaddr( tid, "socketcall.sendto(to.%s)",
+			     (struct sockaddr *) (((UInt*)ARG(2))[4]), ((UInt*)ARG(2))[5]);
+      break;
+
+   case SYS_SEND:
+      /* int send(int s, const void *msg, size_t len, int flags); */
+      SYSCALL_TRACK( pre_mem_read, tid, "socketcall.send(args)", ARG(2),
+		     4*sizeof(Addr) );
+      SYSCALL_TRACK( pre_mem_read, tid, "socketcall.send(msg)",
+		     ((UInt*)ARG(2))[1], /* msg */
+		     ((UInt*)ARG(2))[2]  /* len */ );
+      break;
+
+   case SYS_RECVFROM:
+      /* int recvfrom(int s, void *buf, int len, unsigned int flags,
+	 struct sockaddr *from, int *fromlen); */
+      SYSCALL_TRACK( pre_mem_read, tid, "socketcall.recvfrom(args)", 
+		     ARG(2), 6*sizeof(Addr) );
+      {
+	 Addr buf_p      = ((UInt*)ARG(2))[1];
+	 Int  len        = ((UInt*)ARG(2))[2];
+	 Addr from_p     = ((UInt*)ARG(2))[4];
+	 Addr fromlen_p  = ((UInt*)ARG(2))[5];
+
+	 SYSCALL_TRACK( pre_mem_write, tid, "socketcall.recvfrom(buf)", 
+			buf_p, len );
+	 if (from_p != (Addr)NULL) 
+	    buf_and_len_pre_check ( tid, from_p, fromlen_p, 
+				    "socketcall.recvfrom(from)",
+				    "socketcall.recvfrom(fromlen_in)" );
+      }
+      break;
+   
+   case SYS_RECV:
+      /* int recv(int s, void *buf, int len, unsigned int flags); */
+      /* man 2 recv says:
+	 The  recv call is normally used only on a connected socket
+	 (see connect(2)) and is identical to recvfrom with a  NULL
+	 from parameter.
+      */
+      SYSCALL_TRACK( pre_mem_read, tid, "socketcall.recv(args)", 
+		     ARG(2), 4*sizeof(Addr) );
+      SYSCALL_TRACK( pre_mem_write, tid, "socketcall.recv(buf)", 
+		     ((UInt*)ARG(2))[1], /* buf */
+		     ((UInt*)ARG(2))[2]  /* len */ );
+      break;
+
+   case SYS_CONNECT:
+      /* int connect(int sockfd, 
+	 struct sockaddr *serv_addr, int addrlen ); */
+      SYSCALL_TRACK( pre_mem_read, tid, "socketcall.connect(args)", 
+		     ARG(2), 3*sizeof(Addr) );
+      SYSCALL_TRACK( pre_mem_read, tid, 
+		     "socketcall.connect(serv_addr.sa_family)",
+		     ((UInt*)ARG(2))[1], /* serv_addr */
+		     sizeof (sa_family_t));
+      pre_mem_read_sockaddr( tid,
+			     "socketcall.connect(serv_addr.%s)",
+			     (struct sockaddr *) (((UInt*)ARG(2))[1]), ((UInt*)ARG(2))[2]);
+      break;
+
+   case SYS_SETSOCKOPT:
+      /* int setsockopt(int s, int level, int optname, 
+	 const void *optval, int optlen); */
+      SYSCALL_TRACK( pre_mem_read, tid, "socketcall.setsockopt(args)", 
+		     ARG(2), 5*sizeof(Addr) );
+      SYSCALL_TRACK( pre_mem_read, tid, "socketcall.setsockopt(optval)",
+		     ((UInt*)ARG(2))[3], /* optval */
+		     ((UInt*)ARG(2))[4]  /* optlen */ );
+      break;
+
+   case SYS_GETSOCKOPT:
+      /* int setsockopt(int s, int level, int optname, 
+	 void *optval, socklen_t *optlen); */
+      SYSCALL_TRACK( pre_mem_read, tid, "socketcall.getsockopt(args)", 
+		     ARG(2), 5*sizeof(Addr) );
+      {
+	 Addr optval_p  = ((UInt*)ARG(2))[3];
+	 Addr optlen_p  = ((UInt*)ARG(2))[4];
+	 /* vg_assert(sizeof(socklen_t) == sizeof(UInt)); */
+	 if (optval_p != (Addr)NULL) 
+	    buf_and_len_pre_check ( tid, optval_p, optlen_p,
+				    "socketcall.getsockopt(optval)",
+				    "socketcall.getsockopt(optlen)" );
+      }
+      break;
+
+   case SYS_GETSOCKNAME:
+      /* int getsockname(int s, struct sockaddr* name, int* namelen) */
+      SYSCALL_TRACK( pre_mem_read, tid, "socketcall.getsockname(args)",
+		     ARG(2), 3*sizeof(Addr) );
+      {
+	 Addr name_p     = ((UInt*)ARG(2))[1];
+	 Addr namelen_p  = ((UInt*)ARG(2))[2];
+
+	 /* Nb: name_p cannot be NULL */
+	 buf_and_len_pre_check ( tid, name_p, namelen_p,
+				 "socketcall.getsockname(name)",
+				 "socketcall.getsockname(namelen_in)" );
+      }
+      break;
+
+   case SYS_GETPEERNAME:
+      /* int getpeername(int s, struct sockaddr* name, int* namelen) */
+      SYSCALL_TRACK( pre_mem_read, tid, "socketcall.getpeername(args)",
+		     ARG(2), 3*sizeof(Addr) );
+      {
+	 Addr name_p     = ((UInt*)ARG(2))[1];
+	 Addr namelen_p  = ((UInt*)ARG(2))[2];
+
+	 /* Nb: name_p cannot be NULL */
+	 buf_and_len_pre_check ( tid, name_p, namelen_p,
+				 "socketcall.getpeername(name)",
+				 "socketcall.getpeername(namelen_in)" );
+      }
+      break;
+
+   case SYS_SHUTDOWN:
+      /* int shutdown(int s, int how); */
+      SYSCALL_TRACK( pre_mem_read, tid, "socketcall.shutdown(args)", 
+		     ARG(2), 2*sizeof(Addr) );
+      break;
+
+   case SYS_SENDMSG: {
+      /* int sendmsg(int s, const struct msghdr *msg, int flags); */
+
+      /* this causes warnings, and I don't get why. glibc bug?
+       * (after all it's glibc providing the arguments array)
+       SYSCALL_TRACK( pre_mem_read, "socketcall.sendmsg(args)", 
+       ARG(2), 3*sizeof(Addr) );
+      */
+
+      struct msghdr *msg = (struct msghdr *)((UInt *)ARG(2))[ 1 ];
+      msghdr_foreachfield ( tid, msg, pre_mem_read_sendmsg );
+
+      break;
+   }
+      
+   case SYS_RECVMSG: {
+      /* int recvmsg(int s, struct msghdr *msg, int flags); */
+
+      /* this causes warnings, and I don't get why. glibc bug?
+       * (after all it's glibc providing the arguments array)
+       SYSCALL_TRACK( pre_mem_read, "socketcall.recvmsg(args)", 
+       ARG(2), 3*sizeof(Addr) );
+      */
+
+      struct msghdr *msg = (struct msghdr *)((UInt *)ARG(2))[ 1 ];
+      msghdr_foreachfield ( tid, msg, pre_mem_write_recvmsg );
+
+      break;
+   }
+
+   default:
+      VG_(message)(Vg_DebugMsg,"Warning: unhandled socketcall 0x%x",ARG(1));
+      SETERROR(tst, VKI_EINVAL);
+      break;
+   }
+}
+
+POST(socketcall)
+{
+   /* int socketcall(int call, unsigned long *args); */
+   MAYBE_PRINTF("socketcall ( %d, %p )\n",ARG(1),ARG(2));
+
+   switch (ARG(1) /* request */) {
+
+   case SYS_SOCKETPAIR:
+      /* XXX TODO: check return fd against VG_(max_fd) */
+      VG_TRACK( post_mem_write, ((UInt*)ARG(2))[3], 2*sizeof(int) );
+      if(VG_(clo_track_fds)) {
+         record_fd_open(tid, ((UInt*)((UInt*)ARG(2))[3])[0], NULL);
+         record_fd_open(tid, ((UInt*)((UInt*)ARG(2))[3])[1], NULL);
+      }
+      break;
+
+   case SYS_SOCKET:
+      if (!fd_allowed(RES, "socket", tid)) {
+	 VG_(close)(RES);
+	 SETERROR(tst, VKI_EMFILE);
+      } else {
+         if(VG_(clo_track_fds))
+            record_fd_open(tid, RES, NULL);
+      }
+      break;
+
+   case SYS_BIND:
+      /* int bind(int sockfd, struct sockaddr *my_addr, 
+			int addrlen); */
+      break;
+               
+   case SYS_LISTEN:
+      /* int listen(int s, int backlog); */
+      break;
+
+   case SYS_ACCEPT: {
+      /* int accept(int s, struct sockaddr *addr, int *addrlen); */
+      if (!fd_allowed(RES, "accept", tid)) {
+	 VG_(close)(RES);
+	 SETERROR(tst, VKI_EMFILE);
+      } else {
+	 Addr addr_p     = ((UInt*)ARG(2))[1];
+	 Addr addrlen_p  = ((UInt*)ARG(2))[2];
+
+	 if (addr_p != (Addr)NULL) 
+	    buf_and_len_post_check ( tid, RES, addr_p, addrlen_p,
+				     "socketcall.accept(addrlen_out)" );
+         if(VG_(clo_track_fds))
+            record_fd_open(tid, RES, NULL);
+      }
+      break;
+   }
+
+   case SYS_SENDTO:
+      break;
+
+   case SYS_SEND:
+      break;
+
+   case SYS_RECVFROM:
+      {
+	 Addr buf_p      = ((UInt*)ARG(2))[1];
+	 Int  len        = ((UInt*)ARG(2))[2];
+	 Addr from_p     = ((UInt*)ARG(2))[4];
+	 Addr fromlen_p  = ((UInt*)ARG(2))[5];
+
+	 if (from_p != (Addr)NULL) 
+	    buf_and_len_post_check ( tid, RES, from_p, fromlen_p,
+				     "socketcall.recvfrom(fromlen_out)" );
+	 VG_TRACK( post_mem_write, buf_p, len );
+      }
+      break;
+
+   case SYS_RECV:
+      if (((UInt*)ARG(2))[1] != (UInt)NULL) {
+	 VG_TRACK( post_mem_write, ((UInt*)ARG(2))[1], /* buf */
+		   ((UInt*)ARG(2))[2]  /* len */ );
+      }
+      break;
+
+   case SYS_CONNECT:
+      break;
+
+   case SYS_SETSOCKOPT:
+      break;
+
+   case SYS_GETSOCKOPT:
+      {
+	 Addr optval_p  = ((UInt*)ARG(2))[3];
+	 Addr optlen_p  = ((UInt*)ARG(2))[4];
+
+	 if (optval_p != (Addr)NULL) 
+	    buf_and_len_post_check ( tid, RES, optval_p, optlen_p,
+				     "socketcall.getsockopt(optlen_out)" );
+      }
+      break;
+
+   case SYS_GETSOCKNAME:
+      {
+	 Addr name_p     = ((UInt*)ARG(2))[1];
+	 Addr namelen_p  = ((UInt*)ARG(2))[2];
+
+	 buf_and_len_post_check ( tid, RES, name_p, namelen_p,
+				  "socketcall.getsockname(namelen_out)" );
+      }
+      break;
+
+   case SYS_GETPEERNAME:
+      {
+	 Addr name_p     = ((UInt*)ARG(2))[1];
+	 Addr namelen_p  = ((UInt*)ARG(2))[2];
+
+	 buf_and_len_post_check ( tid, RES, name_p, namelen_p,
+				  "socketcall.getpeername(namelen_out)" );
+      }
+      break;
+
+   case SYS_SHUTDOWN:
+      break;
+
+   case SYS_SENDMSG:
+      break;
+
+   case SYS_RECVMSG:
+   {
+      struct msghdr *msg = (struct msghdr *)((UInt *)ARG(2))[ 1 ];
+
+      msghdr_foreachfield( tid, msg, post_mem_write_recvmsg );
+      check_cmsg_for_fds( tid, msg );
+
+      break;
+   }
+
+   default:
+      VG_(message)(Vg_DebugMsg,"FATAL: unhandled socketcall 0x%x",ARG(1));
+      VG_(core_panic)("... bye!\n");
+      break; /*NOTREACHED*/
+   }
+}
+
+PRE(stat64)
+{
+   /* int stat64(const char *file_name, struct stat64 *buf); */
+   MAYBE_PRINTF("stat64 ( %p, %p )\n",ARG(1),ARG(2));
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "stat64(file_name)", ARG(1) );
+   SYSCALL_TRACK( pre_mem_write, tid, "stat64(buf)", 
+		  ARG(2), sizeof(struct vki_stat64) );
+}
+
+POST(stat64)
+{
+   VG_TRACK( post_mem_write, ARG(2), sizeof(struct vki_stat64) );
+}
+
+PRE(fstat64)
+{
+   /* int fstat64(int filedes, struct stat64 *buf); */
+   MAYBE_PRINTF("fstat64 ( %d, %p )\n",ARG(1),ARG(2));
+   SYSCALL_TRACK( pre_mem_write, tid, "fstat64(buf)", 
+		  ARG(2), sizeof(struct vki_stat64) );
+}
+
+POST(fstat64)
+{
+   VG_TRACK( post_mem_write, ARG(2), sizeof(struct vki_stat64) );
+}
+
+PRE(statfs64)
+{
+   /* int statfs64(const char *path, struct statfs *buf); */
+   MAYBE_PRINTF("statfs64 ( %p, %p )\n",ARG(1),ARG(2));
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "statfs64(path)", ARG(1) );
+   SYSCALL_TRACK( pre_mem_write, tid, "statfs64(buf)", 
+		  ARG(2), sizeof(struct statfs64) );
+}
+
+POST(statfs64)
+{
+   VG_TRACK( post_mem_write, ARG(2), sizeof(struct statfs64) );
+}
+
+PRE(utime)
+{
+   /* int utime(const char *filename, struct utimbuf *buf); */
+   MAYBE_PRINTF("utime ( %p, %p )\n", ARG(1),ARG(2));
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "utime(filename)", ARG(1) );
+   if (ARG(2) != (UInt)NULL)
+      SYSCALL_TRACK( pre_mem_read, tid, "utime(buf)", ARG(2), 
+		     sizeof(struct utimbuf) );
+}
+
+PRE(adjtimex)
+{
+   struct timex *tx = (struct timex *)ARG(1);
+   MAYBE_PRINTF("adjtimex ( %p )\n", ARG(1));
+
+   SYSCALL_TRACK(pre_mem_read, tid, "adjtimex(timex->modes)", ARG(1), sizeof(tx->modes));
+
+#define ADJX(bit,field) 				\
+   if (tx->modes & bit)					\
+      SYSCALL_TRACK(pre_mem_read, tid,			\
+		    "adjtimex(timex->"#field")",	\
+		    (UInt)&tx->field, sizeof(tx->field))
+   ADJX(ADJ_FREQUENCY, freq);
+   ADJX(ADJ_MAXERROR, maxerror);
+   ADJX(ADJ_ESTERROR, esterror);
+   ADJX(ADJ_STATUS, status);
+   ADJX(ADJ_TIMECONST, constant);
+   ADJX(ADJ_TICK, tick);
+#undef ADJX
+   
+   SYSCALL_TRACK(pre_mem_write, tid, "adjtimex(timex)", ARG(1), sizeof(struct timex));
+}
+
+POST(adjtimex)
+{
+   VG_TRACK(post_mem_write, ARG(1), sizeof(struct timex));
+}
+
+PRE(rt_sigtimedwait)
+{
+   /* int sigtimedwait(const  sigset_t  *set,  siginfo_t  *info,
+      const struct timespec timeout); */
+   MAYBE_PRINTF("sigtimedwait ( %p, %p, timeout )\n", ARG(1), ARG(2));
+   if (ARG(1) != (UInt)NULL) 
+      SYSCALL_TRACK( pre_mem_read,  tid, "sigtimedwait(set)",  ARG(1),
+                     sizeof(vki_ksigset_t));
+   if (ARG(2) != (UInt)NULL)
+      SYSCALL_TRACK( pre_mem_write, tid, "sigtimedwait(info)", ARG(2),
+		     sizeof(siginfo_t) );
+}
+
+POST(rt_sigtimedwait)
+{
+   if (ARG(2) != (UInt)NULL)
+      VG_TRACK( post_mem_write, ARG(2), sizeof(siginfo_t) );
+}
+
+PRE(rt_sigqueueinfo)
+{
+   /*  long sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo) */
+   MAYBE_PRINTF("rt_sigqueueinfo(%d, %d, %p)\n", ARG(1), ARG(2), ARG(3));
+   if (ARG(2) != (UInt)NULL)
+      SYSCALL_TRACK( pre_mem_read, tid, "sigqueueinfo(uinfo)", ARG(3), 
+		     sizeof(siginfo_t) );
+}
+
+POST(rt_sigqueueinfo)
+{
+   if (ARG(2) != 0 &&
+       !VG_(is_sig_ign)(ARG(2)) &&
+       !VG_(ksigismember)(&tst->eff_sig_mask, ARG(2)) &&
+       ARG(1) == VG_(getpid)()) {
+      VG_(proxy_waitsig)();
+   }
+}
+
+PRE(select)
+{
+   /* struct sel_arg_struct {
+      unsigned long n;
+      fd_set *inp, *outp, *exp;
+      struct timeval *tvp;
+      };
+      int old_select(struct sel_arg_struct *arg);
+   */
+   SYSCALL_TRACK( pre_mem_read, tid, "select(args)", ARG(1), 5*sizeof(UInt) );
+
+   {
+      UInt* arg_struct = (UInt*)ARG(1);
+      UInt a1, a2, a3, a4, a5;
+
+      a1 = arg_struct[0];
+      a2 = arg_struct[1];
+      a3 = arg_struct[2];
+      a4 = arg_struct[3];
+      a5 = arg_struct[4];
+
+      MAYBE_PRINTF("select ( %d, %p, %p, %p, %p )\n", 
+		   a1,a2,a3,a4,a5);
+      if (a2 != (Addr)NULL)
+	 SYSCALL_TRACK( pre_mem_read, tid, "select(readfds)", a2, 
+			a1/8 /* __FD_SETSIZE/8 */ );
+      if (a3 != (Addr)NULL)
+	 SYSCALL_TRACK( pre_mem_read, tid, "select(writefds)", a3, 
+			ARG(1)/8 /* __FD_SETSIZE/8 */ );
+      if (a4 != (Addr)NULL)
+	 SYSCALL_TRACK( pre_mem_read, tid, "select(exceptfds)", a4, 
+			a1/8 /* __FD_SETSIZE/8 */ );
+      if (a5 != (Addr)NULL)
+	 SYSCALL_TRACK( pre_mem_read, tid, "select(timeout)", a5, 
+			sizeof(struct timeval) );
+   }
+}
+
+PRE(init_module)
+{
+   /* int init_module(const char *name, struct module *image); */
+   MAYBE_PRINTF("init_module ( %p, %p )\n", ARG(1), ARG(2) );
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "init_module(name)", ARG(1) );
+   SYSCALL_TRACK( pre_mem_read, tid, "init_module(image)", ARG(2), 
+		  VKI_SIZEOF_STRUCT_MODULE );
+}
+
diff -puN /dev/null coregrind/arch/i386-linux/vg_syscalls.c
--- /dev/null	2003-01-30 02:24:37.000000000 -0800
+++ valgrind-jeremy/coregrind/arch/i386-linux/vg_syscalls.c	2004-01-27 11:27:03.000000000 -0800
@@ -0,0 +1,3162 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Handle system calls.                           vg_syscalls.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+   This file is part of Valgrind, an extensible x86 protected-mode
+   emulator for monitoring program execution on x86-Unixes.
+
+   Copyright (C) 2000-2004 Julian Seward 
+      jseward@acm.org
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+
+/* vg_unsafe.h should NOT be included into any file except this
+   one. */
+#include "vg_unsafe.h"
+#include "vg_include.h"
+#include "vg_syscalls.h"
+
+/* All system calls are channelled through here, doing two things:
+
+   * notify the skin of the memory events (reads, writes) happening
+
+   * perform the syscall, usually by passing it along to the kernel
+     unmodified.
+
+   A magical piece of assembly code, VG_(do_syscall)(), in vg_syscall.S
+   does the tricky bit of passing a syscall to the kernel, whilst
+   having the simulator retain control.
+*/
+
+#include "vg_skin.h"
+
+#define SYSNO	(tst->m_eax)	/* in PRE(x)  */
+#define RES	(tst->m_eax)	/* in POST(x) */
+#define ARG(_zzqz_n) 				\
+   ({						\
+      UInt val;					\
+      switch(_zzqz_n) {				\
+      case 1:	val = tst->m_ebx; break;	\
+      case 2:	val = tst->m_ecx; break;	\
+      case 3:	val = tst->m_edx; break;	\
+      case 4:	val = tst->m_esi; break;	\
+      case 5:	val = tst->m_edi; break;	\
+      case 6:	val = tst->m_ebp; break;	\
+      }						\
+      val;					\
+   })
+#define SETARG(_zzqz_n, v)			\
+   ({						\
+      switch(_zzqz_n) {				\
+      case 1:	tst->m_ebx = (v); break;	\
+      case 2:	tst->m_ecx = (v); break;	\
+      case 3:	tst->m_edx = (v); break;	\
+      case 4:	tst->m_esi = (v); break;	\
+      case 5:	tst->m_edi = (v); break;	\
+      case 6:	tst->m_ebp = (v); break;	\
+      }						\
+   })
+
+static void run_syscall(UInt syscallno, ThreadState *tst);
+static Bool valid_client_addr(Addr start, UInt size, ThreadId tid, const Char *syscall);
+static const struct sys_info *get_sysinfo(UInt sysno, Bool *);
+
+/* Now that all the OS-specific stuff has been set up/declared,
+   include the rest of the syscalls */
+#include "../common-unix/vg_syscalls.c"
+#include "../common-linux/vg_syscalls.c"
+
+/* return true if address range entirely contained within client
+   address space */
+static Bool valid_client_addr(Addr start, UInt size, ThreadId tid, const Char *syscall)
+{
+   Addr end = start+size;
+   Addr cl_base = VG_(client_base);
+   Bool ret;
+
+   if (size == 0)
+      return True;
+
+   if (cl_base < 0x10000)
+      cl_base = 0x10000;
+
+   ret =
+      (end >= start) && 
+      start >= cl_base && start < VG_(client_end) &&
+      (end <= VG_(client_end));
+
+   if (0)
+      VG_(printf)("%s: test=%p-%p client=%p-%p ret=%d\n",
+		  syscall, start, end, cl_base, VG_(client_end), ret);
+
+   if (!ret && syscall != NULL) {
+      VG_(message)(Vg_UserMsg, "Warning: client syscall %s tried to modify addresses %p-%p",
+		   syscall, start, end);
+
+      if (VG_(clo_verbosity) > 1) {
+	 ExeContext *ec = VG_(get_ExeContext)(tid);
+	 VG_(pp_ExeContext)(ec);
+      }
+   }
+
+   return ret;
+}
+
+
+
+/* Is this a Linux kernel error return value? */
+/* From:
+   http://sources.redhat.com/cgi-bin/cvsweb.cgi/libc/sysdeps/unix/sysv/
+   linux/i386/sysdep.h?
+   rev=1.28&content-type=text/x-cvsweb-markup&cvsroot=glibc
+
+   \begin{quote}:
+
+   Linux uses a negative return value to indicate syscall errors,
+   unlike most Unices, which use the condition codes' carry flag.
+
+   Since version 2.1 the return value of a system call might be
+   negative even if the call succeeded.  E.g., the `lseek' system call
+   might return a large offset.  Therefore we must not anymore test
+   for < 0, but test for a real error by making sure the value in %eax
+   is a real error number.  Linus said he will make sure the no syscall
+   returns a value in -1 .. -4095 as a valid result so we can safely
+   test with -4095.  
+
+   END QUOTE
+*/
+Bool VG_(is_kerror) ( Int res )
+{
+   if (res >= -4095 && res <= -1)
+      return True;
+   else
+      return False;
+}
+
+static
+UInt get_shm_size ( Int shmid )
+{
+   struct shmid_ds buf;
+   long __res = VG_(do_syscall)(__NR_ipc, 24 /* IPCOP_shmctl */, shmid, IPC_STAT, 0, &buf);
+    if ( VG_(is_kerror) ( __res ) )
+       return 0;
+ 
+   return buf.shm_segsz;
+}
+ 
+
+
+/* ---------------------------------------------------------------------
+   The Main Entertainment ...
+   ------------------------------------------------------------------ */
+
+PRE(exit)
+{
+   VG_(core_panic)("syscall exit() not caught by the scheduler?!");
+}
+
+PRE(ptrace)
+{
+   /* long ptrace (enum __ptrace_request request, pid_t pid, 
+      void *addr, void *data); ... sort of. */
+   /* Sigh ... the /usr/include/sys/user.h on R H 6.2 doesn't 
+      define struct user_fpxregs_struct.  On the basis that it 
+      is defined as follows on my R H 7.2 (glibc-2.2.4) box, 
+      I kludge it.
+
+      struct user_fpxregs_struct
+      {
+      unsigned short int cwd;
+      unsigned short int swd;
+      unsigned short int twd;
+      unsigned short int fop;
+      long int fip;
+      long int fcs;
+      long int foo;
+      long int fos;
+      long int mxcsr;
+      long int reserved;
+      long int st_space[32];  8*16 bytes for each FP-reg = 128 bytes
+      long int xmm_space[32]; 8*16 bytes for each XMM-reg = 128 bytes
+      long int padding[56];
+      };
+   */
+   const Int sizeof_struct_user_fpxregs_struct
+      = sizeof(unsigned short) * (1 + 1 + 1 + 1) 
+      + sizeof(long int) * (1 + 1 + 1 + 1 + 1 + 1 + 32 + 32 + 56);
+
+   MAYBE_PRINTF("ptrace ( %d, %d, %p, %p )\n", ARG(1),ARG(2),ARG(3),ARG(4));
+   switch (ARG(1)) {
+   case 12:   /* PTRACE_GETREGS */
+      SYSCALL_TRACK( pre_mem_write, tid, "ptrace(getregs)", ARG(4), 
+		     sizeof (struct user_regs_struct));
+      break;
+   case 14:   /* PTRACE_GETFPREGS */
+      SYSCALL_TRACK( pre_mem_write, tid, "ptrace(getfpregs)", ARG(4), 
+		     sizeof (struct user_fpregs_struct));
+      break;
+   case 18:   /* PTRACE_GETFPXREGS */
+      SYSCALL_TRACK( pre_mem_write, tid, "ptrace(getfpxregs)", ARG(4), 
+		     sizeof_struct_user_fpxregs_struct);
+      break;
+   case 1: case 2: case 3:    /* PTRACE_PEEK{TEXT,DATA,USER} */
+      SYSCALL_TRACK( pre_mem_write, tid, "ptrace(peek)", ARG(4), 
+		     sizeof (long));
+      break;
+   case 13:   /* PTRACE_SETREGS */
+      SYSCALL_TRACK( pre_mem_read, tid, "ptrace(setregs)", ARG(4), 
+		     sizeof (struct user_regs_struct));
+      break;
+   case 15:   /* PTRACE_SETFPREGS */
+      SYSCALL_TRACK( pre_mem_read, tid, "ptrace(setfpregs)", ARG(4), 
+		     sizeof (struct user_fpregs_struct));
+      break;
+   case 19:   /* PTRACE_SETFPXREGS */
+      SYSCALL_TRACK( pre_mem_read, tid, "ptrace(setfpxregs)", ARG(4), 
+		     sizeof_struct_user_fpxregs_struct);
+      break;
+   default:
+      break;
+   }
+}
+
+POST(ptrace)
+{
+   const Int sizeof_struct_user_fpxregs_struct
+      = sizeof(unsigned short) * (1 + 1 + 1 + 1) 
+      + sizeof(long int) * (1 + 1 + 1 + 1 + 1 + 1 + 32 + 32 + 56);
+
+   switch (ARG(1)) {
+   case 12:  /* PTRACE_GETREGS */
+      VG_TRACK( post_mem_write, ARG(4), 
+		sizeof (struct user_regs_struct));
+      break;
+   case 14:  /* PTRACE_GETFPREGS */
+      VG_TRACK( post_mem_write, ARG(4), 
+		sizeof (struct user_fpregs_struct));
+      break;
+   case 18:  /* PTRACE_GETFPXREGS */
+      VG_TRACK( post_mem_write, ARG(4), 
+		sizeof_struct_user_fpxregs_struct);
+      break;
+   case 1: case 2: case 3:    /* PTRACE_PEEK{TEXT,DATA,USER} */
+      VG_TRACK( post_mem_write, ARG(4), sizeof (long));
+      break;
+   default:
+      break;
+   }
+}
+
+PRE(modify_ldt)
+{
+   MAYBE_PRINTF("modify_ldt ( %d, %p, %d )\n", ARG(1),ARG(2),ARG(3));
+   if (ARG(1) == 0) {
+      /* read the LDT into ptr */
+      SYSCALL_TRACK( pre_mem_write, tid, 
+		     "modify_ldt(ptr)(func=0)", ARG(2), ARG(3) );
+   }
+   if (ARG(1) == 1 || ARG(1) == 0x11) {
+      /* write the LDT with the entry pointed at by ptr */
+      SYSCALL_TRACK( pre_mem_read, tid, 
+		     "modify_ldt(ptr)(func=1 or 0x11)", ARG(2), 
+		     sizeof(struct vki_modify_ldt_ldt_s) );
+   }
+   /* "do" the syscall ourselves; the kernel never sees it */
+   RES = VG_(sys_modify_ldt)( tid, ARG(1), (void*)ARG(2), ARG(3) );
+
+   if (ARG(1) == 0 && !VG_(is_kerror)(RES) && RES > 0) {
+      VG_TRACK( post_mem_write, ARG(2), RES );
+   }
+}
+
+PRE(setresgid)
+{
+   /* int setresgid(gid_t rgid, gid_t egid, gid_t sgid); */
+   MAYBE_PRINTF("setresgid ( %d, %d, %d )\n", ARG(1), ARG(2), ARG(3));
+}
+
+PRE(vhangup)
+{
+   MAYBE_PRINTF("vhangup()\n");
+}
+
+PRE(iopl)
+{
+   MAYBE_PRINTF("iopl ( %d )\n", ARG(1));
+}
+
+PRE(setxattr)
+{
+   MAYBE_PRINTF("setxattr ( %p, %p, %p, %d, %d )\n",
+		ARG(1), ARG(2), ARG(3), ARG(4), ARG(5));
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "setxattr(path)", ARG(1) );
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "setxattr(name)", ARG(2) );
+   SYSCALL_TRACK( pre_mem_read, tid, "setxattr(value)", ARG(3), ARG(4) );
+}
+
+PREALIAS(lsetxattr, setxattr);
+
+PRE(fsetxattr)
+{
+   /* int fsetxattr (int filedes, const char *name,
+      const void *value, size_t size, int flags); */
+   MAYBE_PRINTF("fsetxattr ( %d, %p, %p, %d, %d )\n",
+		ARG(1), ARG(2), ARG(3), ARG(4), ARG(5));
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "fsetxattr(name)", ARG(2) );
+   SYSCALL_TRACK( pre_mem_read, tid, "fsetxattr(value)", ARG(3), ARG(4) );
+}
+
+PRE(getxattr)
+{
+   MAYBE_PRINTF("getxattr ( %p, %p, %p, %d )\n", 
+		ARG(1),ARG(2),ARG(3), ARG(4));
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "getxattr(path)", ARG(1) );
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "getxattr(name)", ARG(2) );
+   SYSCALL_TRACK( pre_mem_write, tid, "getxattr(value)", ARG(3), ARG(4) );
+}
+
+POST(getxattr)
+{
+   if (ARG(3) != (Addr)NULL) {
+      VG_TRACK( post_mem_write, ARG(3), RES );
+   }
+}
+
+PREALIAS(lgetxattr, getxattr);
+POSTALIAS(lgetxattr, getxattr);
+
+PRE(fgetxattr)
+{
+   MAYBE_PRINTF("fgetxattr ( %d, %p, %p, %d )\n",
+		ARG(1), ARG(2), ARG(3), ARG(4));
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "fgetxattr(name)", ARG(2) );
+   SYSCALL_TRACK( pre_mem_write, tid, "fgetxattr(value)", ARG(3), ARG(4) );
+}
+
+POST(fgetxattr)
+{
+   if (ARG(3) != (Addr)NULL)
+      VG_TRACK( post_mem_write, ARG(3), RES );
+}
+
+PRE(listxattr)
+{
+   MAYBE_PRINTF("listxattr ( %p, %p, %d )\n", ARG(1), ARG(2), ARG(3));
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "listxattr(path)", ARG(1) );
+   SYSCALL_TRACK( pre_mem_write, tid, "listxattr(list)", ARG(2), ARG(3) );
+}
+
+POST(listxattr)
+{
+   if (ARG(2) != (Addr)NULL)
+      VG_TRACK( post_mem_write, ARG(2), RES );
+}
+
+PREALIAS(llistxattr, listxattr);
+POSTALIAS(llistxattr, listxattr);
+
+PRE(flistxattr)
+{
+   /* ssize_t flistxattr (int filedes, char *list, size_t size); */
+   MAYBE_PRINTF("flistxattr ( %d, %p, %d )\n", ARG(1), ARG(2), ARG(3));
+   SYSCALL_TRACK( pre_mem_write, tid, "listxattr(list)", ARG(2), ARG(3) );
+}
+
+POST(flistxattr)
+{
+   if (ARG(2) != (Addr)NULL)
+      VG_TRACK( post_mem_write, ARG(2), RES );
+}
+
+PRE(removexattr)
+{
+   MAYBE_PRINTF("removexattr ( %p, %p )\n", ARG(1), ARG(2));
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "listxattr(path)", ARG(1) );
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "listxattr(name)", ARG(2) );
+}
+
+PREALIAS(lremovexattr, removexattr);
+
+PRE(fremovexattr)
+{
+   MAYBE_PRINTF("removexattr ( %d, %p )\n", ARG(1), ARG(2));
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "listxattr(name)", ARG(2) );
+}
+
+PRE(quotactl)
+{
+   MAYBE_PRINTF("quotactl (0x%x, %p, 0x%x, 0x%x )\n", 
+		ARG(1),ARG(2),ARG(3), ARG(4));
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "quotactl(special)", ARG(2) );
+}
+
+PRE(lookup_dcookie)
+{
+   MAYBE_PRINTF("lookup_dcookie (0x%llx, %p, %d)\n",
+		ARG(1) | ((long long) ARG(2) << 32), ARG(3), ARG(4));
+   SYSCALL_TRACK( pre_mem_write, tid, "lookup_dcookie(buf)", ARG(3), ARG(4));
+}
+
+POST(lookup_dcookie)
+{
+   if (ARG(3) != (Addr)NULL)
+      VG_TRACK( post_mem_write, ARG(3), RES);
+}
+
+PRE(truncate64)
+{
+   MAYBE_PRINTF("truncate64 ( %p, %lld )\n",
+		ARG(1), ((ULong)ARG(2)) | (((ULong) ARG(3)) << 32));
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "truncate64(path)", ARG(1) );
+}
+
+PRE(fdatasync)
+{
+   /* int fdatasync(int fd); */
+   MAYBE_PRINTF("fdatasync ( %d )\n", ARG(1));
+}
+
+PRE(msync)
+{
+   /* int msync(const void *start, size_t length, int flags); */
+   MAYBE_PRINTF("msync ( %p, %d, %d )\n", ARG(1),ARG(2),ARG(3));
+   SYSCALL_TRACK( pre_mem_read, tid, "msync(start)", ARG(1), ARG(2) );
+}
+
+struct getpmsg_strbuf {
+   int     maxlen;         /* no. of bytes in buffer */
+   int     len;            /* no. of bytes returned */
+   caddr_t buf;            /* pointer to data */
+};
+
+PRE(getpmsg)
+{
+   /* LiS getpmsg from http://www.gcom.com/home/linux/lis/ */
+   /* int getpmsg(int fd, struct strbuf *ctrl, struct strbuf *data, 
+      int *bandp, int *flagsp); */
+   struct getpmsg_strbuf *ctrl;
+   struct getpmsg_strbuf *data;
+   MAYBE_PRINTF("getpmsg ( %d, %p, %p, %p, %p )\n",
+		ARG(1),ARG(2),ARG(3),ARG(4),ARG(5));
+   ctrl = (struct getpmsg_strbuf *)ARG(2);
+   data = (struct getpmsg_strbuf *)ARG(3);
+   if (ctrl && ctrl->maxlen > 0)
+      SYSCALL_TRACK( pre_mem_write,tid, "getpmsg(ctrl)", 
+		     (UInt)ctrl->buf, ctrl->maxlen);
+   if (data && data->maxlen > 0)
+      SYSCALL_TRACK( pre_mem_write,tid, "getpmsg(data)", 
+		     (UInt)data->buf, data->maxlen);
+   if (ARG(4))
+      SYSCALL_TRACK( pre_mem_write,tid, "getpmsg(bandp)", 
+		     (UInt)ARG(4), sizeof(int));
+   if (ARG(5))
+      SYSCALL_TRACK( pre_mem_write,tid, "getpmsg(flagsp)", 
+		     (UInt)ARG(5), sizeof(int));
+}
+
+POST(getpmsg)
+{
+   struct getpmsg_strbuf *ctrl;
+   struct getpmsg_strbuf *data;
+
+   ctrl = (struct getpmsg_strbuf *)ARG(2);
+   data = (struct getpmsg_strbuf *)ARG(3);
+   if (RES == 0 && ctrl && ctrl->len > 0) {
+      VG_TRACK( post_mem_write, (UInt)ctrl->buf, ctrl->len);
+   }
+   if (RES == 0 && data && data->len > 0) {
+      VG_TRACK( post_mem_write, (UInt)data->buf, data->len);
+   }
+}
+
+PRE(putpmsg)
+{
+   /* LiS putpmsg from http://www.gcom.com/home/linux/lis/ */
+   /* int putpmsg(int fd, struct strbuf *ctrl, struct strbuf *data, 
+      int band, int flags); */
+   struct strbuf {
+      int     maxlen;         /* no. of bytes in buffer */
+      int     len;            /* no. of bytes returned */
+      caddr_t buf;            /* pointer to data */
+   };
+   struct strbuf *ctrl;
+   struct strbuf *data;
+   MAYBE_PRINTF("putpmsg ( %d, %p, %p, %d, %d )\n",
+		ARG(1),ARG(2),ARG(3),ARG(4),ARG(5));
+   ctrl = (struct strbuf *)ARG(2);
+   data = (struct strbuf *)ARG(3);
+   if (ctrl && ctrl->len > 0)
+      SYSCALL_TRACK( pre_mem_read,tid, "putpmsg(ctrl)",
+		     (UInt)ctrl->buf, ctrl->len);
+   if (data && data->len > 0)
+      SYSCALL_TRACK( pre_mem_read,tid, "putpmsg(data)",
+		     (UInt)data->buf, data->len);
+}
+
+PRE(getitimer)
+{
+   /* int getitimer(int which, struct itimerval *value); */
+   MAYBE_PRINTF("getitimer ( %d, %p )\n", ARG(1), ARG(2));
+   SYSCALL_TRACK( pre_mem_write, tid, "getitimer(timer)", ARG(2), 
+		  sizeof(struct itimerval) );
+}
+
+POST(getitimer)
+{
+   if (ARG(2) != (Addr)NULL) {
+      VG_TRACK( post_mem_write,ARG(2), sizeof(struct itimerval));
+   }
+}
+
+PRE(syslog)
+{
+   /* int syslog(int type, char *bufp, int len); */
+   MAYBE_PRINTF("syslog (%d, %p, %d)\n",ARG(1),ARG(2),ARG(3));
+   switch(ARG(1)) {
+   case 2: case 3: case 4:
+      SYSCALL_TRACK( pre_mem_write, tid, "syslog(buf)", ARG(2), ARG(3));
+      break;
+   default: 
+      break;
+   }
+}
+
+POST(syslog)
+{
+   switch (ARG(1)) {
+   case 2: case 3: case 4:
+      VG_TRACK( post_mem_write, ARG(2), ARG(3) );
+      break;
+   default:
+      break;
+   }
+}
+
+PRE(personality)
+{
+   /* int personality(unsigned long persona); */
+   MAYBE_PRINTF("personality ( %d )\n", ARG(1));
+}
+
+PRE(chroot)
+{
+   /* int chroot(const char *path); */
+   MAYBE_PRINTF("chroot ( %p )\n", ARG(1));
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "chroot(path)", ARG(1) );
+}
+
+PRE(madvise)
+{
+   /* int madvise(void *start, size_t length, int advice ); */
+   MAYBE_PRINTF("madvise ( %p, %d, %d )\n", ARG(1),ARG(2),ARG(3));
+}
+
+PRE(mremap)
+{
+   /* void* mremap(void * old_address, size_t old_size, 
+      size_t new_size, unsigned long flags, void * new_address); */
+   MAYBE_PRINTF("mremap ( %p, %d, %d, 0x%x, %p )\n", 
+		ARG(1), ARG(2), ARG(3), ARG(4), ARG(5));
+   
+   RES = mremap_segment((Addr)ARG(1), ARG(2), (Addr)ARG(5), ARG(3), ARG(4), tid);
+}
+
+PRE(nice)
+{
+   /* int nice(int inc); */
+   MAYBE_PRINTF("nice ( %d )\n", ARG(1));
+}
+
+PRE(setresgid32)
+{
+   /* int setresgid(gid_t rgid, gid_t egid, gid_t sgid); */
+   MAYBE_PRINTF("setresgid32 ( %d, %d, %d )\n", ARG(1), ARG(2), ARG(3));
+}
+
+PRE(setfsuid32)
+{
+   /* int setfsuid(uid_t fsuid); */
+   MAYBE_PRINTF("setfsuid ( %d )\n", ARG(1));
+}
+
+PRE(sched_getscheduler)
+{
+   /* int sched_getscheduler(pid_t pid); */
+   MAYBE_PRINTF("sched_getscheduler ( %d )\n", ARG(1));
+}
+
+PRE(sched_setscheduler)
+{
+   /* int sched_setscheduler(pid_t pid, int policy, 
+      const struct sched_param *p); */
+   MAYBE_PRINTF("sched_setscheduler ( %d, %d, %p )\n",ARG(1),ARG(2),ARG(3));
+   if (ARG(3) != (UInt)NULL)
+      SYSCALL_TRACK( pre_mem_read, tid,
+		     "sched_setscheduler(struct sched_param *p)", 
+		     ARG(3), sizeof(struct sched_param));
+}
+
+PRE(mlock)
+{
+   /* int mlock(const void * addr, size_t len) */
+   MAYBE_PRINTF("mlock ( %p, %d )\n", ARG(1), ARG(2));
+}
+
+PRE(munlock)
+{
+   /* int munlock(const void * addr, size_t len) */
+   MAYBE_PRINTF("munlock ( %p, %d )\n", ARG(1), ARG(2));
+}
+
+PRE(mlockall)
+{
+   /* int mlockall(int flags); */
+   MAYBE_PRINTF("mlockall ( %x )\n", ARG(1));
+}
+
+PRE(munlockall)
+{
+   /* int munlock(const void * addr, size_t len) */
+   MAYBE_PRINTF("munlock ( %p, %d )\n", ARG(1), ARG(2));
+}
+
+PRE(sched_get_priority_max)
+{
+   /* int sched_get_priority_max(int policy); */
+   MAYBE_PRINTF("sched_get_priority_max ( %d )\n", ARG(1));
+}
+
+PRE(sched_get_priority_min)
+{
+   /* int sched_get_priority_min(int policy); */
+   MAYBE_PRINTF("sched_get_priority_min ( %d )\n", ARG(1));
+}
+
+PRE(setpriority)
+{
+   /* int setpriority(int which, int who, int prio); */
+   MAYBE_PRINTF("setpriority ( %d, %d, %d )\n", ARG(1), ARG(2), ARG(3));
+}
+
+PRE(getpriority)
+{
+   /* int getpriority(int which, int who); */
+   MAYBE_PRINTF("getpriority ( %d, %d )\n", ARG(1), ARG(2));
+}
+
+PRE(setfsgid)
+{
+   /* int setfsgid(gid_t gid); */
+   MAYBE_PRINTF("setfsgid ( %d )\n", ARG(1));
+}
+
+PRE(setregid)
+{
+   /* int setregid(gid_t rgid, gid_t egid); */
+   MAYBE_PRINTF("setregid ( %d, %d )\n", ARG(1), ARG(2));
+}
+
+PRE(setresuid)
+{
+   /* int setresuid(uid_t ruid, uid_t euid, uid_t suid); */
+   MAYBE_PRINTF("setresuid ( %d, %d, %d )\n", ARG(1), ARG(2), ARG(3));
+}
+
+PRE(setfsuid)
+{
+   /* int setfsuid(uid_t uid); */
+   MAYBE_PRINTF("setfsuid ( %d )\n", ARG(1));
+}
+
+PRE(sendfile)
+{
+   /* ssize_t sendfile(int out_fd, int in_fd, off_t *offset, 
+      size_t count) */
+   MAYBE_PRINTF("sendfile ( %d, %d, %p, %d )\n",ARG(1),ARG(2),ARG(3),ARG(4));
+   if (ARG(3) != (UInt)NULL)
+      SYSCALL_TRACK( pre_mem_write, tid, "sendfile(offset)",
+		     ARG(3), sizeof(off_t) );
+}
+
+POST(sendfile)
+{
+   VG_TRACK( post_mem_write, ARG(3), sizeof( off_t ) );
+}
+
+PRE(pwrite64)
+{
+   /* ssize_t pwrite (int fd, const void *buf, size_t nbytes,
+      off_t offset); */
+   MAYBE_PRINTF("pwrite64 ( %d, %p, %d, %d )\n", ARG(1), ARG(2), ARG(3), ARG(4));
+   SYSCALL_TRACK( pre_mem_read, tid, "pwrite(buf)", ARG(2), ARG(3) );
+}
+
+PRE(fstatfs)
+{
+   /* int fstatfs(int fd, struct statfs *buf); */
+   MAYBE_PRINTF("fstatfs ( %d, %p )\n",ARG(1),ARG(2));
+   SYSCALL_TRACK( pre_mem_write, tid, "stat(buf)", 
+		  ARG(2), sizeof(struct statfs) );
+}
+
+POST(fstatfs)
+{
+   VG_TRACK( post_mem_write, ARG(2), sizeof(struct statfs) );
+}
+
+PRE(getsid)
+{
+   /* pid_t getsid(pid_t pid); */
+   MAYBE_PRINTF("getsid ( %d )\n", ARG(1));
+}
+
+PRE(pread64)
+{
+   /* ssize_t pread64(int fd, void *buf, size_t count, off_t offset); */
+   MAYBE_PRINTF("pread ( %d, %p, %d, %d ) ...\n",ARG(1),ARG(2),ARG(3),ARG(4));
+   SYSCALL_TRACK( pre_mem_write, tid, "pread(buf)", ARG(2), ARG(3) );
+}
+
+POST(pread64)
+{
+   MAYBE_PRINTF("SYSCALL[%d]       pread ( %d, %p, %d, %d ) --> %d\n",
+		VG_(getpid)(),
+		ARG(1), ARG(2), ARG(3), ARG(4), RES);
+   VG_TRACK( post_mem_write, ARG(2), RES );
+}
+
+PRE(ioperm)
+{
+   /* int ioperm(unsigned long from, unsigned long num, int turn_on); */
+   MAYBE_PRINTF("ioperm ( %d, %d, %d )\n", ARG(1), ARG(2), ARG(3) );
+}
+
+PRE(capget)
+{
+   /* int capget(cap_user_header_t header, cap_user_data_t data); */
+   MAYBE_PRINTF("capget ( %p, %p )\n", ARG(1), ARG(2) );
+   SYSCALL_TRACK( pre_mem_read, tid, "capget(header)", ARG(1), 
+		  sizeof(vki_cap_user_header_t) );
+   SYSCALL_TRACK( pre_mem_write, tid, "capget(data)", ARG(2), 
+		  sizeof( vki_cap_user_data_t) );
+}
+
+POST(capget)
+{
+   if (ARG(2) != (Addr)NULL)
+      VG_TRACK( post_mem_write, ARG(2), sizeof( vki_cap_user_data_t) );
+}
+
+PRE(capset)
+{
+   SYSCALL_TRACK( pre_mem_read, tid, "capset(header)", 
+		  ARG(1), sizeof(vki_cap_user_header_t) );
+   SYSCALL_TRACK( pre_mem_read, tid, "capset(data)", 
+		  ARG(2), sizeof( vki_cap_user_data_t) );
+}
+
+PRE(brk)
+{
+   Addr brk_limit = VG_(brk_limit);
+
+   /* libc   says: int   brk(void *end_data_segment);
+      kernel says: void* brk(void* end_data_segment);  (more or less)
+
+      libc returns 0 on success, and -1 (and sets errno) on failure.
+      Nb: if you ask to shrink the dataseg end below what it
+      currently is, that always succeeds, even if the dataseg end
+      doesn't actually change (eg. brk(0)).  Unless it seg faults.
+
+      Kernel returns the new dataseg end.  If the brk() failed, this
+      will be unchanged from the old one.  That's why calling (kernel)
+      brk(0) gives the current dataseg end (libc brk() just returns
+      zero in that case).
+
+      Both will seg fault if you shrink it back into a text segment.
+   */
+   MAYBE_PRINTF("brk ( %p ) --> ",ARG(1));
+
+   RES = do_brk(ARG(1));
+
+   MAYBE_PRINTF("0x%x\n", RES);
+
+   if (RES == ARG(1)) {
+      /* brk() succeeded */
+      if (RES < brk_limit) {
+         /* successfully shrunk the data segment. */
+         VG_TRACK( die_mem_brk, (Addr)ARG(1),
+		   brk_limit-ARG(1) );
+      } else
+      if (RES > brk_limit) {
+         /* successfully grew the data segment */
+         VG_TRACK( new_mem_brk, brk_limit,
+                                ARG(1)-brk_limit );
+      }
+   } else {
+      /* brk() failed */
+      vg_assert(brk_limit == RES);
+   }
+}
+
+PRE(chdir)
+{
+   /* int chdir(const char *path); */
+   MAYBE_PRINTF("chdir ( %p )\n", ARG(1));
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "chdir(path)", ARG(1) );
+}
+
+PRE(chmod)
+{
+   /* int chmod(const char *path, mode_t mode); */
+   MAYBE_PRINTF("chmod ( %p, %d )\n", ARG(1),ARG(2));
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "chmod(path)", ARG(1) );
+}
+
+PRE(chown)
+{
+   /* int chown(const char *path, uid_t owner, gid_t group); */
+   MAYBE_PRINTF("chown ( %p, 0x%x, 0x%x )\n", ARG(1),ARG(2),ARG(3));
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "chown(path)", ARG(1) );
+}
+
+PREALIAS(chown32, chown);
+PREALIAS(lchown32, chown);
+
+PRE(close)
+{
+   /* int close(int fd); */
+   MAYBE_PRINTF("close ( %d )\n",ARG(1));
+   /* Detect and negate attempts by the client to close Valgrind's
+      logfile fd ... */
+   if (!fd_allowed(ARG(1), "close", tid))
+      SETERROR(tst, VKI_EBADF);
+}
+
+POST(close)
+{
+   if(VG_(clo_track_fds)) record_fd_close(tid, ARG(1));
+}
+
+PRE(dup)
+{
+   /* int dup(int oldfd); */
+   MAYBE_PRINTF("dup ( %d ) --> ", ARG(1));
+}
+
+POST(dup)
+{
+   MAYBE_PRINTF("%d\n", RES);
+   if (!fd_allowed(RES, "dup", tid)) {
+      VG_(close)(RES);
+      SETERROR(tst, VKI_EMFILE);
+   } else {
+      if(VG_(clo_track_fds))
+         record_fd_open(tid, RES, VG_(resolve_filename)(RES));
+   }
+}
+
+PRE(dup2)
+{
+   /* int dup2(int oldfd, int newfd); */
+   MAYBE_PRINTF("dup2 ( %d, %d ) ...\n", ARG(1),ARG(2));
+   if (!fd_allowed(ARG(2), "dup2", tid))
+      SETERROR(tst, VKI_EBADF);
+}
+
+POST(dup2)
+{
+   MAYBE_PRINTF("SYSCALL[%d]       dup2 ( %d, %d ) = %d\n", 
+		VG_(getpid)(), 
+		ARG(1), ARG(2), RES);
+   if(VG_(clo_track_fds))
+      record_fd_open(tid, RES, VG_(resolve_filename)(RES));
+}
+
+PRE(fcntl)
+{
+   /* int fcntl(int fd, int cmd, int arg); */
+   MAYBE_PRINTF("fcntl ( %d, %d, %d )\n",ARG(1),ARG(2),ARG(3));
+}
+
+POST(fcntl)
+{
+   if (ARG(2) == VKI_F_DUPFD)
+      if(VG_(clo_track_fds))
+         record_fd_open(tid, RES, VG_(resolve_filename)(RES));
+}
+
+PRE(fchdir)
+{
+   /* int fchdir(int fd); */
+   MAYBE_PRINTF("fchdir ( %d )\n", ARG(1));
+}
+
+PRE(fchown)
+{
+   /* int fchown(int filedes, uid_t owner, gid_t group); */
+   MAYBE_PRINTF("fchown ( %d, %d, %d )\n", ARG(1),ARG(2),ARG(3));
+}
+
+PREALIAS(fchown32, fchown);
+
+PRE(fchmod)
+{
+   /* int fchmod(int fildes, mode_t mode); */
+   MAYBE_PRINTF("fchmod ( %d, %d )\n", ARG(1),ARG(2));
+}
+
+PRE(fcntl64)
+{
+   /* int fcntl64(int fd, int cmd, int arg); */
+   MAYBE_PRINTF("fcntl64 ( %d, %d, %d )\n", ARG(1),ARG(2),ARG(3));
+}
+
+POST(fcntl64)
+{
+   if (ARG(2) == VKI_F_DUPFD)
+      if(VG_(clo_track_fds))
+         record_fd_open(tid, RES, VG_(resolve_filename)(RES));
+}
+
+PRE(fstat)
+{
+   /* int fstat(int filedes, struct stat *buf); */
+   MAYBE_PRINTF("fstat ( %d, %p )\n",ARG(1),ARG(2));
+   SYSCALL_TRACK( pre_mem_write, tid, "fstat", ARG(2), sizeof(struct vki_stat) );
+}
+
+POST(fstat)
+{
+   VG_TRACK( post_mem_write, ARG(2), sizeof(struct vki_stat) );
+}
+
+PRE(fsync)
+{
+   /* int fsync(int fd); */
+   MAYBE_PRINTF("fsync ( %d )\n", ARG(1));
+}
+
+PRE(ftruncate)
+{
+   /* int ftruncate(int fd, size_t length); */
+   MAYBE_PRINTF("ftruncate ( %d, %d )\n", ARG(1),ARG(2));
+}
+
+PRE(ftruncate64)
+{
+   /* int ftruncate64(int fd, off64_t length); */
+   MAYBE_PRINTF("ftruncate64 ( %d, %lld )\n", 
+		ARG(1),ARG(2)|((long long) ARG(3) << 32));
+}
+
+PRE(getgroups)
+{
+   /* int getgroups(int size, gid_t list[]); */
+   MAYBE_PRINTF("getgroups ( %d, %p )\n", ARG(1), ARG(2));
+   if (ARG(1) > 0)
+      SYSCALL_TRACK( pre_mem_write, tid, "getgroups(list)", ARG(2), 
+		     ARG(1) * sizeof(gid_t) );
+}
+
+POST(getgroups)
+{
+   if (ARG(1) > 0)
+      VG_TRACK( post_mem_write, ARG(2), RES * sizeof(gid_t) );
+}
+
+PREALIAS(getgroups32, getgroups);
+POSTALIAS(getgroups32, getgroups);
+
+PRE(getcwd)
+{
+   /* char *getcwd(char *buf, size_t size);  (but see comment below) */
+   MAYBE_PRINTF("getcwd ( %p, %d )\n",ARG(1),ARG(2));
+   SYSCALL_TRACK( pre_mem_write, tid, "getcwd(buf)", ARG(1), ARG(2) );
+}
+
+POST(getcwd)
+{
+   if (RES != (Addr)NULL)
+      VG_TRACK( post_mem_write, ARG(1), RES );
+}
+
+PRE(geteuid)
+{
+   /* uid_t geteuid(void); */
+   MAYBE_PRINTF("geteuid ( )\n");
+}
+
+PRE(geteuid32)
+{
+   /* ?? uid_t geteuid32(void); */
+   MAYBE_PRINTF("geteuid32(?) ( )\n");
+}
+
+PRE(getegid)
+{
+   /* gid_t getegid(void); */
+   MAYBE_PRINTF("getegid ()\n");
+}
+
+PRE(getegid32)
+{
+   /* gid_t getegid32(void); */
+   MAYBE_PRINTF("getegid32 ()\n");
+}
+
+PRE(getgid)
+{
+   /* gid_t getgid(void); */
+   MAYBE_PRINTF("getgid ()\n");
+}
+
+PRE(getgid32)
+{
+   /* gid_t getgid32(void); */
+   MAYBE_PRINTF("getgid32 ()\n");
+}
+
+PRE(getpid)
+{
+   /* pid_t getpid(void); */
+   MAYBE_PRINTF("getpid ()\n");
+}
+
+PRE(getpgid)
+{
+   /* pid_t getpgid(pid_t pid); */
+   MAYBE_PRINTF("getpgid ( %d )\n", ARG(1));
+}
+
+PRE(getpgrp)
+{
+   /* pid_t getpgrp(void); */
+   MAYBE_PRINTF("getpgrp ()\n");
+}
+
+PRE(getppid)
+{
+   /* pid_t getppid(void); */
+   MAYBE_PRINTF("getppid ()\n");
+}
+
+PRE(getresgid)
+{
+   /* int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); */
+   MAYBE_PRINTF("getresgid ( %p, %p, %p )\n", ARG(1),ARG(2),ARG(3));
+   SYSCALL_TRACK( pre_mem_write, tid, "getresgid(rgid)", 
+		  ARG(1), sizeof(gid_t) );
+   SYSCALL_TRACK( pre_mem_write, tid, "getresgid(egid)", 
+		  ARG(2), sizeof(gid_t) );
+   SYSCALL_TRACK( pre_mem_write, tid, "getresgid(sgid)", 
+		  ARG(3), sizeof(gid_t) );
+}
+
+POST(getresgid)
+{
+   if (RES == 0) {
+      VG_TRACK( post_mem_write, ARG(1), sizeof(gid_t) );
+      VG_TRACK( post_mem_write, ARG(2), sizeof(gid_t) );
+      VG_TRACK( post_mem_write, ARG(3), sizeof(gid_t) );
+   }
+}
+
+PRE(getresgid32)
+{
+   /* int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); */
+   MAYBE_PRINTF("getresgid32 ( %p, %p, %p )\n", ARG(1),ARG(2),ARG(3));
+   SYSCALL_TRACK( pre_mem_write, tid, "getresgid32(rgid)", 
+		  ARG(1), sizeof(gid_t) );
+   SYSCALL_TRACK( pre_mem_write, tid, "getresgid32(egid)", 
+		  ARG(2), sizeof(gid_t) );
+   SYSCALL_TRACK( pre_mem_write, tid, "getresgid32(sgid)", 
+		  ARG(3), sizeof(gid_t) );
+}
+
+POST(getresgid32)
+{
+   if (RES == 0) {
+      VG_TRACK( post_mem_write, ARG(1), sizeof(gid_t) );
+      VG_TRACK( post_mem_write, ARG(2), sizeof(gid_t) );
+      VG_TRACK( post_mem_write, ARG(3), sizeof(gid_t) );
+   }
+}
+
+PRE(getresuid)
+{
+   /* int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); */
+   MAYBE_PRINTF("getresuid ( %p, %p, %p )\n", ARG(1),ARG(2),ARG(3));
+   SYSCALL_TRACK( pre_mem_write, tid, "getresuid(ruid)", 
+		  ARG(1), sizeof(uid_t) );
+   SYSCALL_TRACK( pre_mem_write, tid, "getresuid(euid)", 
+		  ARG(2), sizeof(uid_t) );
+   SYSCALL_TRACK( pre_mem_write, tid, "getresuid(suid)", 
+		  ARG(3), sizeof(uid_t) );
+}
+
+POST(getresuid)
+{
+   if (RES == 0) {
+      VG_TRACK( post_mem_write, ARG(1), sizeof(uid_t) );
+      VG_TRACK( post_mem_write, ARG(2), sizeof(uid_t) );
+      VG_TRACK( post_mem_write, ARG(3), sizeof(uid_t) );
+   }
+}
+
+PRE(getresuid32)
+{
+   /* int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); */
+   MAYBE_PRINTF("getresuid32 ( %p, %p, %p )\n", ARG(1),ARG(2),ARG(3));
+   SYSCALL_TRACK( pre_mem_write, tid, "getresuid32(ruid)", 
+		  ARG(1), sizeof(uid_t) );
+   SYSCALL_TRACK( pre_mem_write, tid, "getresuid32(euid)", 
+		  ARG(2), sizeof(uid_t) );
+   SYSCALL_TRACK( pre_mem_write, tid, "getresuid32(suid)", 
+		  ARG(3), sizeof(uid_t) );
+}
+
+POST(getresuid32)
+{
+   if (RES == 0) {
+      VG_TRACK( post_mem_write, ARG(1), sizeof(uid_t) );
+      VG_TRACK( post_mem_write, ARG(2), sizeof(uid_t) );
+      VG_TRACK( post_mem_write, ARG(3), sizeof(uid_t) );
+   }
+}
+
+PRE(getrlimit)
+{
+   /* int getrlimit (int resource, struct rlimit *rlim); */
+   MAYBE_PRINTF("getrlimit ( %d, %p )\n", ARG(1),ARG(2));
+   SYSCALL_TRACK( pre_mem_write, tid, "getrlimit(rlim)", ARG(2), 
+		  sizeof(struct rlimit) );
+}
+
+POST(getrlimit)
+{
+   if (RES == 0)
+      VG_TRACK( post_mem_write, ARG(2), sizeof(struct rlimit) );
+}
+
+PREALIAS(ugetrlimit, getrlimit);
+POSTALIAS(ugetrlimit, getrlimit);
+
+PRE(getrusage)
+{
+   /* int getrusage (int who, struct rusage *usage); */
+   MAYBE_PRINTF("getrusage ( %d, %p )\n", ARG(1),ARG(2));
+   SYSCALL_TRACK( pre_mem_write, tid, "getrusage(usage)", ARG(2), 
+		  sizeof(struct rusage) );
+}
+
+POST(getrusage)
+{
+   if (RES == 0)
+      VG_TRACK( post_mem_write,ARG(2), sizeof(struct rusage) );
+}
+
+PRE(gettimeofday)
+{
+   /* int gettimeofday(struct timeval *tv, struct timezone *tz); */
+   MAYBE_PRINTF("gettimeofday ( %p, %p )\n",ARG(1),ARG(2));
+   SYSCALL_TRACK( pre_mem_write, tid, "gettimeofday(tv)", ARG(1), 
+		  sizeof(struct timeval) );
+   if (ARG(2) != 0)
+      SYSCALL_TRACK( pre_mem_write, tid, "gettimeofday(tz)", ARG(2), 
+		     sizeof(struct timezone) );
+}
+
+POST(gettimeofday)
+{
+   if (RES == 0) {
+      VG_TRACK( post_mem_write, ARG(1), sizeof(struct timeval) );
+      if (ARG(2) != 0)
+	 VG_TRACK( post_mem_write, ARG(2), sizeof(struct timezone) );
+   }
+}
+
+PRE(getuid)
+{
+   /* uid_t getuid(void); */
+   MAYBE_PRINTF("getuid ( )\n");
+}
+
+PRE(getuid32)
+{
+   /* ???uid_t getuid32(void); */
+   MAYBE_PRINTF("getuid32 ( )\n");
+}
+
+PRE(ipc)
+{
+   MAYBE_PRINTF("ipc ( %d, %d, %d, %d, %p, %d )\n",
+		ARG(1),ARG(2),ARG(3),ARG(4),ARG(5),ARG(6));
+   switch (ARG(1) /* call */) {
+   case 1: /* IPCOP_semop */
+      SYSCALL_TRACK( pre_mem_read, tid, "semop(sops)", ARG(5), 
+		     ARG(3) * sizeof(struct sembuf) );
+      break;
+   case 2: /* IPCOP_semget */
+   case 3: /* IPCOP_semctl */
+      break;
+   case 11: /* IPCOP_msgsnd */
+   {
+      struct msgbuf *msgp = (struct msgbuf *)ARG(5);
+      Int msgsz = ARG(3);
+
+      SYSCALL_TRACK( pre_mem_read, tid, "msgsnd(msgp->mtype)", 
+		     (UInt)&msgp->mtype, sizeof(msgp->mtype) );
+      SYSCALL_TRACK( pre_mem_read, tid, "msgsnd(msgp->mtext)", 
+		     (UInt)msgp->mtext, msgsz );
+      break;
+   }
+   case 12: /* IPCOP_msgrcv */
+   {
+      struct msgbuf *msgp;
+      Int msgsz = ARG(3);
+ 
+      msgp = (struct msgbuf *)deref_Addr( tid,
+					  (Addr) (&((struct ipc_kludge *)ARG(5))->msgp),
+					  "msgrcv(msgp)" );
+
+      SYSCALL_TRACK( pre_mem_write, tid, "msgrcv(msgp->mtype)", 
+		     (UInt)&msgp->mtype, sizeof(msgp->mtype) );
+      SYSCALL_TRACK( pre_mem_write, tid, "msgrcv(msgp->mtext)", 
+		     (UInt)msgp->mtext, msgsz );
+      break;
+   }
+   case 13: /* IPCOP_msgget */
+      break;
+   case 14: /* IPCOP_msgctl */
+   {
+      switch (ARG(3) /* cmd */) {
+      case IPC_STAT:
+	 SYSCALL_TRACK( pre_mem_write, tid, "msgctl(buf)", ARG(5), 
+			sizeof(struct msqid_ds) );
+	 break;
+      case IPC_SET:
+	 SYSCALL_TRACK( pre_mem_read, tid, "msgctl(buf)", ARG(5), 
+			sizeof(struct msqid_ds) );
+	 break;
+#                    if defined(IPC_64)
+      case IPC_STAT|IPC_64:
+	 SYSCALL_TRACK( pre_mem_write, tid, "msgctl(buf)", ARG(5), 
+			sizeof(struct msqid64_ds) );
+	 break;
+#                    endif
+#                    if defined(IPC_64)
+      case IPC_SET|IPC_64:
+	 SYSCALL_TRACK( pre_mem_read, tid, "msgctl(buf)", ARG(5), 
+			sizeof(struct msqid64_ds) );
+	 break;
+#                    endif
+      default:
+	 break;
+      }
+      break;
+   }
+   case 21: /* IPCOP_shmat */
+   {
+      UInt shmid = ARG(2);
+      UInt segmentSize = get_shm_size ( shmid );
+      
+      /* If they didn't ask for a particular address, then place it
+	 like an mmap. */
+      if (ARG(5) == 0)
+	 SETARG(5, VG_(find_map_space)(0, segmentSize, True));
+      else if (!valid_client_addr(ARG(5), segmentSize, tid, "shmat"))
+	 SETERROR(tst, VKI_EINVAL);
+      break;
+   }
+   case 22: /* IPCOP_shmdt */
+      if (!valid_client_addr(ARG(1), 1, tid, "shmdt"))
+	 SETERROR(tst, VKI_EINVAL);
+      break;
+   case 23: /* IPCOP_shmget */
+      break;
+   case 24: /* IPCOP_shmctl */
+      /* Subject: shmctl: The True Story
+	 Date: Thu, 9 May 2002 18:07:23 +0100 (BST)
+	 From: Reuben Thomas <rrt@mupsych.org>
+	 To: Julian Seward <jseward@acm.org>
+
+	 1. As you suggested, the syscall subop is in ARG(1).
+
+	 2. There are a couple more twists, so the arg order
+	 is actually:
+
+	 ARG(1) syscall subop
+	 ARG(2) file desc
+	 ARG(3) shm operation code (can have IPC_64 set)
+	 ARG(4) 0 ??? is ARG(3)-ARG(4) a 64-bit quantity when IPC_64
+	 is defined?
+	 ARG(5) pointer to buffer
+
+	 3. With this in mind, I've amended the case as below:
+      */
+   {
+      UInt cmd = ARG(3);
+      Bool out_arg = False;
+      if ( ARG(5) ) {
+#                    if defined(IPC_64)
+	 cmd = cmd & (~IPC_64);
+#                    endif
+	 out_arg = cmd == SHM_STAT || cmd == IPC_STAT;
+	 if ( out_arg )
+	    SYSCALL_TRACK( pre_mem_write, tid, 
+                           "shmctl(SHM_STAT or IPC_STAT,buf)", 
+                           ARG(5), sizeof(struct shmid_ds) );
+	 else
+	    SYSCALL_TRACK( pre_mem_read, tid, 
+                           "shmctl(SHM_XXXX,buf)", 
+                           ARG(5), sizeof(struct shmid_ds) );
+      }
+   }
+   break;
+   default:
+      VG_(message)(Vg_DebugMsg,
+		   "FATAL: unhandled syscall(ipc) %d",
+		   ARG(1) );
+      VG_(core_panic)("... bye!\n");
+      break; /*NOTREACHED*/
+   }   
+}
+
+POST(ipc)
+{
+   switch (ARG(1) /* call */) {
+   case 1: /* IPCOP_semop */
+      break;
+   case 2: /* IPCOP_semget */
+   case 3: /* IPCOP_semctl */
+      break;
+   case 11: /* IPCOP_msgsnd */
+      break;
+   case 12: /* IPCOP_msgrcv */
+   {
+      struct msgbuf *msgp;
+ 
+      msgp = (struct msgbuf *)deref_Addr( tid,
+					  (Addr) (&((struct ipc_kludge *)ARG(5))->msgp),
+					  "msgrcv(msgp)" );
+      if ( RES > 0 ) {
+	 VG_TRACK( post_mem_write, (UInt)&msgp->mtype, 
+		   sizeof(msgp->mtype) );
+	 VG_TRACK( post_mem_write, (UInt)msgp->mtext, RES );
+      }
+      break;
+   }
+   case 13: /* IPCOP_msgget */
+      break;
+   case 14: /* IPCOP_msgctl */
+   {
+      switch (ARG(3) /* cmd */) {
+      case IPC_STAT:
+	 if ( RES > 0 ) {
+	    VG_TRACK( post_mem_write, ARG(5), 
+		      sizeof(struct msqid_ds) );
+	 }
+	 break;
+      case IPC_SET:
+	 break;
+#                    if defined(IPC_64)
+      case IPC_STAT|IPC_64:
+	 if ( RES > 0 ) {
+	    VG_TRACK( post_mem_write, ARG(5), 
+		      sizeof(struct msqid64_ds) );
+	 }
+	 break;
+#                    endif
+#                    if defined(IPC_64)
+      case IPC_SET|IPC_64:
+	 break;
+#                    endif
+      default:
+	 break;
+      }
+      break;
+   }
+   case 21: /* IPCOP_shmat */
+   {
+      Int shmid = ARG(2);
+      Int shmflag = ARG(3);
+      Addr addr;
+
+      /* force readability. before the syscall it is
+       * indeed uninitialized, as can be seen in
+       * glibc/sysdeps/unix/sysv/linux/shmat.c */
+      VG_TRACK( post_mem_write, ARG(4), sizeof( ULong ) );
+
+      addr = deref_Addr ( tid, ARG(4), "shmat(addr)" );
+      if ( addr > 0 ) { 
+	 UInt segmentSize = get_shm_size ( shmid );
+	 if ( segmentSize > 0 ) {
+	    UInt prot;
+	    /* we don't distinguish whether it's read-only or
+	     * read-write -- it doesn't matter really. */
+	    VG_TRACK( new_mem_mmap, addr, segmentSize, 
+		      True, True, False );
+
+	    prot = VKI_PROT_READ|VKI_PROT_WRITE;
+	    if (!(shmflag & 010000)) /* = SHM_RDONLY */
+	       prot &= ~VKI_PROT_WRITE;
+	    VG_(map_segment)(addr, segmentSize, prot,
+			     SF_SHARED | SF_SHM);
+	 }
+      }
+      break;
+   }
+   case 22: /* IPCOP_shmdt */
+   {
+      Segment *s = VG_(find_segment)(ARG(1));
+
+      if (s != NULL && (s->flags & SF_SHM) && VG_(seg_contains)(s, ARG(1), 1)) {
+	 VG_TRACK( die_mem_munmap, s->addr, s->len );
+	 VG_(unmap_range)(s->addr, s->len);
+      }
+      break;
+   }
+   case 23: /* IPCOP_shmget */
+      break;
+   case 24: /* IPCOP_shmctl */
+      /* Subject: shmctl: The True Story
+	 Date: Thu, 9 May 2002 18:07:23 +0100 (BST)
+	 From: Reuben Thomas <rrt@mupsych.org>
+	 To: Julian Seward <jseward@acm.org>
+
+	 1. As you suggested, the syscall subop is in ARG(1).
+
+	 2. There are a couple more twists, so the arg order
+	 is actually:
+
+	 ARG(1) syscall subop
+	 ARG(2) file desc
+	 ARG(3) shm operation code (can have IPC_64 set)
+	 ARG(4) 0 ??? is ARG(3)-ARG(4) a 64-bit quantity when IPC_64
+	 is defined?
+	 ARG(5) pointer to buffer
+
+	 3. With this in mind, I've amended the case as below:
+      */
+   {
+      UInt cmd = ARG(3);
+      Bool out_arg = False;
+      if ( ARG(5) ) {
+#                    if defined(IPC_64)
+	 cmd = cmd & (~IPC_64);
+#                    endif
+	 out_arg = cmd == SHM_STAT || cmd == IPC_STAT;
+      }
+      if ( ARG(5) && RES == 0 && out_arg )
+	 VG_TRACK( post_mem_write, ARG(5), 
+		   sizeof(struct shmid_ds) );
+   }
+   break;
+   default:
+      VG_(message)(Vg_DebugMsg,
+		   "FATAL: unhandled syscall(ipc) %d",
+		   ARG(1) );
+      VG_(core_panic)("... bye!\n");
+      break; /*NOTREACHED*/
+   }
+}
+
+PRE(ioctl)
+{
+   /* int ioctl(int d, int request, ...)
+      [The  "third"  argument  is traditionally char *argp, 
+      and will be so named for this discussion.]
+   */
+   /*
+     VG_(message)(
+     Vg_DebugMsg, 
+     "is an IOCTL,  request = 0x%x,   d = %d,   argp = 0x%x", 
+     ARG(2),ARG(1),ARG(3));
+   */
+   MAYBE_PRINTF("ioctl ( %d, 0x%x, %p )\n",ARG(1),ARG(2),ARG(3));
+   switch (ARG(2) /* request */) {
+   case TCSETS:
+   case TCSETSW:
+   case TCSETSF:
+      SYSCALL_TRACK( pre_mem_read, tid, "ioctl(TCSET{S,SW,SF})", ARG(3), 
+		     VKI_SIZEOF_STRUCT_TERMIOS );
+      break; 
+   case TCGETS:
+      SYSCALL_TRACK( pre_mem_write, tid, "ioctl(TCGETS)", ARG(3), 
+		     VKI_SIZEOF_STRUCT_TERMIOS );
+      break;
+   case TCSETA:
+   case TCSETAW:
+   case TCSETAF:
+      SYSCALL_TRACK( pre_mem_read, tid, "ioctl(TCSET{A,AW,AF})", ARG(3),
+		     VKI_SIZEOF_STRUCT_TERMIO );
+      break;
+   case TCGETA:
+      SYSCALL_TRACK( pre_mem_write, tid, "ioctl(TCGETA)", ARG(3),
+		     VKI_SIZEOF_STRUCT_TERMIO );
+      break;
+   case TCSBRK:
+   case TCXONC:
+   case TCSBRKP:
+   case TCFLSH:
+      /* These just take an int by value */
+      break;
+   case TIOCGWINSZ:
+      SYSCALL_TRACK( pre_mem_write, tid, "ioctl(TIOCGWINSZ)", ARG(3), 
+		     sizeof(struct winsize) );
+      break;
+   case TIOCSWINSZ:
+      SYSCALL_TRACK( pre_mem_read, tid, "ioctl(TIOCSWINSZ)", ARG(3), 
+		     sizeof(struct winsize) );
+      break;
+   case TIOCLINUX:
+      SYSCALL_TRACK( pre_mem_read, tid, "ioctl(TIOCLINUX)", ARG(3), 
+		     sizeof(char *) );
+      if (*(char *)ARG(3) == 11) {
+	 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(TIOCLINUX, 11)", 
+			ARG(3), 2 * sizeof(char *) );
+      }
+      break;
+   case TIOCGPGRP:
+      /* Get process group ID for foreground processing group. */
+      SYSCALL_TRACK( pre_mem_write, tid, "ioctl(TIOCGPGRP)", ARG(3),
+		     sizeof(pid_t) );
+      break;
+   case TIOCSPGRP:
+      /* Set a process group ID? */
+      SYSCALL_TRACK( pre_mem_write, tid, "ioctl(TIOCGPGRP)", ARG(3),
+		     sizeof(pid_t) );
+      break;
+   case TIOCGPTN: /* Get Pty Number (of pty-mux device) */
+      SYSCALL_TRACK( pre_mem_write, tid, "ioctl(TIOCGPTN)", 
+		     ARG(3), sizeof(int) );
+      break;
+   case TIOCSCTTY:
+      /* Just takes an int value.  */
+      break;
+   case TIOCSPTLCK: /* Lock/unlock Pty */
+      SYSCALL_TRACK( pre_mem_read, tid, "ioctl(TIOCSPTLCK)", 
+		     ARG(3), sizeof(int) );
+      break;
+   case FIONBIO:
+      SYSCALL_TRACK( pre_mem_read, tid, "ioctl(FIONBIO)", 
+		     ARG(3), sizeof(int) );
+      break;
+   case FIOASYNC:
+      SYSCALL_TRACK( pre_mem_read, tid, "ioctl(FIOASYNC)", 
+		     ARG(3), sizeof(int) );
+      break;
+   case FIONREAD:                /* identical to SIOCINQ */
+      SYSCALL_TRACK( pre_mem_write, tid, "ioctl(FIONREAD)", 
+		     ARG(3), sizeof(int) );
+      break;
+
+      /* If you get compilation problems here, change the #if
+	 1 to #if 0 and get rid of <scsi/sg.h> in
+	 vg_unsafe.h. */
+#       if 1
+   case SG_SET_COMMAND_Q:
+      SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SG_SET_COMMAND_Q)", 
+		     ARG(3), sizeof(int) );
+      break;
+#           if defined(SG_IO)
+   case SG_IO:
+      SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SG_IO)", ARG(3), 
+		     sizeof(struct sg_io_hdr) );
+      break;
+#           endif /* SG_IO */
+   case SG_GET_SCSI_ID:
+      /* Note: sometimes sg_scsi_id is called sg_scsi_id_t */
+      SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SG_GET_SCSI_ID)", ARG(3), 
+		     sizeof(struct sg_scsi_id) );
+      break;
+   case SG_SET_RESERVED_SIZE:
+      SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SG_SET_RESERVED_SIZE)", 
+		     ARG(3), sizeof(int) );
+      break;
+   case SG_SET_TIMEOUT:
+      SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SG_SET_TIMEOUT)", ARG(3), 
+		     sizeof(int) );
+      break;
+   case SG_GET_RESERVED_SIZE:
+      SYSCALL_TRACK( pre_mem_write, tid, 
+		     "ioctl(SG_GET_RESERVED_SIZE)", ARG(3), 
+		     sizeof(int) );
+      break;
+   case SG_GET_TIMEOUT:
+      SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SG_GET_TIMEOUT)", ARG(3), 
+		     sizeof(int) );
+      break;
+   case SG_GET_VERSION_NUM:
+      SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SG_GET_VERSION_NUM)", 
+		     ARG(3), sizeof(int) );
+      break;
+#       endif
+
+   case VKI_IIOCGETCPS:
+      /* In early 2.4 kernels, ISDN_MAX_CHANNELS was only defined
+       * when KERNEL was. I never saw a larger value than 64 though */
+#              ifndef ISDN_MAX_CHANNELS
+#              define ISDN_MAX_CHANNELS 64
+#              endif
+      SYSCALL_TRACK( pre_mem_write, tid, "ioctl(IIOCGETCPS)", ARG(3),
+		     ISDN_MAX_CHANNELS 
+		     * 2 * sizeof(unsigned long) );
+      break;
+   case VKI_IIOCNETGPN:
+      SYSCALL_TRACK( pre_mem_read, tid, "ioctl(IIOCNETGPN)",
+		     (UInt)&((isdn_net_ioctl_phone *)ARG(3))->name,
+		     sizeof(((isdn_net_ioctl_phone *)ARG(3))->name) );
+      SYSCALL_TRACK( pre_mem_write, tid, "ioctl(IIOCNETGPN)", ARG(3),
+		     sizeof(isdn_net_ioctl_phone) );
+      break;
+
+      /* These all use struct ifreq AFAIK */
+   case SIOCGIFINDEX:
+   case SIOCGIFFLAGS:        /* get flags                    */
+   case SIOCGIFHWADDR:       /* Get hardware address         */
+   case SIOCGIFMTU:          /* get MTU size                 */
+   case SIOCGIFADDR:         /* get PA address               */
+   case SIOCGIFNETMASK:      /* get network PA mask          */
+   case SIOCGIFMETRIC:       /* get metric                   */
+   case SIOCGIFMAP:          /* Get device parameters        */
+   case SIOCGIFTXQLEN:       /* Get the tx queue length      */
+   case SIOCGIFDSTADDR:      /* get remote PA address        */
+   case SIOCGIFBRDADDR:      /* get broadcast PA address     */
+   case SIOCGIFNAME:         /* get iface name               */
+      SYSCALL_TRACK( pre_mem_write,tid, "ioctl(SIOCGIFINDEX)", ARG(3), 
+		     sizeof(struct ifreq));
+      break;
+   case SIOCGIFCONF:         /* get iface list               */
+      /* WAS:
+	 SYSCALL_TRACK( pre_mem_write,"ioctl(SIOCGIFCONF)", ARG(3), 
+	 sizeof(struct ifconf));
+	 KERNEL_DO_SYSCALL(tid,res);
+	 if (!VG_(is_kerror)(res) && res == 0)
+	 VG_TRACK( post_mem_write,ARG(3), sizeof(struct ifconf));
+      */
+      SYSCALL_TRACK( pre_mem_read,tid, "ioctl(SIOCGIFCONF)", ARG(3), 
+		     sizeof(struct ifconf));
+      if ( ARG(3) ) {
+	 // TODO len must be readable and writable
+	 // buf pointer only needs to be readable
+	 struct ifconf *ifc = (struct ifconf *) ARG(3);
+	 SYSCALL_TRACK( pre_mem_write,tid, "ioctl(SIOCGIFCONF).ifc_buf",
+			(Addr)(ifc->ifc_buf), (UInt)(ifc->ifc_len) );
+      }
+      break;
+   case SIOCGSTAMP:
+      SYSCALL_TRACK( pre_mem_write,tid, "ioctl(SIOCGSTAMP)", ARG(3), 
+		     sizeof(struct timeval));
+      break;
+      /* SIOCOUTQ is an ioctl that, when called on a socket, returns
+	 the number of bytes currently in that socket's send buffer.
+	 It writes this value as an int to the memory location
+	 indicated by the third argument of ioctl(2). */
+   case SIOCOUTQ:
+      SYSCALL_TRACK( pre_mem_write,tid, "ioctl(SIOCOUTQ)", ARG(3), 
+		     sizeof(int));
+      break;
+   case SIOCGRARP:           /* get RARP table entry         */
+   case SIOCGARP:            /* get ARP table entry          */
+      SYSCALL_TRACK( pre_mem_write,tid, "ioctl(SIOCGARP)", ARG(3), 
+		     sizeof(struct arpreq));
+      break;
+                    
+   case SIOCSIFFLAGS:        /* set flags                    */
+   case SIOCSIFMAP:          /* Set device parameters        */
+   case SIOCSIFTXQLEN:       /* Set the tx queue length      */
+   case SIOCSIFDSTADDR:      /* set remote PA address        */
+   case SIOCSIFBRDADDR:      /* set broadcast PA address     */
+   case SIOCSIFNETMASK:      /* set network PA mask          */
+   case SIOCSIFMETRIC:       /* set metric                   */
+   case SIOCSIFADDR:         /* set PA address               */
+   case SIOCSIFMTU:          /* set MTU size                 */
+   case SIOCSIFHWADDR:       /* set hardware address         */
+      SYSCALL_TRACK( pre_mem_read,tid,"ioctl(SIOCSIFFLAGS)", ARG(3), 
+		     sizeof(struct ifreq));
+      break;
+      /* Routing table calls.  */
+   case SIOCADDRT:           /* add routing table entry      */
+   case SIOCDELRT:           /* delete routing table entry   */
+      SYSCALL_TRACK( pre_mem_read,tid,"ioctl(SIOCADDRT/DELRT)", ARG(3), 
+		     sizeof(struct rtentry));
+      break;
+
+      /* RARP cache control calls. */
+   case SIOCDRARP:           /* delete RARP table entry      */
+   case SIOCSRARP:           /* set RARP table entry         */
+      /* ARP cache control calls. */
+   case SIOCSARP:            /* set ARP table entry          */
+   case SIOCDARP:            /* delete ARP table entry       */
+      SYSCALL_TRACK( pre_mem_read,tid, "ioctl(SIOCSIFFLAGS)", ARG(3), 
+		     sizeof(struct ifreq));
+      break;
+
+   case SIOCSPGRP:
+      SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SIOCSPGRP)", ARG(3), 
+		     sizeof(int) );
+      break;
+
+      /* linux/soundcard interface (OSS) */
+   case SNDCTL_SEQ_GETOUTCOUNT:
+   case SNDCTL_SEQ_GETINCOUNT:
+   case SNDCTL_SEQ_PERCMODE:
+   case SNDCTL_SEQ_TESTMIDI:
+   case SNDCTL_SEQ_RESETSAMPLES:
+   case SNDCTL_SEQ_NRSYNTHS:
+   case SNDCTL_SEQ_NRMIDIS:
+   case SNDCTL_SEQ_GETTIME:
+   case SNDCTL_DSP_GETFMTS:
+   case SNDCTL_DSP_GETTRIGGER:
+   case SNDCTL_DSP_GETODELAY:
+#           if defined(SNDCTL_DSP_GETSPDIF)
+   case SNDCTL_DSP_GETSPDIF:
+#           endif
+   case SNDCTL_DSP_GETCAPS:
+   case SOUND_PCM_READ_RATE:
+   case SOUND_PCM_READ_CHANNELS:
+   case SOUND_PCM_READ_BITS:
+   case (SOUND_PCM_READ_BITS|0x40000000): /* what the fuck ? */
+   case SOUND_PCM_READ_FILTER:
+      SYSCALL_TRACK( pre_mem_write,tid,
+		     "ioctl(SNDCTL_XXX|SOUND_XXX (SIOR, int))", 
+		     ARG(3),
+		     sizeof(int));
+      break;
+   case SNDCTL_SEQ_CTRLRATE:
+   case SNDCTL_DSP_SPEED:
+   case SNDCTL_DSP_STEREO:
+   case SNDCTL_DSP_GETBLKSIZE: 
+   case SNDCTL_DSP_CHANNELS:
+   case SOUND_PCM_WRITE_FILTER:
+   case SNDCTL_DSP_SUBDIVIDE:
+   case SNDCTL_DSP_SETFRAGMENT:
+#           if defined(SNDCTL_DSP_GETCHANNELMASK)
+   case SNDCTL_DSP_GETCHANNELMASK:
+#           endif
+#           if defined(SNDCTL_DSP_BIND_CHANNEL)
+   case SNDCTL_DSP_BIND_CHANNEL:
+#           endif
+   case SNDCTL_TMR_TIMEBASE:
+   case SNDCTL_TMR_TEMPO:
+   case SNDCTL_TMR_SOURCE:
+   case SNDCTL_MIDI_PRETIME:
+   case SNDCTL_MIDI_MPUMODE:
+      SYSCALL_TRACK( pre_mem_read,tid, "ioctl(SNDCTL_XXX|SOUND_XXX "
+		     "(SIOWR, int))", 
+		     ARG(3), sizeof(int));
+      SYSCALL_TRACK( pre_mem_write,tid, "ioctl(SNDCTL_XXX|SOUND_XXX "
+		     "(SIOWR, int))", 
+		     ARG(3), sizeof(int));
+      break;
+   case SNDCTL_DSP_GETOSPACE:
+   case SNDCTL_DSP_GETISPACE:
+      SYSCALL_TRACK( pre_mem_write,tid, 
+		     "ioctl(SNDCTL_XXX|SOUND_XXX "
+		     "(SIOR, audio_buf_info))", ARG(3),
+		     sizeof(audio_buf_info));
+      break;
+   case SNDCTL_DSP_SETTRIGGER:
+      SYSCALL_TRACK( pre_mem_read,tid, 
+		     "ioctl(SNDCTL_XXX|SOUND_XXX (SIOW, int))", 
+		     ARG(3), sizeof(int));
+      break;
+
+   case SNDCTL_DSP_POST:
+   case SNDCTL_DSP_RESET:
+   case SNDCTL_DSP_SYNC:
+   case SNDCTL_DSP_SETSYNCRO:
+   case SNDCTL_DSP_SETDUPLEX:
+      break;
+
+      /* Real Time Clock (/dev/rtc) ioctls */
+#           ifndef GLIBC_2_1
+   case RTC_UIE_ON:
+   case RTC_UIE_OFF:
+   case RTC_AIE_ON:
+   case RTC_AIE_OFF:
+   case RTC_PIE_ON:
+   case RTC_PIE_OFF:
+   case RTC_IRQP_SET:
+      break;
+   case RTC_RD_TIME:
+   case RTC_ALM_READ:
+      SYSCALL_TRACK( pre_mem_write,tid, "ioctl(RTC_RD_TIME/ALM_READ)", 
+		     ARG(3), sizeof(struct rtc_time));
+      break;
+   case RTC_ALM_SET:
+      SYSCALL_TRACK( pre_mem_read,tid, "ioctl(RTC_ALM_SET)", ARG(3),
+		     sizeof(struct rtc_time));
+      break;
+   case RTC_IRQP_READ:
+      SYSCALL_TRACK( pre_mem_write,tid, "ioctl(RTC_IRQP_READ)", ARG(3),
+		     sizeof(unsigned long));
+      break;
+#           endif /* GLIBC_2_1 */
+
+#           ifdef BLKGETSIZE
+   case BLKGETSIZE:
+      SYSCALL_TRACK( pre_mem_write,tid, "ioctl(BLKGETSIZE)", ARG(3),
+		     sizeof(unsigned long));
+      break;
+#           endif /* BLKGETSIZE */
+
+      /* CD ROM stuff (??)  */
+   case CDROMSUBCHNL:
+      SYSCALL_TRACK( pre_mem_read,tid, 
+		     "ioctl(CDROMSUBCHNL (cdsc_format, char))",
+		     (int) &(((struct cdrom_subchnl *) ARG(3))->cdsc_format), 
+		     sizeof(((struct cdrom_subchnl *) ARG(3))->cdsc_format));
+      SYSCALL_TRACK( pre_mem_write,tid, 
+		     "ioctl(CDROMSUBCHNL)", ARG(3), 
+		     sizeof(struct cdrom_subchnl));
+      break;
+   case CDROMREADTOCHDR:
+      SYSCALL_TRACK( pre_mem_write,tid, 
+		     "ioctl(CDROMREADTOCHDR)", ARG(3), 
+		     sizeof(struct cdrom_tochdr));
+      break;
+   case CDROMREADTOCENTRY:
+      SYSCALL_TRACK( pre_mem_read,tid, 
+		     "ioctl(CDROMREADTOCENTRY (cdte_format, char))",
+		     (int) &(((struct cdrom_tocentry *) ARG(3))->cdte_format), 
+		     sizeof(((struct cdrom_tocentry *) ARG(3))->cdte_format));
+      SYSCALL_TRACK( pre_mem_read,tid, 
+		     "ioctl(CDROMREADTOCENTRY (cdte_track, char))",
+		     (int) &(((struct cdrom_tocentry *) ARG(3))->cdte_track), 
+		     sizeof(((struct cdrom_tocentry *) ARG(3))->cdte_track));
+      SYSCALL_TRACK( pre_mem_write,tid, 
+		     "ioctl(CDROMREADTOCENTRY)", ARG(3), 
+		     sizeof(struct cdrom_tocentry));
+      break;
+   case CDROMPLAYMSF:
+      SYSCALL_TRACK( pre_mem_read,tid, "ioctl(CDROMPLAYMSF)", ARG(3), 
+		     sizeof(struct cdrom_msf));
+      break;
+      /* The following two are probably bogus (should check args
+	 for readability).  JRS 20021117 */
+   case CDROM_DRIVE_STATUS: /* 0x5326 */
+   case CDROM_CLEAR_OPTIONS: /* 0x5321 */
+      break;
+
+      /* We don't have any specific information on it, so
+	 try to do something reasonable based on direction and
+	 size bits.  The encoding scheme is described in
+	 /usr/include/asm/ioctl.h.  
+
+	 According to Simon Hausmann, _IOC_READ means the kernel
+	 writes a value to the ioctl value passed from the user
+	 space and the other way around with _IOC_WRITE. */
+   default: {
+      UInt dir  = _IOC_DIR(ARG(2));
+      UInt size = _IOC_SIZE(ARG(2));
+      if (VG_(strstr)(VG_(clo_weird_hacks), "lax-ioctls") != NULL) {
+	 /* 
+	  * Be very lax about ioctl handling; the only
+	  * assumption is that the size is correct. Doesn't
+	  * require the full buffer to be initialized when
+	  * writing.  Without this, using some device
+	  * drivers with a large number of strange ioctl
+	  * commands becomes very tiresome.
+	  */
+      } else if (/* size == 0 || */ dir == _IOC_NONE) {
+	 static Int moans = 3;
+	 if (moans > 0) {
+	    moans--;
+	    VG_(message)(Vg_UserMsg, 
+			 "Warning: noted but unhandled ioctl 0x%x"
+			 " with no size/direction hints",
+			 ARG(2)); 
+	    VG_(message)(Vg_UserMsg, 
+			 "   This could cause spurious value errors"
+			 " to appear.");
+	    VG_(message)(Vg_UserMsg, 
+			 "   See README_MISSING_SYSCALL_OR_IOCTL for "
+			 "guidance on writing a proper wrapper." );
+	 }
+      } else {
+	 if ((dir & _IOC_WRITE) && size > 0)
+	    SYSCALL_TRACK( pre_mem_read,tid, "ioctl(generic)", 
+			   ARG(3), size);
+	 if ((dir & _IOC_READ) && size > 0)
+	    SYSCALL_TRACK( pre_mem_write,tid, "ioctl(generic)", 
+			   ARG(3), size);
+      }
+      break;
+   }
+   }   
+}
+
+POST(ioctl)
+{
+   /* int ioctl(int d, int request, ...)
+      [The  "third"  argument  is traditionally char *argp, 
+      and will be so named for this discussion.]
+   */
+   /*
+     VG_(message)(
+     Vg_DebugMsg, 
+     "is an IOCTL,  request = 0x%x,   d = %d,   argp = 0x%x", 
+     ARG(2),ARG(1),ARG(3));
+   */
+   MAYBE_PRINTF("ioctl ( %d, 0x%x, %p )\n",ARG(1),ARG(2),ARG(3));
+   switch (ARG(2) /* request */) {
+   case TCSETS:
+   case TCSETSW:
+   case TCSETSF:
+      break; 
+   case TCGETS:
+      if (RES == 0)
+	 VG_TRACK( post_mem_write, ARG(3), VKI_SIZEOF_STRUCT_TERMIOS );
+      break;
+   case TCSETA:
+   case TCSETAW:
+   case TCSETAF:
+      break;
+   case TCGETA:
+      VG_TRACK( post_mem_write, ARG(3), VKI_SIZEOF_STRUCT_TERMIO );
+      break;
+   case TCSBRK:
+   case TCXONC:
+   case TCSBRKP:
+   case TCFLSH:
+      break;
+   case TIOCGWINSZ:
+      VG_TRACK( post_mem_write, ARG(3), sizeof(struct winsize) );
+      break;
+   case TIOCSWINSZ:
+      break;
+   case TIOCLINUX:
+      VG_TRACK( post_mem_write, ARG(3), sizeof(char *) );
+      break;
+   case TIOCGPGRP:
+      /* Get process group ID for foreground processing group. */
+      VG_TRACK( post_mem_write, ARG(3), sizeof(pid_t) );
+      break;
+   case TIOCSPGRP:
+      /* Set a process group ID? */
+      VG_TRACK( post_mem_write, ARG(3), sizeof(pid_t) );
+      break;
+   case TIOCGPTN: /* Get Pty Number (of pty-mux device) */
+      VG_TRACK( post_mem_write, ARG(3), sizeof(int));
+      break;
+   case TIOCSCTTY:
+      break;
+   case TIOCSPTLCK: /* Lock/unlock Pty */
+      break;
+   case FIONBIO:
+      break;
+   case FIOASYNC:
+      break;
+   case FIONREAD:                /* identical to SIOCINQ */
+      VG_TRACK( post_mem_write, ARG(3), sizeof(int) );
+      break;
+
+      /* If you get compilation problems here, change the #if
+	 1 to #if 0 and get rid of <scsi/sg.h> in
+	 vg_unsafe.h. */
+#       if 1
+   case SG_SET_COMMAND_Q:
+      break;
+#           if defined(SG_IO)
+   case SG_IO:
+      VG_TRACK( post_mem_write,ARG(3), sizeof(struct sg_io_hdr));
+      break;
+#           endif /* SG_IO */
+   case SG_GET_SCSI_ID:
+      VG_TRACK( post_mem_write,ARG(3), sizeof(struct sg_scsi_id));
+      break;
+   case SG_SET_RESERVED_SIZE:
+      break;
+   case SG_SET_TIMEOUT:
+      break;
+   case SG_GET_RESERVED_SIZE:
+      VG_TRACK( post_mem_write,ARG(3), sizeof(int));
+      break;
+   case SG_GET_TIMEOUT:
+      VG_TRACK( post_mem_write,ARG(3), sizeof(int));
+      break;
+   case SG_GET_VERSION_NUM:
+      break;
+#       endif
+
+   case VKI_IIOCGETCPS:
+      /* In early 2.4 kernels, ISDN_MAX_CHANNELS was only defined
+       * when KERNEL was. I never saw a larger value than 64 though */
+#              ifndef ISDN_MAX_CHANNELS
+#              define ISDN_MAX_CHANNELS 64
+#              endif
+      VG_TRACK( post_mem_write, ARG(3), ISDN_MAX_CHANNELS 
+		* 2 * sizeof(unsigned long) );
+      break;
+   case VKI_IIOCNETGPN:
+      VG_TRACK( post_mem_write, ARG(3), sizeof(isdn_net_ioctl_phone) );
+      break;
+
+      /* These all use struct ifreq AFAIK */
+   case SIOCGIFINDEX:
+   case SIOCGIFFLAGS:        /* get flags                    */
+   case SIOCGIFHWADDR:       /* Get hardware address         */
+   case SIOCGIFMTU:          /* get MTU size                 */
+   case SIOCGIFADDR:         /* get PA address               */
+   case SIOCGIFNETMASK:      /* get network PA mask          */
+   case SIOCGIFMETRIC:       /* get metric                   */
+   case SIOCGIFMAP:          /* Get device parameters        */
+   case SIOCGIFTXQLEN:       /* Get the tx queue length      */
+   case SIOCGIFDSTADDR:      /* get remote PA address        */
+   case SIOCGIFBRDADDR:      /* get broadcast PA address     */
+   case SIOCGIFNAME:         /* get iface name               */
+      VG_TRACK( post_mem_write,ARG(3), sizeof(struct ifreq));
+      break;
+   case SIOCGIFCONF:         /* get iface list               */
+      /* WAS:
+	 SYSCALL_TRACK( pre_mem_write,"ioctl(SIOCGIFCONF)", ARG(3), 
+	 sizeof(struct ifconf));
+	 KERNEL_DO_SYSCALL(tid,res);
+	 if (!VG_(is_kerror)(res) && res == 0)
+	 VG_TRACK( post_mem_write,ARG(3), sizeof(struct ifconf));
+      */
+      if ( ARG(3) ) {
+	 struct ifconf *ifc = (struct ifconf *) ARG(3);
+	 if (ifc->ifc_buf != NULL)
+	    VG_TRACK( post_mem_write, (Addr)(ifc->ifc_buf), 
+		      (UInt)(ifc->ifc_len) );
+      }
+      break;
+   case SIOCGSTAMP:
+      VG_TRACK( post_mem_write,ARG(3), sizeof(struct timeval));
+      break;
+      /* SIOCOUTQ is an ioctl that, when called on a socket, returns
+	 the number of bytes currently in that socket's send buffer.
+	 It writes this value as an int to the memory location
+	 indicated by the third argument of ioctl(2). */
+   case SIOCOUTQ:
+      VG_TRACK( post_mem_write,ARG(3), sizeof(int));
+      break;
+   case SIOCGRARP:           /* get RARP table entry         */
+   case SIOCGARP:            /* get ARP table entry          */
+      VG_TRACK( post_mem_write,ARG(3), sizeof(struct arpreq));
+      break;
+                    
+   case SIOCSIFFLAGS:        /* set flags                    */
+   case SIOCSIFMAP:          /* Set device parameters        */
+   case SIOCSIFTXQLEN:       /* Set the tx queue length      */
+   case SIOCSIFDSTADDR:      /* set remote PA address        */
+   case SIOCSIFBRDADDR:      /* set broadcast PA address     */
+   case SIOCSIFNETMASK:      /* set network PA mask          */
+   case SIOCSIFMETRIC:       /* set metric                   */
+   case SIOCSIFADDR:         /* set PA address               */
+   case SIOCSIFMTU:          /* set MTU size                 */
+   case SIOCSIFHWADDR:       /* set hardware address         */
+      break;
+      /* Routing table calls.  */
+   case SIOCADDRT:           /* add routing table entry      */
+   case SIOCDELRT:           /* delete routing table entry   */
+      break;
+
+      /* RARP cache control calls. */
+   case SIOCDRARP:           /* delete RARP table entry      */
+   case SIOCSRARP:           /* set RARP table entry         */
+      /* ARP cache control calls. */
+   case SIOCSARP:            /* set ARP table entry          */
+   case SIOCDARP:            /* delete ARP table entry       */
+      break;
+
+   case SIOCSPGRP:
+      break;
+
+      /* linux/soundcard interface (OSS) */
+   case SNDCTL_SEQ_GETOUTCOUNT:
+   case SNDCTL_SEQ_GETINCOUNT:
+   case SNDCTL_SEQ_PERCMODE:
+   case SNDCTL_SEQ_TESTMIDI:
+   case SNDCTL_SEQ_RESETSAMPLES:
+   case SNDCTL_SEQ_NRSYNTHS:
+   case SNDCTL_SEQ_NRMIDIS:
+   case SNDCTL_SEQ_GETTIME:
+   case SNDCTL_DSP_GETFMTS:
+   case SNDCTL_DSP_GETTRIGGER:
+   case SNDCTL_DSP_GETODELAY:
+#           if defined(SNDCTL_DSP_GETSPDIF)
+   case SNDCTL_DSP_GETSPDIF:
+#           endif
+   case SNDCTL_DSP_GETCAPS:
+   case SOUND_PCM_READ_RATE:
+   case SOUND_PCM_READ_CHANNELS:
+   case SOUND_PCM_READ_BITS:
+   case (SOUND_PCM_READ_BITS|0x40000000): /* what the fuck ? */
+   case SOUND_PCM_READ_FILTER:
+      VG_TRACK( post_mem_write,ARG(3), sizeof(int));
+      break;
+   case SNDCTL_SEQ_CTRLRATE:
+   case SNDCTL_DSP_SPEED:
+   case SNDCTL_DSP_STEREO:
+   case SNDCTL_DSP_GETBLKSIZE: 
+   case SNDCTL_DSP_CHANNELS:
+   case SOUND_PCM_WRITE_FILTER:
+   case SNDCTL_DSP_SUBDIVIDE:
+   case SNDCTL_DSP_SETFRAGMENT:
+#           if defined(SNDCTL_DSP_GETCHANNELMASK)
+   case SNDCTL_DSP_GETCHANNELMASK:
+#           endif
+#           if defined(SNDCTL_DSP_BIND_CHANNEL)
+   case SNDCTL_DSP_BIND_CHANNEL:
+#           endif
+   case SNDCTL_TMR_TIMEBASE:
+   case SNDCTL_TMR_TEMPO:
+   case SNDCTL_TMR_SOURCE:
+   case SNDCTL_MIDI_PRETIME:
+   case SNDCTL_MIDI_MPUMODE:
+      break;
+   case SNDCTL_DSP_GETOSPACE:
+   case SNDCTL_DSP_GETISPACE:
+      VG_TRACK( post_mem_write,ARG(3), sizeof(audio_buf_info));
+      break;
+   case SNDCTL_DSP_SETTRIGGER:
+      break;
+
+   case SNDCTL_DSP_POST:
+   case SNDCTL_DSP_RESET:
+   case SNDCTL_DSP_SYNC:
+   case SNDCTL_DSP_SETSYNCRO:
+   case SNDCTL_DSP_SETDUPLEX:
+      break;
+
+      /* Real Time Clock (/dev/rtc) ioctls */
+#           ifndef GLIBC_2_1
+   case RTC_UIE_ON:
+   case RTC_UIE_OFF:
+   case RTC_AIE_ON:
+   case RTC_AIE_OFF:
+   case RTC_PIE_ON:
+   case RTC_PIE_OFF:
+   case RTC_IRQP_SET:
+      break;
+   case RTC_RD_TIME:
+   case RTC_ALM_READ:
+      VG_TRACK( post_mem_write,ARG(3), sizeof(struct rtc_time));
+      break;
+   case RTC_ALM_SET:
+      break;
+   case RTC_IRQP_READ:
+      VG_TRACK( post_mem_write,ARG(3), sizeof(unsigned long));
+      break;
+#           endif /* GLIBC_2_1 */
+
+#           ifdef BLKGETSIZE
+   case BLKGETSIZE:
+      VG_TRACK( post_mem_write,ARG(3), sizeof(unsigned long));
+      break;
+#           endif /* BLKGETSIZE */
+
+      /* CD ROM stuff (??)  */
+   case CDROMSUBCHNL:
+      VG_TRACK( post_mem_write,ARG(3), sizeof(struct cdrom_subchnl));
+      break;
+   case CDROMREADTOCHDR:
+      VG_TRACK( post_mem_write,ARG(3), sizeof(struct cdrom_tochdr));
+      break;
+   case CDROMREADTOCENTRY:
+      VG_TRACK( post_mem_write,ARG(3), sizeof(struct cdrom_tochdr));
+      break;
+   case CDROMPLAYMSF:
+      break;
+      /* The following two are probably bogus (should check args
+	 for readability).  JRS 20021117 */
+   case CDROM_DRIVE_STATUS: /* 0x5326 */
+   case CDROM_CLEAR_OPTIONS: /* 0x5321 */
+      break;
+
+      /* We don't have any specific information on it, so
+	 try to do something reasonable based on direction and
+	 size bits.  The encoding scheme is described in
+	 /usr/include/asm/ioctl.h.  
+
+	 According to Simon Hausmann, _IOC_READ means the kernel
+	 writes a value to the ioctl value passed from the user
+	 space and the other way around with _IOC_WRITE. */
+   default: {
+      UInt dir  = _IOC_DIR(ARG(2));
+      UInt size = _IOC_SIZE(ARG(2));
+      if (size > 0 && (dir & _IOC_READ)
+	  && ARG(3) != (Addr)NULL)
+	 VG_TRACK( post_mem_write,ARG(3), size);
+      break;
+   }
+   }
+}
+
+PRE(mmap2)
+{
+   /* My impression is that this is exactly like __NR_mmap 
+      except that all 6 args are passed in regs, rather than in 
+      a memory-block.
+      
+      Almost.  The big difference is that the file offset is specified
+      in pagesize units rather than bytes, so that it can be used for
+      files bigger than 2^32 bytes. - JSGF
+   */
+   /* void* mmap(void *start, size_t length, int prot, 
+      int flags, int fd, off_t offset); 
+   */
+   MAYBE_PRINTF("mmap2 ( %p, %d, %d, %d, %d, %d )\n",
+		ARG(1), ARG(2), ARG(3), ARG(4), ARG(5), ARG(6) );
+
+   if (ARG(4) & VKI_MAP_FIXED) {
+      if (!valid_client_addr(ARG(1), ARG(2), tid, "mmap2"))
+	 SETERROR(tst, VKI_ENOMEM);
+   } else {
+      SETARG(1, VG_(find_map_space)(ARG(1), ARG(2), True));
+      if (ARG(1) == 0)
+	 SETERROR(tst, VKI_ENOMEM);
+      SETARG(4, ARG(4) | VKI_MAP_FIXED);
+   }
+}
+
+POST(mmap2)
+{
+   if (!valid_client_addr(RES, ARG(2), tid, "mmap2")) {
+      VG_(munmap)((void *)RES, ARG(2));
+      SETERROR(tst, VKI_ENOMEM);
+   } else
+      mmap_segment( (Addr)RES, ARG(2), ARG(3), ARG(4), ARG(5), 
+		    ARG(6) * (ULong)VKI_BYTES_PER_PAGE );
+}
+
+PRE(mmap)
+{
+   /* void* mmap(void *start, size_t length, int prot, 
+      int flags, int fd, off_t offset); 
+   */
+
+   UInt* arg_block = (UInt*)ARG(1);
+   UInt a1, a2, a3, a4, a5, a6;
+
+   SYSCALL_TRACK( pre_mem_read, tid, "mmap(args)", ARG(1), 6*sizeof(UInt) );
+
+   a1 = arg_block[0];
+   a2 = arg_block[1];
+   a3 = arg_block[2];
+   a4 = arg_block[3];
+   a5 = arg_block[4];
+   a6 = arg_block[5];
+   MAYBE_PRINTF("mmap ( %p, %d, %d, %d, %d, %d )\n",
+		a1, a2, a3, a4, a5, a6 );
+
+   if (a4 & VKI_MAP_FIXED) {
+      if (!valid_client_addr(a1, a2, tid, "mmap")) {
+	 MAYBE_PRINTF("mmap failing: %p-%p\n", a1, a1+a2);
+	 SETERROR(tst, VKI_ENOMEM);
+      }
+   } else {
+      a1 = VG_(find_map_space)(arg_block[0], arg_block[1], True);
+      if (a1 == 0)
+	 SETERROR(tst, VKI_ENOMEM);
+      else
+	 a4 |= VKI_MAP_FIXED;
+   }
+
+   if (RES != -VKI_ENOMEM) {
+      UInt new_arg_block[6];
+
+      new_arg_block[0] = a1;
+      new_arg_block[1] = a2;
+      new_arg_block[2] = a3;
+      new_arg_block[3] = a4;
+      new_arg_block[4] = a5;
+      new_arg_block[5] = a6;
+      
+      RES = VG_(do_syscall)(__NR_mmap, new_arg_block);
+
+      if (!VG_(is_kerror)(RES)) {
+         if (!valid_client_addr(RES, a2, tid, "mmap")) {
+	    VG_(munmap)((void *)RES, a2);
+	    SETERROR(tst, VKI_ENOMEM);
+         } else
+	    mmap_segment( (Addr)RES, a2, a3, a4, a5, a6 );
+      }
+   }
+}
+
+PRE(mprotect)
+{
+   /* int mprotect(const void *addr, size_t len, int prot); */
+   /* should addr .. addr+len-1 be checked before the call? */
+   MAYBE_PRINTF("mprotect ( %p, %d, %d )\n", ARG(1),ARG(2),ARG(3));
+
+   if (!valid_client_addr(ARG(1), ARG(2), tid, "mprotect"))
+      SETERROR(tst, VKI_ENOMEM);
+}
+
+POST(mprotect)
+{
+   mprotect_segment( ARG(1), ARG(2), ARG(3) );
+}
+
+PRE(munmap)
+{
+   /* int munmap(void *start, size_t length); */
+   /* should start .. start+length-1 be checked before the call? */
+   MAYBE_PRINTF("munmap ( %p, %d )\n", ARG(1),ARG(2));
+
+   if (!valid_client_addr(ARG(1), ARG(2), tid, "munmap"))
+      SETERROR(tst, VKI_EINVAL);
+}
+
+POST(munmap)
+{
+   munmap_segment( ARG(1), ARG(2) );
+}
+
+PRE(mincore)
+{
+   /* int mincore(void *start, size_t length, unsigned char *vec); */
+   MAYBE_PRINTF("mincore ( %p, %d, %p )\n", ARG(1),ARG(2),ARG(3));
+   SYSCALL_TRACK(pre_mem_write, tid, "mincore(vec)",
+                 ARG(3), (ARG(2) + 4096 - 1) / 4096);
+}
+
+POST(mincore)
+{
+   if (!VG_(is_kerror)(RES))
+      VG_TRACK( post_mem_write, ARG(3), (ARG(2) + 4096 - 1) / 4096 );  
+}
+
+PRE(nanosleep)
+{
+         /* int nanosleep(const struct timespec *req, struct timespec *rem); */
+         MAYBE_PRINTF("nanosleep ( %p, %p )\n", ARG(1),ARG(2));
+         SYSCALL_TRACK( pre_mem_read, tid, "nanosleep(req)", ARG(1), 
+                                              sizeof(struct timespec) );
+         if (ARG(2) != (UInt)NULL)
+            SYSCALL_TRACK( pre_mem_write, tid, "nanosleep(rem)", ARG(2), 
+			   sizeof(struct timespec) );
+}
+
+POST(nanosleep)
+{
+   /* Somewhat bogus ... is only written by the kernel if
+      res == -1 && errno == EINTR. */
+   if (ARG(2) != (UInt)NULL)
+      VG_TRACK( post_mem_write, ARG(2), sizeof(struct timespec) );
+}
+
+PRE(_newselect)
+{
+   /* int select(int n,  
+		 fd_set *readfds, fd_set *writefds, fd_set *exceptfds, 
+		 struct timeval *timeout);
+   */
+   MAYBE_PRINTF("newselect ( %d, %p, %p, %p, %p )\n",
+		ARG(1),ARG(2),ARG(3),ARG(4),ARG(5));
+   if (ARG(2) != 0)
+      SYSCALL_TRACK( pre_mem_read, tid, "newselect(readfds)",   
+		     ARG(2), ARG(1)/8 /* __FD_SETSIZE/8 */ );
+   if (ARG(3) != 0)
+      SYSCALL_TRACK( pre_mem_read, tid, "newselect(writefds)",  
+		     ARG(3), ARG(1)/8 /* __FD_SETSIZE/8 */ );
+   if (ARG(4) != 0)
+      SYSCALL_TRACK( pre_mem_read, tid, "newselect(exceptfds)", 
+		     ARG(4), ARG(1)/8 /* __FD_SETSIZE/8 */ );
+   if (ARG(5) != 0)
+      SYSCALL_TRACK( pre_mem_read, tid, "newselect(timeout)", ARG(5), 
+		     sizeof(struct timeval) );
+}
+
+PRE(open)
+{
+   /* int open(const char *pathname, int flags); */
+   MAYBE_PRINTF("open ( %p(%s), %d ) --> ",ARG(1),ARG(1),ARG(2));
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "open(pathname)", ARG(1) );
+}
+
+POST(open)
+{
+   if (!fd_allowed(RES, "open", tid)) {
+      VG_(close)(RES);
+      SETERROR(tst, VKI_EMFILE);
+   } else {
+      if(VG_(clo_track_fds))
+         record_fd_open(tid, RES, VG_(arena_strdup)(VG_AR_CORE, (Char*)ARG(1)));
+   }
+   MAYBE_PRINTF("%d\n",RES);
+}
+
+PRE(read)
+{
+   /* size_t read(int fd, void *buf, size_t count); */
+   MAYBE_PRINTF("read ( %d, %p, %d )\n", ARG(1), ARG(2), ARG(3));
+
+   if (!fd_allowed(ARG(1), "read", tid))
+      SETERROR(tst, VKI_EBADF);   
+}
+
+POST(read)
+{
+   VG_TRACK(post_mem_write, ARG(2), RES);
+}
+
+PRE(write)
+{
+   /* size_t write(int fd, const void *buf, size_t count); */
+   MAYBE_PRINTF("write ( %d, %p, %d )\n", ARG(1), ARG(2), ARG(3));
+   if (!fd_allowed(ARG(1), "write", tid))
+      SETERROR(tst, VKI_EBADF);
+   else
+      SYSCALL_TRACK( pre_mem_read, tid, "write(buf)", ARG(2), ARG(3) );
+}
+
+PRE(creat)
+{
+   /* int creat(const char *pathname, mode_t mode); */
+   MAYBE_PRINTF("creat ( %p(%s), %d ) --> ",ARG(1),ARG(1),ARG(2));
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "creat(pathname)", ARG(1) );
+}
+
+POST(creat)
+{
+   if (!fd_allowed(RES, "creat", tid)) {
+      VG_(close)(RES);
+      SETERROR(tst, VKI_EMFILE);
+   } else {
+      if(VG_(clo_track_fds))
+         record_fd_open(tid, RES, VG_(arena_strdup)(VG_AR_CORE, (Char*)ARG(1)));
+   }
+   MAYBE_PRINTF("%d\n",RES);
+}
+
+PRE(rename)
+{
+   /* int rename(const char *oldpath, const char *newpath); */
+   MAYBE_PRINTF("rename ( %p, %p )\n", ARG(1), ARG(2) );
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "rename(oldpath)", ARG(1) );
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "rename(newpath)", ARG(2) );
+}
+
+PRE(rmdir)
+{
+   /* int rmdir(const char *pathname); */
+   MAYBE_PRINTF("rmdir ( %p )\n", ARG(1));
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "rmdir(pathname)", ARG(1) );
+}
+
+PRE(sched_setparam)
+{
+   /* int sched_setparam(pid_t pid, const struct sched_param *p); */
+   MAYBE_PRINTF("sched_setparam ( %d, %p )\n", ARG(1), ARG(2) );
+   SYSCALL_TRACK( pre_mem_read, tid, "sched_setparam(ptr)",
+		  ARG(2), sizeof(struct sched_param) );
+}
+
+POST(sched_setparam)
+{
+   VG_TRACK( post_mem_write, ARG(2), sizeof(struct sched_param) );
+}
+
+PRE(sched_getparam)
+{
+   /* int sched_getparam(pid_t pid, struct sched_param *p); */
+   MAYBE_PRINTF("sched_getparam ( %d, %p )\n", ARG(1), ARG(2) );
+   SYSCALL_TRACK( pre_mem_write, tid, "sched_getparam(ptr)",
+		  ARG(2), sizeof(struct sched_param) );
+}
+
+POST(sched_getparam)
+{
+   VG_TRACK( post_mem_write, ARG(2), sizeof(struct sched_param) );
+}
+
+PRE(sched_yield)
+{
+   /* int sched_yield(void); */
+   MAYBE_PRINTF("sched_yield ()\n" );
+}
+
+
+PRE(setitimer)
+{
+         /* setitimer(int which, const struct itimerval *value,
+                                 struct itimerval *ovalue); */
+         MAYBE_PRINTF("setitimer ( %d, %p, %p )\n", ARG(1),ARG(2),ARG(3));
+         if (ARG(2) != (Addr)NULL)
+            SYSCALL_TRACK( pre_mem_read,tid, "setitimer(value)", 
+                             ARG(2), sizeof(struct itimerval) );
+         if (ARG(3) != (Addr)NULL)
+            SYSCALL_TRACK( pre_mem_write,tid, "setitimer(ovalue)", 
+                             ARG(3), sizeof(struct itimerval));
+}
+
+POST(setitimer)
+{
+   if (ARG(3) != (Addr)NULL) {
+      VG_TRACK( post_mem_write,ARG(3), sizeof(struct itimerval));
+   }
+}
+
+PRE(setfsgid32)
+{
+   /* int setfsgid(uid_t fsgid); */
+   MAYBE_PRINTF("setfsgid ( %d )\n", ARG(1));
+}
+
+PRE(setgid)
+{
+   /* int setgid(gid_t gid); */
+   MAYBE_PRINTF("setgid ( %d )\n", ARG(1));
+}
+
+PREALIAS(setgid32, setgid);
+
+PRE(setsid)
+{
+   /* pid_t setsid(void); */
+   MAYBE_PRINTF("setsid ()\n");
+}
+
+PRE(setgroups)
+{
+   /* int setgroups(size_t size, const gid_t *list); */
+   MAYBE_PRINTF("setgroups ( %d, %p )\n", ARG(1), ARG(2));
+   if (ARG(1) > 0)
+      SYSCALL_TRACK( pre_mem_read, tid, "setgroups(list)", ARG(2), 
+		     ARG(1) * sizeof(gid_t) );
+}
+
+PREALIAS(setgroups32, setgroups);
+
+PRE(setpgid)
+{
+   /* int setpgid(pid_t pid, pid_t pgid); */
+   MAYBE_PRINTF("setpgid ( %d, %d )\n", ARG(1), ARG(2));
+}
+
+POST(setpgid)
+{
+   VG_(main_pgrp) = VG_(getpgrp)();
+}
+
+PRE(setregid32)
+{
+   /* int setregid(gid_t rgid, gid_t egid); */
+   MAYBE_PRINTF("setregid32(?) ( %d, %d )\n", ARG(1), ARG(2));
+}
+
+PRE(setresuid32)
+{
+   /* int setresuid(uid_t ruid, uid_t euid, uid_t suid); */
+   MAYBE_PRINTF("setresuid32(?) ( %d, %d, %d )\n", ARG(1), ARG(2), ARG(3));
+}
+
+PRE(setreuid)
+{
+   /* int setreuid(uid_t ruid, uid_t euid); */
+   MAYBE_PRINTF("setreuid ( 0x%x, 0x%x )\n", ARG(1), ARG(2));
+}
+
+PREALIAS(setreuid32, setreuid);
+
+PRE(setrlimit)
+{
+   /* int setrlimit (int resource, const struct rlimit *rlim); */
+   MAYBE_PRINTF("setrlimit ( %d, %p )\n", ARG(1),ARG(2));
+   SYSCALL_TRACK( pre_mem_read, tid, "setrlimit(rlim)", 
+		  ARG(2), sizeof(struct rlimit) );
+}
+
+PRE(setuid)
+{
+   /* int setuid(uid_t uid); */
+   MAYBE_PRINTF("setuid ( %d )\n", ARG(1));
+}
+PREALIAS(setuid32, setuid);
+
+PRE(set_thread_area)
+{
+   MAYBE_PRINTF("set_thread_area ( %p )\n", ARG(1));
+
+   SYSCALL_TRACK( pre_mem_read, tid, 
+		  "set_thread_area(ptr)", ARG(1), 
+		  sizeof(struct vki_modify_ldt_ldt_s) );
+
+   /* "do" the syscall ourselves; the kernel never sees it */
+   RES = VG_(sys_set_thread_area)( tid, (void *)ARG(1) );
+}
+
+PRE(get_thread_area)
+{
+   MAYBE_PRINTF("get_thread_area ( %p )\n", ARG(1));
+   SYSCALL_TRACK( pre_mem_write, tid, 
+		  "get_thread_area(ptr)", ARG(1), 
+		  sizeof(struct vki_modify_ldt_ldt_s) );
+
+   /* "do" the syscall ourselves; the kernel never sees it */
+   RES = VG_(sys_get_thread_area)( tid, (void *)ARG(1) );
+
+   if (!VG_(is_kerror)(RES)) {
+      VG_TRACK( post_mem_write, ARG(1), sizeof(struct vki_modify_ldt_ldt_s) );
+   }
+}
+
+PRE(stat)
+{
+   /* int stat(const char *file_name, struct stat *buf); */
+   MAYBE_PRINTF("stat ( %p, %p )\n",ARG(1),ARG(2));
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "stat(file_name)", ARG(1) );
+   SYSCALL_TRACK( pre_mem_write, tid, "stat(buf)", 
+		  ARG(2), sizeof(struct vki_stat) );
+}
+
+POST(stat)
+{
+   VG_TRACK( post_mem_write, ARG(2), sizeof(struct vki_stat) );
+}
+
+PRE(statfs)
+{
+   /* int statfs(const char *path, struct statfs *buf); */
+   MAYBE_PRINTF("statfs ( %p, %p )\n",ARG(1),ARG(2));
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "statfs(path)", ARG(1) );
+   SYSCALL_TRACK( pre_mem_write, tid, "statfs(buf)", 
+		  ARG(2), sizeof(struct statfs) );
+}
+
+POST(statfs)
+{
+   VG_TRACK( post_mem_write, ARG(2), sizeof(struct statfs) );
+}
+
+PRE(symlink)
+{
+   /* int symlink(const char *oldpath, const char *newpath); */
+   MAYBE_PRINTF("symlink ( %p, %p )\n",ARG(1),ARG(2));
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "symlink(oldpath)", ARG(1) );
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "symlink(newpath)", ARG(2) );
+}
+
+PRE(sysinfo)
+{
+   /* int sysinfo(struct sysinfo *info); */
+   MAYBE_PRINTF("sysinfo ( %p )\n",ARG(1));
+   SYSCALL_TRACK( pre_mem_write, tid, "sysinfo(info)", 
+		  ARG(1), sizeof(struct sysinfo) );
+}
+
+POST(sysinfo)
+{
+   VG_TRACK( post_mem_write, ARG(1), sizeof(struct sysinfo) );
+}
+
+PRE(time)
+{
+   /* time_t time(time_t *t); */
+   MAYBE_PRINTF("time ( %p )\n",ARG(1));
+   if (ARG(1) != (UInt)NULL) {
+      SYSCALL_TRACK( pre_mem_write, tid, "time", ARG(1), sizeof(time_t) );
+   }
+}
+
+POST(time)
+{
+   if (ARG(1) != (UInt)NULL) {
+      VG_TRACK( post_mem_write, ARG(1), sizeof(time_t) );
+   }
+}
+
+PRE(times)
+{
+   /* clock_t times(struct tms *buf); */
+   MAYBE_PRINTF("times ( %p )\n",ARG(1));
+   SYSCALL_TRACK( pre_mem_write, tid, "times(buf)", 
+		  ARG(1), sizeof(struct tms) );
+}
+
+POST(times)
+{
+   if (ARG(1) != (UInt)NULL) {
+      VG_TRACK( post_mem_write, ARG(1), sizeof(struct tms) );
+   }
+}
+
+PRE(truncate)
+{
+   /* int truncate(const char *path, size_t length); */
+   MAYBE_PRINTF("truncate ( %p \"%s\", %d )\n", ARG(1),ARG(1),ARG(2));
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "truncate(path)", ARG(1) );
+}
+
+PRE(umask)
+{
+   /* mode_t umask(mode_t mask); */
+   MAYBE_PRINTF("umask ( %d )\n", ARG(1));
+}
+
+PRE(unlink)
+{
+   /* int unlink(const char *pathname) */
+   MAYBE_PRINTF("unlink ( %p \"%s\" )\n",ARG(1), ARG(1));
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "unlink(pathname)", ARG(1) );
+}
+
+PRE(uname)
+{
+   /* int uname(struct utsname *buf); */
+   MAYBE_PRINTF("uname ( %p )\n",ARG(1));
+   SYSCALL_TRACK( pre_mem_write, tid, "uname(buf)", 
+		  ARG(1), sizeof(struct utsname) );
+}
+
+POST(uname)
+{
+   if (ARG(1) != (UInt)NULL) {
+      VG_TRACK( post_mem_write, ARG(1), sizeof(struct utsname) );
+   }
+}
+
+PRE(waitpid)
+{
+   /* pid_t waitpid(pid_t pid, int *status, int options); */
+
+   MAYBE_PRINTF("waitpid ( %d, %p, %d )\n",
+                ARG(1),ARG(2),ARG(3));
+   if (ARG(2) != (Addr)NULL)
+      SYSCALL_TRACK( pre_mem_write, tid, "waitpid(status)",
+                     ARG(2), sizeof(int) );
+}
+
+POST(waitpid)
+{
+   if (ARG(2) != (Addr)NULL)
+      VG_TRACK( post_mem_write, ARG(2), sizeof(int) );
+}
+
+PRE(wait4)
+{
+   /* pid_t wait4(pid_t pid, int *status, int options,
+      struct rusage *rusage) */
+   MAYBE_PRINTF("wait4 ( %d, %p, %d, %p )\n",
+		ARG(1),ARG(2),ARG(3),ARG(4));
+   SETARG(3, ARG(3) & ~(VKI__WCLONE | VKI__WALL));
+
+   if (ARG(2) != (Addr)NULL)
+      SYSCALL_TRACK( pre_mem_write, tid, "wait4(status)", 
+		     ARG(2), sizeof(int) );
+   if (ARG(4) != (Addr)NULL)
+      SYSCALL_TRACK( pre_mem_write, tid, "wait4(rusage)", ARG(4), 
+		     sizeof(struct rusage) );
+}
+
+POST(wait4)
+{
+   if (ARG(2) != (Addr)NULL)
+      VG_TRACK( post_mem_write, ARG(2), sizeof(int) );
+   if (ARG(4) != (Addr)NULL)
+      VG_TRACK( post_mem_write, ARG(4), sizeof(struct rusage) );
+}
+
+PRE(writev)
+{
+   /* int writev(int fd, const struct iovec * vector, size_t count); */
+   Int i;
+   struct iovec * vec;
+   MAYBE_PRINTF("writev ( %d, %p, %d )\n",ARG(1),ARG(2),ARG(3));
+   if (!fd_allowed(ARG(1), "writev", tid)) {
+      SETERROR(tst, VKI_EBADF);
+   } else {
+      SYSCALL_TRACK( pre_mem_read, tid, "writev(vector)", 
+		     ARG(2), ARG(3) * sizeof(struct iovec) );
+      /* ToDo: don't do any of the following if the vector is invalid */
+      vec = (struct iovec *)ARG(2);
+      for (i = 0; i < (Int)ARG(3); i++)
+	 SYSCALL_TRACK( pre_mem_read, tid, "writev(vector[...])",
+			(UInt)vec[i].iov_base,vec[i].iov_len );
+   }
+}
+
+PRE(prctl)
+{
+   /* int prctl(int option, unsigned long ARG(2), unsigned long ARG(3),
+      unsigned long ARG(4), unsigned long ARG(5)); */
+   MAYBE_PRINTF( "prctl ( %d, %d, %d, %d, %d )\n", ARG(1), ARG(2), ARG(3),
+		 ARG(4), ARG(5) );
+}
+
+PRE(clock_gettime)
+{
+    /* int clock_gettime(clockid_t clk_id, struct timespec *tp); */
+    MAYBE_PRINTF("clock_gettime(%d, %p)\n" ,ARG(1),ARG(2));
+    SYSCALL_TRACK(pre_mem_write, tid, "clock_gettime(tp)",
+                   ARG(2), sizeof(struct timespec));
+}
+
+POST(clock_gettime)
+{
+   VG_TRACK( post_mem_write, ARG(2), sizeof(struct timespec) );
+}
+
+PRE(utimes)
+{
+    /* int utimes(const char *filename, struct timeval *tvp); */
+    MAYBE_PRINTF("utimes ( %p, %p )\n", ARG(1),ARG(2));
+    SYSCALL_TRACK( pre_mem_read_asciiz, tid, "utimes(filename)", ARG(1) );
+    if (ARG(2) != (UInt)NULL)
+         SYSCALL_TRACK( pre_mem_read, tid, "utimes(tvp)", ARG(2),
+                       sizeof(struct timeval) );
+}
+
+PREALIAS(rt_sigsuspend, sigsuspend);
+
+PREALIAS(rt_sigaction, sigaction);
+POSTALIAS(rt_sigaction, sigaction);
+
+PREALIAS(rt_sigprocmask, sigprocmask);
+POSTALIAS(rt_sigprocmask, sigprocmask);
+
+PRE(sigpending)
+{
+   /* int sigpending( sigset_t *set ) ; */
+   MAYBE_PRINTF( "sigpending ( %p )\n", ARG(1) );
+   SYSCALL_TRACK( pre_mem_write, tid, "sigpending(set)", 
+		  ARG(1), sizeof(vki_ksigset_t));
+}
+
+POST(sigpending)
+{
+   VG_TRACK( post_mem_write, ARG(1), sizeof( vki_ksigset_t ) ) ;
+}
+
+PREALIAS(rt_sigpending, sigpending);
+POSTALIAS(rt_sigpending, sigpending);
+
+
+#undef SYSNO
+#undef RES
+#undef ARG
+
+#define SYSB_(name, blk)	[__NR_##name] = { blk, before_##name, NULL }
+#define SYSBA(name, blk)	[__NR_##name] = { blk, before_##name, after_##name }
+
+static const struct sys_info special_sys[] = {
+   /* special */
+   SYSB_(exit_group,		False),
+   SYSB_(exit,			False),
+   SYSB_(clone,			False),
+
+   SYSB_(modify_ldt,		False),
+   SYSB_(set_thread_area,	False),
+   SYSB_(get_thread_area,	False),
+
+   SYSB_(execve,		False),
+   SYSB_(brk,			False),
+   SYSB_(mmap,			False),
+   SYSB_(mremap,		False),
+
+   SYSBA(sigaltstack,		False),
+   SYSBA(rt_sigaction,		False),
+   SYSBA(sigaction,		False),
+   SYSBA(rt_sigprocmask,	False),
+   SYSBA(sigprocmask,		False),
+};
+#define MAX_SPECIAL_SYS		(sizeof(special_sys)/sizeof(special_sys[0]))
+
+static const struct sys_info sys_info[] = {
+   SYSBA(ptrace,		False),
+   SYSB_(mount,			True),
+   SYSB_(umount,		False),
+
+   SYSB_(setresgid,		False),
+   SYSB_(vhangup,		False),
+   SYSB_(iopl,			False),
+
+   SYSB_(setxattr,		True),
+   SYSB_(lsetxattr,		True),
+   SYSB_(fsetxattr,		True),
+   SYSBA(getxattr,		True),
+   SYSBA(lgetxattr,		True),
+   SYSBA(fgetxattr,		True),
+   SYSBA(listxattr,		True),
+   SYSBA(llistxattr,		True),
+   SYSBA(flistxattr,		True),
+   SYSB_(removexattr,		True),
+   SYSB_(lremovexattr,		True),
+   SYSB_(fremovexattr,		True),
+
+   SYSB_(quotactl,		False),
+   SYSBA(lookup_dcookie,	False),
+
+   SYSB_(truncate64,		True),
+   SYSB_(fdatasync,		True),
+   SYSB_(msync,			True),
+
+   SYSBA(getpmsg,		True),
+   SYSB_(putpmsg,		True),
+
+   SYSBA(syslog,		True),
+   SYSB_(personality,		False),
+   SYSB_(chroot,		False),
+   SYSB_(madvise,		True),
+   SYSB_(nice,			False),
+   SYSB_(setresgid32,		False),
+   SYSB_(setfsuid32,		False),
+   SYSBA(_sysctl,		False),
+
+   SYSB_(sched_getscheduler,	False),	/* ??? */
+   SYSB_(sched_setscheduler,	False),	/* ??? */
+
+   SYSB_(mlock,			True),
+   SYSB_(munlock,		True),
+   SYSB_(mlockall,		True),
+   SYSB_(munlockall,		True),
+
+   SYSB_(sched_get_priority_max,	False),	/* ??? */
+   SYSB_(sched_get_priority_min,	False),	/* ??? */
+
+   SYSB_(setpriority,		False),
+   SYSB_(getpriority,		False),
+
+   SYSB_(setfsgid,		False),
+   SYSB_(setregid,		False),
+   SYSB_(setresuid,		False),
+   SYSB_(setfsuid,		False),
+
+   SYSBA(sendfile,		True),
+   SYSBA(sendfile64,		True),
+   SYSB_(pwrite64,		True),
+   SYSB_(sync,			True),
+   SYSBA(fstatfs,		False),
+   SYSB_(getsid,		False),
+   SYSBA(pread64,		True),
+   SYSB_(mknod,			False),
+   SYSB_(flock,			True),
+   SYSB_(init_module,		True),
+   SYSB_(ioperm,		False),
+   SYSBA(capget,		False),
+   SYSB_(capset,		False),
+   SYSB_(access,		False),
+   SYSB_(chdir,			False),
+   SYSB_(chmod,			False),
+   SYSB_(chown32,		False),
+   SYSB_(lchown32,		False),
+   SYSB_(chown,			False),
+   SYSBA(close,			False),
+   SYSBA(dup,			False),
+   SYSBA(dup2,			False),
+   SYSBA(fcntl,			True),
+   SYSB_(fchdir,		False),
+   SYSB_(fchown32,		False),
+   SYSB_(fchown,		False),
+   SYSB_(fchmod,		False),
+   SYSBA(fcntl64,		True),
+   SYSBA(fstat,			False),
+   SYSBA(fork,			False),
+   SYSB_(fsync,			True),
+   SYSB_(ftruncate,		True),
+   SYSB_(ftruncate64,		True),
+   SYSBA(getdents,		True),
+   SYSBA(getdents64,		True),
+   SYSBA(getgroups32,		True),
+   SYSBA(getgroups,		False),
+   SYSBA(getcwd,		False),
+   SYSB_(geteuid,		False),
+   SYSB_(geteuid32,		False),
+   SYSB_(getegid,		False),
+   SYSB_(getegid32,		False),
+   SYSB_(getgid,		False),
+   SYSB_(getgid32,		False),
+   SYSB_(getpid,		False),
+   SYSB_(getpgid,		False),
+   SYSB_(getpgrp,		False),
+   SYSB_(getppid,		False),
+   SYSBA(getresgid,		False),
+   SYSBA(getresgid32,		False),
+   SYSBA(getresuid,		False),
+   SYSBA(getresuid32,		False),
+   SYSBA(ugetrlimit,		False),
+   SYSBA(getrlimit,		False),
+   SYSBA(getrusage,		False),
+   SYSBA(gettimeofday,		False),
+   SYSB_(getuid,		False),
+   SYSB_(getuid32,		False),
+   SYSBA(ipc,			True),
+   SYSBA(ioctl,			True),
+   SYSBA(kill,			False),
+   SYSB_(link,			True),
+   SYSB_(lseek,			False),
+   SYSBA(_llseek,		False),
+   SYSBA(lstat,			False),
+   SYSBA(lstat64,		False),
+   SYSB_(mkdir,			True),
+   SYSBA(mprotect,		False),
+   SYSBA(munmap,		False),
+   SYSBA(mincore,		False),
+   SYSBA(nanosleep,		True),
+   SYSB_(_newselect,		True),
+   SYSBA(open,			True),
+   SYSBA(read,			True),
+   SYSB_(write,			True),
+   SYSBA(creat,			True),
+   SYSBA(pipe,			False),
+   SYSBA(poll,			True),
+   SYSBA(readlink,		False),
+   SYSBA(readv,			True),
+   SYSB_(rename,		False),
+   SYSB_(rmdir,			True),
+   SYSBA(sched_setparam,	False),	/* ??? */
+   SYSBA(sched_getparam,	False),	/* ??? */
+   SYSB_(sched_yield,		False),	/* ??? */
+   SYSB_(select,		True),
+   SYSB_(setfsgid32,		False),
+   SYSB_(setgid32,		False),
+   SYSB_(setgid,		False),
+   SYSB_(setsid,		False),
+   SYSB_(setgroups32,		False),
+   SYSB_(setgroups,		False),
+   SYSBA(setpgid,		False),
+   SYSB_(setregid32,		False),
+   SYSB_(setresuid32,		False),
+   SYSB_(setreuid32,		False),
+   SYSB_(setreuid,		False),
+   SYSB_(setrlimit,		False),
+   SYSB_(setuid32,		False),
+   SYSB_(setuid,		False),
+   SYSBA(socketcall,		True),
+   SYSBA(stat,			False),
+   SYSBA(statfs,		False),
+   SYSBA(statfs64,		False),
+   SYSB_(symlink,		True),
+   SYSBA(stat64,		False),
+   SYSBA(fstat64,		False),
+   SYSBA(sysinfo,		False),
+   SYSBA(time,			False),
+   SYSBA(times,			False),
+   SYSB_(truncate,		True),
+   SYSB_(umask,			False),
+   SYSB_(unlink,		True),
+   SYSBA(uname,			False),
+   SYSB_(utime,			True),
+   SYSB_(utimes,                False),
+   SYSBA(waitpid,		True),
+   SYSBA(wait4,			True),
+   SYSB_(writev,		True),
+   SYSB_(prctl,			True),
+   SYSBA(adjtimex,		False),
+   SYSBA(mmap2,			False),
+   SYSBA(clock_gettime,         False),
+   SYSBA(futex,                 True),
+
+   /* new signal handling makes these normal blocking syscalls */
+   SYSB_(pause,			True),
+   SYSB_(sigsuspend,		True),
+   SYSB_(rt_sigsuspend,		True),
+   SYSBA(rt_sigtimedwait,	True),
+   SYSBA(rt_sigqueueinfo,	False),
+
+   SYSBA(sigpending,		True), /* not blocking, but must run in LWP context */
+   SYSBA(rt_sigpending,		True), /* not blocking, but must run in LWP context */
+   SYSB_(alarm,			True), /* not blocking, but must run in LWP context */
+   SYSBA(setitimer,		True), /* not blocking, but must run in LWP context */
+   SYSBA(getitimer,		True), /* not blocking, but must run in LWP context */
+};
+#define MAX_SYS_INFO		(sizeof(sys_info)/sizeof(sys_info[0]))
+
+#undef SYSB_
+#undef SYSBA
+
+
+/* the syscall no is in %eax.  For syscalls with <= 6 args,
+   args 1 .. 6 to the syscall are in %ebx %ecx %edx %esi %edi %ebp.
+   For calls with > 6 args, %ebx points to a lump of memory
+   containing the args.
+
+   The result is returned in %eax.  If this value >= 0, the call
+   succeeded, and this is the return value.  If < 0, it failed, and
+   the negation of this value is errno.  To be more specific, 
+   if res is in the range -EMEDIUMTYPE (-124) .. -EPERM (-1)
+   (kernel 2.4.9 sources, include/asm-i386/errno.h)
+   then it indicates an error.  Otherwise it doesn't.
+   
+   Dirk Mueller (mueller@kde.org) says that values -4095 .. -1
+   (inclusive?) indicate error returns.  Not sure where the -4095
+   comes from.
+*/
+
+static void run_syscall(UInt syscallno, ThreadState *tst)
+{
+   tst->m_eax = VG_(do_syscall)(syscallno, 
+				tst->m_ebx,
+				tst->m_ecx, 
+				tst->m_edx,
+				tst->m_esi,
+				tst->m_edi,
+				tst->m_ebp);
+}
+
+static const struct sys_info *get_sysinfo(UInt syscallno, Bool *special)
+{
+   const struct sys_info *sys = NULL;
+   *special = False;
+
+   if (syscallno < MAX_SPECIAL_SYS && special_sys[syscallno].before != NULL) {
+      sys = &special_sys[syscallno];
+      *special = True;
+   } else if (syscallno < MAX_SYS_INFO && sys_info[syscallno].before != NULL) {
+      sys = &sys_info[syscallno];
+   } else {
+      sys = &bad_sys;
+      *special = True;
+   }
+
+   return sys;
+}
+
+void VG_(restart_syscall)(ThreadId tid)
+{
+   ThreadState* tst;
+   tst = VG_(get_ThreadState)(tid);
+
+   vg_assert(tst != NULL);
+   vg_assert(tst->status == VgTs_WaitSys);
+   vg_assert(tst->syscallno != -1);
+
+   tst->m_eax = tst->syscallno;
+   tst->m_eip -= 2;		/* sizeof(int $0x80) */
+
+   /* Make sure our caller is actually sane, and we're really backing
+      back over a syscall.
+
+      int $0x80 == CD 80 
+   */
+   {
+      UChar *p = (UChar *)tst->m_eip;
+      
+      if (p[0] != 0xcd || p[1] != 0x80)
+	 VG_(message)(Vg_DebugMsg, 
+		      "?! restarting over syscall at %p %02x %02x\n",
+		      tst->m_eip, p[0], p[1]);
+
+      vg_assert(p[0] == 0xcd && p[1] == 0x80);
+   }
+}
+
+/*--------------------------------------------------------------------*/
+/*--- end                                            vg_syscalls.c ---*/
+/*--------------------------------------------------------------------*/
diff -puN /dev/null coregrind/arch/common-unix/vg_syscalls.c
--- /dev/null	2003-01-30 02:24:37.000000000 -0800
+++ valgrind-jeremy/coregrind/arch/common-unix/vg_syscalls.c	2004-01-27 11:09:55.000000000 -0800
@@ -0,0 +1,1438 @@
+#include "vg_include.h"
+
+struct sys_info {
+   Bool	may_block;		/* is a potentially blocking syscall */
+   void	(*before)(ThreadId tid, ThreadState *tst);
+   void	(*after)(ThreadId tid, ThreadState *tst);
+};
+
+#define SYSCALL_TRACK(fn, args...)  VG_TRACK(fn, Vg_CoreSysCall, ## args)
+
+#define MAYBE_PRINTF(format, args...)  \
+   if (VG_(clo_trace_syscalls))        \
+      VG_(printf)(format, ## args)
+
+
+/* ---------------------------------------------------------------------
+   A simple atfork() facility for Valgrind's internal use
+   ------------------------------------------------------------------ */
+
+struct atfork {
+   vg_atfork_t	pre;
+   vg_atfork_t	parent;
+   vg_atfork_t	child;
+};
+
+#define VG_MAX_ATFORK	10
+
+static struct atfork atforks[VG_MAX_ATFORK];
+static Int n_atfork;
+
+void VG_(atfork)(vg_atfork_t pre, vg_atfork_t parent, vg_atfork_t child)
+{
+   Int i;
+
+   for(i = 0; i < n_atfork; i++) {
+      if (atforks[i].pre == pre &&
+	  atforks[i].parent == parent &&
+	  atforks[i].child == child)
+	 return;
+   }
+
+   if (n_atfork >= VG_MAX_ATFORK)
+      VG_(core_panic)("Too many VG_(atfork) handlers requested: raise VG_MAX_ATFORK");
+
+   atforks[n_atfork].pre    = pre;
+   atforks[n_atfork].parent = parent;
+   atforks[n_atfork].child  = child;
+
+   n_atfork++;
+}
+
+static void do_atfork_pre(ThreadId tid)
+{
+   Int i;
+
+   for(i = 0; i < n_atfork; i++)
+      if (atforks[i].pre != NULL)
+	 (*atforks[i].pre)(tid);
+}
+
+static void do_atfork_parent(ThreadId tid)
+{
+   Int i;
+
+   for(i = 0; i < n_atfork; i++)
+      if (atforks[i].parent != NULL)
+	 (*atforks[i].parent)(tid);
+}
+
+static void do_atfork_child(ThreadId tid)
+{
+   Int i;
+
+   for(i = 0; i < n_atfork; i++)
+      if (atforks[i].child != NULL)
+	 (*atforks[i].child)(tid);
+}
+
+/* ---------------------------------------------------------------------
+   Doing mmap, munmap, mprotect
+   ------------------------------------------------------------------ */
+
+// Nb: this isn't done as precisely as possible, but it seems that programs
+// are usually sufficiently well-behaved that the more obscure corner cases
+// aren't important.  Various comments in the few functions below give more
+// details... njn 2002-Sep-17
+
+/* AFAICT from kernel sources (mm/mprotect.c) and general experimentation,
+   munmap, mprotect (and mremap??) work at the page level.  So addresses
+   and lengths must be adjusted for this. */
+
+/* Mash around start and length so that the area exactly covers
+   an integral number of pages.  If we don't do that, memcheck's
+   idea of addressible memory diverges from that of the
+   kernel's, which causes the leak detector to crash. */
+static 
+void mash_addr_and_len( Addr* a, UInt* len)
+{
+   Addr ra;
+   
+   ra = PGROUNDDN(*a);
+   *len = PGROUNDUP(*a + *len) - ra;
+   *a = ra;
+}
+
+static
+void mmap_segment ( Addr a, UInt len, UInt prot, UInt mm_flags, Int fd, ULong offset )
+{
+   Bool rr, ww, xx;
+   UInt flags;
+
+   flags = SF_MMAP;
+   
+   if (mm_flags & VKI_MAP_FIXED)
+      flags |= SF_FIXED;
+   if (!(mm_flags & VKI_MAP_PRIVATE))
+      flags |= SF_SHARED;
+
+   if (fd != -1)
+      flags |= SF_FILE;
+
+   VG_(map_fd_segment)(a, len, prot, flags, fd, offset, NULL);
+
+   rr = prot & VKI_PROT_READ;
+   ww = prot & VKI_PROT_WRITE;
+   xx = prot & VKI_PROT_EXEC;
+
+   VG_TRACK( new_mem_mmap, a, len, rr, ww, xx );
+}
+
+static
+void munmap_segment ( Addr a, UInt len )
+{
+   /* Addr orig_a   = a;
+      Addr orig_len = len; */
+
+   mash_addr_and_len(&a, &len);
+
+   VG_(unmap_range)(a, len);
+
+   /*
+   VG_(printf)("MUNMAP: correct (%p for %d) to (%p for %d) %s\n", 
+      orig_a, orig_len, a, len, (orig_a!=start || orig_len!=length) 
+                                    ? "CHANGE" : "");
+   */
+
+   VG_TRACK( die_mem_munmap, a, len );
+}
+
+static 
+void mprotect_segment ( Addr a, UInt len, Int prot )
+{
+   Bool rr, ww, xx;
+
+   VG_(mprotect_range)(a, len, prot);
+
+   rr = prot & VKI_PROT_READ;
+   ww = prot & VKI_PROT_WRITE;
+   xx = prot & VKI_PROT_EXEC;
+
+   // if removing exe permission, should check and remove from exe_seg list
+   // if adding, should check and add to exe_seg list
+   // easier to ignore both cases -- both v. unlikely?
+   mash_addr_and_len(&a, &len);
+   VG_TRACK( change_mem_mprotect, a, len, rr, ww, xx );
+}
+
+
+/* Walk through a colon-separated environment variable, and remove the
+   entries which matches file_pattern.  It slides everything down over
+   the removed entries, and pads the remaining space with '\0'.  It
+   modifies the entries in place (in the client address space), but it
+   shouldn't matter too much, since we only do this just before an
+   execve().
+
+   This is also careful to mop up any excess ':'s, since empty strings
+   delimited by ':' are considered to be '.' in a path.
+*/
+void VG_(mash_colon_env)(Char *varp, const Char *remove_pattern)
+{
+   Char *const start = varp;
+   Char *entry_start = varp;
+   Char *output = varp;
+
+   if (varp == NULL)
+      return;
+
+   while(*varp) {
+      if (*varp == ':') {
+	 Char prev;
+	 Bool match;
+
+	 /* This is a bit subtle: we want to match against the entry
+	    we just copied, because it may have overlapped with
+	    itself, junking the original. */
+
+	 prev = *output;
+	 *output = '\0';
+
+	 match = VG_(string_match)(remove_pattern, entry_start);
+
+	 *output = prev;
+	 
+	 if (match) {
+	    output = entry_start;
+	    varp++;			/* skip ':' after removed entry */
+	 } else
+	    entry_start = output+1;	/* entry starts after ':' */
+      }
+
+      *output++ = *varp++;
+   }
+
+   /* match against the last entry */
+   if (VG_(string_match)(remove_pattern, entry_start)) {
+      output = entry_start;
+      if (output > start) {
+	 /* remove trailing ':' */
+	 output--;
+	 vg_assert(*output == ':');
+      }
+   }	 
+
+   /* pad out the left-overs with '\0' */
+   while(output < varp)
+      *output++ = '\0';
+}
+
+
+/* ---------------------------------------------------------------------
+   FD tracking
+   ------------------------------------------------------------------ */
+
+/* One of these is allocated for each open file descriptor.  */
+
+typedef struct OpenFd
+{
+   Int fd;                        /* The file descriptor */
+   Char *pathname;                /* NULL if not a regular file or unknown */
+   ExeContext *where;             /* NULL if inherited from parent */
+   struct OpenFd *next, *prev;
+} OpenFd;
+
+/* List of allocated file descriptors. */
+
+static OpenFd *allocated_fds;
+
+/* Count of open file descriptors. */
+
+static int fd_count = 0;
+
+/* Note the fact that a file descriptor was just closed. */
+
+static
+void record_fd_close(Int tid, Int fd)
+{
+   OpenFd *i = allocated_fds;
+
+   if (fd > VG_(max_fd))
+      return;			/* Valgrind internal */
+
+   while(i) {
+      if(i->fd == fd) {
+         if(i->prev)
+            i->prev->next = i->next;
+         else
+            allocated_fds = i->next;
+         if(i->next)
+            i->next->prev = i->prev;
+         if(i->pathname) 
+            VG_(arena_free) (VG_AR_CORE, i->pathname);
+         VG_(arena_free) (VG_AR_CORE, i);
+         fd_count--;
+         break;
+      }
+      i = i->next;
+   }
+}
+
+/* Note the fact that a file descriptor was just opened.  If the
+   tid is -1, this indicates an inherited fd.  If the pathname is NULL,
+   this either indicates a non-standard file (i.e. a pipe or socket or
+   some such thing) or that we don't know the filename.  If the fd is
+   already open, then we're probably doing a dup2() to an existing fd,
+   so just overwrite the existing one. */
+
+static
+void record_fd_open(Int tid, Int fd, char *pathname)
+{
+   OpenFd *i;
+
+   if (fd > VG_(max_fd))
+      return;			/* Valgrind internal */
+
+   /* Check to see if this fd is already open. */
+   i = allocated_fds;
+   while (i) {
+      if (i->fd == fd) {
+         if (i->pathname) VG_(arena_free)(VG_AR_CORE, i->pathname);
+         break;
+      }
+      i = i->next;
+   }
+
+   /* Not already one: allocate an OpenFd */
+   if (i == NULL) {
+      i = VG_(arena_malloc)(VG_AR_CORE, sizeof(OpenFd));
+
+      i->prev = NULL;
+      i->next = allocated_fds;
+      if(allocated_fds) allocated_fds->prev = i;
+      allocated_fds = i;
+      fd_count++;
+   }
+
+   i->fd = fd;
+   i->pathname = pathname;
+   i->where = (tid == -1) ? NULL : VG_(get_ExeContext)(tid);
+}
+
+static
+Char *unix2name(struct sockaddr_un *sa, UInt len, Char *name)
+{
+   if(sa == NULL || len == 0 || sa->sun_path[0] == '\0') {
+      VG_(sprintf)(name, "<unknown>");
+   } else {
+      VG_(sprintf)(name, "%s", sa->sun_path);
+   }
+
+   return name;
+}
+
+static
+Char *inet2name(struct sockaddr_in *sa, UInt len, Char *name)
+{
+   if(sa == NULL || len == 0) {
+      VG_(sprintf)(name, "<unknown>");
+   } else {
+      UInt addr = sa->sin_addr.s_addr;
+
+      if (addr == 0) {
+         VG_(sprintf)(name, "<unbound>");
+      } else {
+         VG_(sprintf)(name, "%u.%u.%u.%u:%u",
+                      addr & 0xFF, (addr>>8) & 0xFF,
+                      (addr>>16) & 0xFF, (addr>>24) & 0xFF,
+                      sa->sin_port);
+      }
+   }
+
+   return name;
+}
+
+
+/*
+ * Try get some details about a socket.
+ */
+
+static void
+getsockdetails(int fd)
+{
+   union u {
+      struct sockaddr a;
+      struct sockaddr_in in;
+      struct sockaddr_un un;
+   } laddr;
+   socklen_t llen;
+
+   llen = sizeof(laddr);
+   VG_(memset)(&laddr, 0, llen);
+
+   if(VG_(getsockname)(fd, (struct vki_sockaddr *)&(laddr.a), &llen) != -1) {
+      switch(laddr.a.sa_family) {
+      case AF_INET: {
+         static char lname[32];
+         static char pname[32];
+         struct sockaddr_in paddr;
+         socklen_t plen = sizeof(struct sockaddr_in);
+
+         if(VG_(getpeername)(fd, (struct vki_sockaddr *)&paddr, &plen) != -1) {
+            VG_(message)(Vg_UserMsg, "Open AF_INET socket %d: %s <-> %s", fd,
+                         inet2name(&(laddr.in), llen, lname),
+                         inet2name(&paddr, plen, pname));
+         } else {
+            VG_(message)(Vg_UserMsg, "Open AF_INET socket %d: %s <-> unbound",
+                         fd, inet2name(&(laddr.in), llen, lname));
+         }
+         return;
+         }
+      case AF_UNIX: {
+         static char lname[256];
+         VG_(message)(Vg_UserMsg, "Open AF_UNIX socket %d: %s", fd,
+                      unix2name(&(laddr.un), llen, lname));
+         return;
+         }
+      default:
+         VG_(message)(Vg_UserMsg, "Open pf-%d socket %d:",
+                      laddr.a.sa_family, fd);
+         return;
+      }
+   }
+
+   VG_(message)(Vg_UserMsg, "Open socket %d:", fd);
+}
+
+
+/* Dump out a summary, and optionally a more detailed list, of open file
+   descriptors. */
+
+void VG_(fd_stats) ()
+{
+   OpenFd *i = allocated_fds;
+
+   VG_(message)(Vg_UserMsg,
+                "FILE DESCRIPTORS: %d open at exit.", fd_count);
+
+   while(i) {
+      if(i->pathname) {
+         VG_(message)(Vg_UserMsg, "Open file descriptor %d: %s", i->fd,
+                      i->pathname);
+      } else {
+         int val;
+         socklen_t len = sizeof(val);
+
+         if(VG_(getsockopt)(i->fd, SOL_SOCKET, SO_TYPE, &val, &len) == -1) {
+            VG_(message)(Vg_UserMsg, "Open file descriptor %d:", i->fd);
+         } else {
+            getsockdetails(i->fd);
+         }
+      }
+
+      if(i->where) {
+         VG_(pp_ExeContext)(i->where);
+         VG_(message)(Vg_UserMsg, "");
+      } else {
+         VG_(message)(Vg_UserMsg, "   <inherited from parent>");
+         VG_(message)(Vg_UserMsg, "");
+      }
+
+      i = i->next;
+   }
+
+   VG_(message)(Vg_UserMsg, "");
+}
+
+static
+Char *strdupcat ( const Char *s1, const Char *s2, ArenaId aid )
+{
+   UInt len = VG_(strlen) ( s1 ) + VG_(strlen) ( s2 ) + 1;
+   Char *result = VG_(arena_malloc) ( aid, len );
+   VG_(strcpy) ( result, s1 );
+   VG_(strcat) ( result, s2 );
+   return result;
+}
+
+static 
+void pre_mem_read_sendmsg ( ThreadId tid,
+                            Char *msg, UInt base, UInt size )
+{
+   Char *outmsg = strdupcat ( "socketcall.sendmsg", msg, VG_AR_TRANSIENT );
+   SYSCALL_TRACK( pre_mem_read, tid, outmsg, base, size );
+
+   VG_(arena_free) ( VG_AR_TRANSIENT, outmsg );
+}
+
+static 
+void pre_mem_write_recvmsg ( ThreadId tid,
+                             Char *msg, UInt base, UInt size )
+{
+   Char *outmsg = strdupcat ( "socketcall.recvmsg", msg, VG_AR_TRANSIENT );
+   SYSCALL_TRACK( pre_mem_write, tid, outmsg, base, size );
+   VG_(arena_free) ( VG_AR_TRANSIENT, outmsg );
+}
+
+static
+void post_mem_write_recvmsg ( ThreadId tid,
+                              Char *fieldName, UInt base, UInt size )
+{
+   VG_TRACK( post_mem_write, base, size );
+}
+ 
+static
+void msghdr_foreachfield ( 
+        ThreadId tid, 
+        struct msghdr *msg, 
+        void (*foreach_func)( ThreadId, Char *, UInt, UInt ) 
+     )
+{
+   if ( !msg )
+      return;
+
+   foreach_func ( tid, "(msg)", (Addr)msg, sizeof( struct msghdr ) );
+
+   if ( msg->msg_name )
+      foreach_func ( tid, 
+                     "(msg.msg_name)", 
+                     (Addr)msg->msg_name, msg->msg_namelen );
+
+   if ( msg->msg_iov ) {
+      struct iovec *iov = msg->msg_iov;
+      UInt i;
+
+      foreach_func ( tid, 
+                     "(msg.msg_iov)", 
+                     (Addr)iov, msg->msg_iovlen * sizeof( struct iovec ) );
+
+      for ( i = 0; i < msg->msg_iovlen; ++i, ++iov )
+         foreach_func ( tid, 
+                        "(msg.msg_iov[i]", 
+                        (Addr)iov->iov_base, iov->iov_len );
+   }
+
+   if ( msg->msg_control )
+      foreach_func ( tid, 
+                     "(msg.msg_control)", 
+                     (Addr)msg->msg_control, msg->msg_controllen );
+}
+
+void check_cmsg_for_fds(Int tid, struct msghdr *msg)
+{
+   struct cmsghdr *cm = CMSG_FIRSTHDR(msg);
+
+   while (cm) {
+      if (cm->cmsg_level == SOL_SOCKET &&
+          cm->cmsg_type == SCM_RIGHTS ) {
+         int *fds = (int *) CMSG_DATA(cm);
+         int fdc = (cm->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr)))
+                         / sizeof(int);
+         int i;
+
+         for (i = 0; i < fdc; i++)
+            if(VG_(clo_track_fds))
+               record_fd_open (tid, fds[i], VG_(resolve_filename)(fds[i]));
+      }
+
+      cm = CMSG_NXTHDR(msg, cm);
+   }
+}
+
+static
+void pre_mem_read_sockaddr ( ThreadId tid,
+			     Char *description,
+			     struct sockaddr *sa, UInt salen )
+{
+   Char *outmsg;
+
+   /* NULL/zero-length sockaddrs are legal */
+   if ( sa == NULL || salen == 0 ) return;
+
+   outmsg = VG_(arena_malloc) ( VG_AR_TRANSIENT,
+                                strlen( description ) + 30 );
+
+   VG_(sprintf) ( outmsg, description, ".sa_family" );
+   SYSCALL_TRACK( pre_mem_read, tid, outmsg, 
+                  (UInt) &sa->sa_family, sizeof (sa_family_t));
+
+   switch (sa->sa_family) {
+                  
+      case AF_UNIX:
+         VG_(sprintf) ( outmsg, description, ".sun_path" );
+         SYSCALL_TRACK( pre_mem_read_asciiz, tid, outmsg,
+            (UInt) ((struct sockaddr_un *) sa)->sun_path);
+         break;
+                     
+      case AF_INET:
+         VG_(sprintf) ( outmsg, description, ".sin_port" );
+         SYSCALL_TRACK( pre_mem_read, tid, outmsg,
+            (UInt) &((struct sockaddr_in *) sa)->sin_port,
+            sizeof (((struct sockaddr_in *) sa)->sin_port));
+         VG_(sprintf) ( outmsg, description, ".sin_addr" );
+         SYSCALL_TRACK( pre_mem_read, tid, outmsg,
+            (UInt) &((struct sockaddr_in *) sa)->sin_addr,
+            sizeof (struct in_addr));
+         break;
+                           
+      case AF_INET6:
+         VG_(sprintf) ( outmsg, description, ".sin6_port" );
+         SYSCALL_TRACK( pre_mem_read, tid, outmsg,
+            (UInt) &((struct sockaddr_in6 *) sa)->sin6_port,
+            sizeof (((struct sockaddr_in6 *) sa)->sin6_port));
+         VG_(sprintf) ( outmsg, description, ".sin6_flowinfo" );
+         SYSCALL_TRACK( pre_mem_read, tid, outmsg,
+            (UInt) &((struct sockaddr_in6 *) sa)->sin6_flowinfo,
+            sizeof (uint32_t));
+         VG_(sprintf) ( outmsg, description, ".sin6_addr" );
+         SYSCALL_TRACK( pre_mem_read, tid, outmsg,
+            (UInt) &((struct sockaddr_in6 *) sa)->sin6_addr,
+            sizeof (struct in6_addr));
+#        ifndef GLIBC_2_1
+         VG_(sprintf) ( outmsg, description, ".sin6_scope_id" );
+         SYSCALL_TRACK( pre_mem_read, tid, outmsg,
+            (UInt) &((struct sockaddr_in6 *) sa)->sin6_scope_id,
+			sizeof (uint32_t));
+#        endif
+         break;
+               
+      default:
+         VG_(sprintf) ( outmsg, description, "" );
+         SYSCALL_TRACK( pre_mem_read, tid, outmsg, (UInt) sa, salen );
+         break;
+   }
+   
+   VG_(arena_free) ( VG_AR_TRANSIENT, outmsg );
+}
+
+/* Dereference a pointer to a UInt. */
+static UInt deref_UInt ( ThreadId tid, Addr a, Char* s )
+{
+   UInt* a_p = (UInt*)a;
+   SYSCALL_TRACK( pre_mem_read, tid, s, (Addr)a_p, sizeof(UInt) );
+   if (a_p == NULL)
+      return 0;
+   else
+      return *a_p;
+}
+
+/* Dereference a pointer to a pointer. */
+static Addr deref_Addr ( ThreadId tid, Addr a, Char* s )
+{
+   Addr* a_p = (Addr*)a;
+   SYSCALL_TRACK( pre_mem_read, tid, s, (Addr)a_p, sizeof(Addr) );
+   return *a_p;
+}
+
+static 
+void buf_and_len_pre_check( ThreadId tid, Addr buf_p, Addr buflen_p,
+                            Char* buf_s, Char* buflen_s )
+{
+   if (VG_(defined_pre_mem_write)()) {
+      UInt buflen_in = deref_UInt( tid, buflen_p, buflen_s);
+      if (buflen_in > 0) {
+         TL_(pre_mem_write) ( Vg_CoreSysCall,
+			      tid, buf_s, buf_p, buflen_in );
+      }
+   }
+}
+
+static 
+void buf_and_len_post_check( ThreadId tid, Int res,
+                             Addr buf_p, Addr buflen_p, Char* s )
+{
+   if (!VG_(is_kerror)(res) && VG_(defined_post_mem_write)()) {
+      UInt buflen_out = deref_UInt( tid, buflen_p, s);
+      if (buflen_out > 0 && buf_p != (Addr)NULL) {
+         TL_(post_mem_write) ( buf_p, buflen_out );
+      }
+   }
+}
+
+/* ---------------------------------------------------------------------
+   Data seg end, for brk()
+   ------------------------------------------------------------------ */
+
+static Addr do_brk(Addr newbrk)
+{
+   Addr ret = VG_(brk_limit);
+   static const Bool debug = False;
+   Segment *seg;
+
+   if (debug)
+      VG_(printf)("do_brk: brk_base=%p brk_limit=%p newbrk=%p\n",
+		  VG_(brk_base), VG_(brk_limit), newbrk);
+
+   if (newbrk < VG_(brk_base) || newbrk >= VG_(client_end))
+      return VG_(brk_limit);
+
+   /* brk isn't allowed to grow over anything else */
+   seg = VG_(find_segment)(VG_(brk_limit));
+
+   vg_assert(seg != NULL);
+
+   if (0)
+      VG_(printf)("brk_limit=%p seg->addr=%p seg->end=%p\n", 
+		  VG_(brk_limit), seg->addr, seg->addr+seg->len);
+   vg_assert(VG_(brk_limit) >= seg->addr && VG_(brk_limit) <= (seg->addr + seg->len));
+
+   seg = VG_(next_segment)(seg);
+   if (seg != NULL && newbrk > seg->addr)
+      return VG_(brk_limit);
+
+   if (PGROUNDDN(newbrk) != PGROUNDDN(VG_(brk_limit))) {
+      Addr current = PGROUNDUP(VG_(brk_limit));
+      Addr newaddr = PGROUNDUP(newbrk);
+
+      /* new brk in a new page - fix the mappings */
+      if (newbrk > VG_(brk_limit)) {
+	 
+	 if (debug)
+	    VG_(printf)("  extending brk: current=%p newaddr=%p delta=%d\n",
+			current, newaddr, newaddr-current);
+
+	 if (newaddr == current) {
+	    ret = newbrk;
+	 } else if (VG_(mmap)((void *)current , newaddr-current,
+			      VKI_PROT_READ | VKI_PROT_WRITE | VKI_PROT_EXEC,
+			      VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS | VKI_MAP_FIXED | VKI_MAP_CLIENT,
+			      -1, 0) >= 0) {
+	    VG_(map_segment)(current, newaddr-current, VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC,
+			     SF_FIXED|SF_BRK);
+	    ret = newbrk;
+	 }
+      } else {
+	 vg_assert(newbrk < VG_(brk_limit));
+
+	 if (debug)
+	    VG_(printf)("  shrinking brk: current=%p newaddr=%p delta=%d\n",
+			current, newaddr, current-newaddr);
+
+	 if (newaddr != current) {
+	    VG_(munmap)((void *)newaddr, current - newaddr);
+	    VG_(unmap_range)(newaddr, current-newaddr);
+	 }
+	 ret = newbrk;
+      }
+   } else
+      ret = newbrk;
+
+   VG_(brk_limit) = ret;
+
+   return ret;
+}
+
+
+/* ---------------------------------------------------------------------
+   Vet file descriptors for sanity
+   ------------------------------------------------------------------ */
+
+/* Return true if we're allowed to use or create this fd */
+static Bool fd_allowed(Int fd, const Char *syscall, ThreadId tid)
+{
+   if (fd < 0 || fd > VG_(max_fd) || fd == VG_(clo_logfile_fd)) {
+      VG_(message)(Vg_UserMsg, 
+         "Warning: invalid file descriptor %d in syscall %s()",
+         fd, syscall);
+      if (fd == VG_(clo_logfile_fd))
+	 VG_(message)(Vg_UserMsg, 
+            "   Use --logfile-fd=<number> to select an alternative "
+	    "logfile fd.");
+      if (VG_(clo_verbosity) > 1) {
+	 ExeContext *ec = VG_(get_ExeContext)(tid);
+	 VG_(pp_ExeContext)(ec);
+      }
+      return False;
+   }
+   return True;
+}
+
+/* ---------------------------------------------------------------------
+   The Main Entertainment ...
+   ------------------------------------------------------------------ */
+
+#define PRE(x)	\
+	static void before_##x(ThreadId tid, ThreadState *tst)
+#define POST(x)	\
+	static void after_##x(ThreadId tid, ThreadState *tst)
+
+#define PREALIAS(new, old)	\
+	PRE(new) __attribute__((alias(STR(before_##old))))
+#define POSTALIAS(new, old)	\
+	POST(new) __attribute__((alias(STR(after_##old))))
+
+PRE(mount)
+{
+   MAYBE_PRINTF( "mount( %p, %p, %p )\n" ,ARG(1),ARG(2),ARG(3));
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid,"mount(specialfile)",ARG(1));
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid,"mount(dir)",ARG(2));
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid,"mount(filesystemtype)",ARG(3));
+}
+
+PRE(umount)
+{
+   /* int umount(const char *path) */
+   MAYBE_PRINTF("umount( %p )\n", ARG(1));
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid,"umount(path)",ARG(1));
+}
+
+
+PRE(kill)
+{
+   /* int kill(pid_t pid, int sig); */
+   MAYBE_PRINTF("kill ( %d, %d )\n", ARG(1),ARG(2));
+   if (ARG(2) == VKI_SIGVGINT || ARG(2) == VKI_SIGVGKILL)
+      SETERROR(tst, VKI_EINVAL);
+}
+
+POST(kill)
+{
+   /* If this was a self-kill then wait for a signal to be
+      delivered to any thread before claiming the kill is done. */
+   if (ARG(2) != 0 &&					/* if a real signal */
+       !VG_(is_sig_ign)(ARG(2)) &&			/* that isn't ignored and */
+       !VG_(ksigismember)(&tst->eff_sig_mask, ARG(2)) &&	/*      we're not blocking it */
+       (ARG(1) == VG_(getpid)() ||			/* directed at us or */
+	ARG(1) == -1	      ||			/* directed at everyone or */
+	ARG(1) == 0	      ||			/* directed at whole group or */
+	-ARG(1) == VG_(getpgrp)())) {			/* directed at our group... */
+      /* ...then wait for that signal to be delivered to someone
+	 (might be us, might be someone else who doesn't have it
+	 blocked) */
+      VG_(proxy_waitsig)();
+   }
+}
+
+PRE(link)
+{
+   /* int link(const char *oldpath, const char *newpath); */
+   MAYBE_PRINTF("link ( %p, %p)\n", ARG(1), ARG(2));
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "link(oldpath)", ARG(1));
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "link(newpath)", ARG(2));
+}
+
+PRE(lseek)
+{
+   /* off_t lseek(int fildes, off_t offset, int whence); */
+   MAYBE_PRINTF("lseek ( %d, %d, %d )\n",ARG(1),ARG(2),ARG(3));
+}
+
+
+PRE(lstat)
+{
+   /* int lstat(const char *file_name, struct stat *buf); */
+   MAYBE_PRINTF("lstat ( %p \"%s\", %p )\n",ARG(1),ARG(1),ARG(2));
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "lstat(file_name)", ARG(1) );
+   SYSCALL_TRACK( pre_mem_write, tid, "lstat(buf)", ARG(2), 
+		  sizeof(struct vki_stat) );
+}
+
+POST(lstat)
+{
+   VG_TRACK( post_mem_write, ARG(2), sizeof(struct vki_stat) );
+}
+
+
+PRE(mkdir)
+{
+   /* int mkdir(const char *pathname, mode_t mode); */
+   MAYBE_PRINTF("mkdir ( %p, %d )\n", ARG(1),ARG(2));
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "mkdir(pathname)", ARG(1) );
+}
+
+
+PRE(poll)
+{
+   /* struct pollfd {
+	int fd;           -- file descriptor
+	short events;     -- requested events
+	short revents;    -- returned events
+      };
+      int poll(struct pollfd *ufds, unsigned int nfds, 
+      int timeout) 
+   */
+   MAYBE_PRINTF("poll ( %p, %d, %d )\n",ARG(1),ARG(2),ARG(3));
+   /* In fact some parts of this struct should be readable too.
+      This should be fixed properly. */
+   SYSCALL_TRACK( pre_mem_write, tid, "poll(ufds)", 
+		  ARG(1), ARG(2) * sizeof(struct pollfd) );
+}
+
+POST(poll)
+{
+   UInt i;
+   struct pollfd * arr = (struct pollfd *)ARG(1);
+   for (i = 0; i < ARG(2); i++)
+      VG_TRACK( post_mem_write, (Addr)(&arr[i].revents), 
+		sizeof(Short) );
+}
+
+
+PRE(readlink)
+{
+   /* int readlink(const char *path, char *buf, size_t bufsiz); */
+   MAYBE_PRINTF("readlink ( %p, %p, %d )\n", ARG(1),ARG(2),ARG(3));
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "readlink(path)", ARG(1) );
+   SYSCALL_TRACK( pre_mem_write, tid, "readlink(buf)", ARG(2),ARG(3) );
+}
+
+POST(readlink)
+{
+   VG_TRACK( post_mem_write, ARG(2), RES );
+}
+
+PRE(readv)
+{
+   /* int readv(int fd, const struct iovec * vector, size_t count); */
+   Int i;
+   struct iovec * vec;
+   MAYBE_PRINTF("readv ( %d, %p, %d )\n",ARG(1),ARG(2),ARG(3));
+   if (!fd_allowed(ARG(1), "readv", tid)) {
+      SETERROR(tst, VKI_EBADF);
+   } else {
+      SYSCALL_TRACK( pre_mem_read, tid, "readv(vector)", 
+		     ARG(2), ARG(3) * sizeof(struct iovec) );
+      /* ToDo: don't do any of the following if the vector is invalid */
+      vec = (struct iovec *)ARG(2);
+      for (i = 0; i < (Int)ARG(3); i++)
+	 SYSCALL_TRACK( pre_mem_write, tid, "readv(vector[...])",
+			(UInt)vec[i].iov_base,vec[i].iov_len );
+   }
+}
+
+POST(readv)
+{
+   Int i;
+   struct iovec * vec = (struct iovec *)ARG(2);
+   Int remains = RES;
+
+   /* res holds the number of bytes read. */
+   for (i = 0; i < (Int)ARG(3); i++) {
+      Int nReadThisBuf = vec[i].iov_len;
+      if (nReadThisBuf > remains) nReadThisBuf = remains;
+      VG_TRACK( post_mem_write, (UInt)vec[i].iov_base, nReadThisBuf );
+      remains -= nReadThisBuf;
+      if (remains < 0) VG_(core_panic)("readv: remains < 0");
+   }
+}
+
+
+
+
+PRE(sigprocmask)
+{
+   /* int sigprocmask(int how, k_sigset_t *set, 
+      k_sigset_t *oldset); */
+   MAYBE_PRINTF("sigprocmask ( %d, %p, %p )\n",ARG(1),ARG(2),ARG(3));
+   if (ARG(2) != (UInt)NULL)
+      SYSCALL_TRACK( pre_mem_read, tid, "sigprocmask(set)", 
+		     ARG(2), sizeof(vki_ksigset_t));
+   if (ARG(3) != (UInt)NULL)
+      SYSCALL_TRACK( pre_mem_write, tid, "sigprocmask(oldset)", 
+		     ARG(3), sizeof(vki_ksigset_t));
+
+   VG_(do__NR_sigprocmask) ( tid, 
+			     ARG(1) /*how*/, 
+			     (vki_ksigset_t*) ARG(2),
+			     (vki_ksigset_t*) ARG(3) );
+}
+
+POST(sigprocmask)
+{
+   if (ARG(3) != (UInt)NULL)
+      VG_TRACK( post_mem_write, ARG(3), sizeof(vki_ksigset_t));
+}
+
+PRE(sigaltstack)
+{
+   /* int sigaltstack(const stack_t *ss, stack_t *oss); */
+   MAYBE_PRINTF("sigaltstack ( %p, %p )\n",ARG(1),ARG(2));
+   if (ARG(1) != (UInt)NULL) {
+      SYSCALL_TRACK( pre_mem_read, tid, "sigaltstack(ss)", 
+		     ARG(1), sizeof(vki_kstack_t) );
+   }
+   if (ARG(2) != (UInt)NULL) {
+      SYSCALL_TRACK( pre_mem_write, tid, "sigaltstack(oss)", 
+		     ARG(2), sizeof(vki_kstack_t) );
+   }
+
+   VG_(do__NR_sigaltstack) (tid);
+}
+
+POST(sigaltstack)
+{
+   if (ARG(2) != (UInt)NULL)
+      VG_TRACK( post_mem_write, ARG(2), sizeof(vki_kstack_t));
+}
+
+PRE(sigaction)
+{
+   /* int sigaction(int signum, struct k_sigaction *act, 
+      struct k_sigaction *oldact); */
+   MAYBE_PRINTF("sigaction ( %d, %p, %p )\n",ARG(1),ARG(2),ARG(3));
+   if (ARG(2) != (UInt)NULL)
+      SYSCALL_TRACK( pre_mem_read, tid, "sigaction(act)", 
+		     ARG(2), sizeof(vki_ksigaction));
+   if (ARG(3) != (UInt)NULL)
+      SYSCALL_TRACK( pre_mem_write, tid, "sigaction(oldact)", 
+		     ARG(3), sizeof(vki_ksigaction));
+
+   VG_(do__NR_sigaction)(tid);
+}
+
+POST(sigaction)
+{
+   if (ARG(3) != (UInt)NULL)
+      VG_TRACK( post_mem_write, ARG(3), sizeof(vki_ksigaction));
+}
+
+PRE(sigsuspend)
+{
+   /* int sigsuspend(const sigset_t *mask); */
+   MAYBE_PRINTF("sigsuspend ( %p )\n", ARG(1) );
+   if (ARG(1) != (Addr)NULL) {
+      /* above NULL test is paranoia */
+      SYSCALL_TRACK( pre_mem_read, tid, "sigsuspend(mask)", ARG(1), 
+		     sizeof(vki_ksigset_t) );
+   }
+}
+
+PRE(pause)
+{
+   /* int pause(void); */
+   MAYBE_PRINTF("pause ( )\n");
+}
+
+
+
+
+
+
+
+
+
+
+static void bad_before(ThreadId tid, ThreadState *tst)
+{
+   VG_(message)
+      (Vg_DebugMsg,"WARNING: unhandled syscall: %d", tst->m_eax);
+   if (VG_(clo_verbosity) > 1) {
+      ExeContext *ec = VG_(get_ExeContext)(tid);
+      VG_(pp_ExeContext)(ec);
+   }
+   VG_(message)
+      (Vg_DebugMsg,"Do not panic.  You may be able to fix this easily.");
+   VG_(message)
+      (Vg_DebugMsg,"Read the file README_MISSING_SYSCALL_OR_IOCTL.");
+
+   tst->m_eax = -VKI_ENOSYS;
+}
+
+static void bad_after(ThreadId tid, ThreadState *tst)
+{
+}
+
+static const struct sys_info bad_sys = { False, bad_before, bad_after };
+
+
+
+Bool VG_(pre_syscall) ( ThreadId tid )
+{
+   ThreadState* tst;
+   UInt         syscallno;
+   const struct sys_info *sys;
+   Bool special = False;
+   Bool syscall_done = False;	/* we actually ran the syscall */
+
+   VGP_PUSHCC(VgpCoreSysWrap);
+
+   tst = VG_(get_ThreadState)(tid);
+
+   /* Convert vfork to fork, since we can't handle it otherwise. */
+   if (tst->m_eax == __NR_vfork)
+      tst->m_eax = __NR_fork;
+
+   syscallno = SYSNO;
+
+   if (tst->syscallno != -1)
+      VG_(printf)("tid %d has syscall %d\n", tst->tid, tst->syscallno);
+
+   vg_assert(tst->syscallno == -1);		/* should be no current syscall */
+   vg_assert(tst->status == VgTs_Runnable);	/* should be runnable */
+
+   tst->syscallno = syscallno;
+
+   sys = get_sysinfo(syscallno, &special);
+
+   /* Do any pre-syscall actions */
+   if (VG_(needs).syscall_wrapper) {
+      VGP_PUSHCC(VgpSkinSysWrap);
+      tst->sys_pre_res = TL_(pre_syscall)(tid, syscallno, /*isBlocking*/sys->may_block);
+      VGP_POPCC(VgpSkinSysWrap);
+   }
+
+   MAYBE_PRINTF("SYSCALL[%d,%d](%3d)%s%s:", 
+		VG_(getpid)(), tid, syscallno, 
+		special ? " special" : "",
+		sys->may_block ? " blocking" : "");
+
+   if (special) {
+      /* "Special" syscalls are implemented by Valgrind internally,
+	 and do not generate real kernel calls.  The expectation,
+	 therefore, is that the "before" function not only does the
+	 appropriate tests, but also performs the syscall itself and
+	 sets the result.  Special syscalls cannot block. */
+      vg_assert(sys->may_block == False);
+
+      (sys->before)(tst->tid, tst);
+
+      syscall_done = True;
+   } else {
+      (sys->before)(tst->tid, tst);
+
+      if ((Int)tst->m_eax <= 0) {
+	 /* "before" decided the syscall wasn't viable, so don't do
+	    anything - just pretend the syscall happened. */
+	 syscall_done = True;
+      } else if (sys->may_block) {
+	 /* Issue to worker.  If we're waiting on the syscall because
+	    it's in the hands of the ProxyLWP, then set the thread
+	    state to WaitSys. */
+	 tst->status = VgTs_WaitSys;
+	 VG_(sys_issue)(tid);
+      } else {
+	 /* run the syscall directly */
+	 run_syscall(syscallno, tst);
+	 syscall_done = True;
+      }
+   }
+
+   VGP_POPCC(VgpCoreSysWrap);
+
+   vg_assert(( syscall_done && tst->status == VgTs_Runnable) ||
+	     (!syscall_done && tst->status == VgTs_WaitSys ));
+
+   return syscall_done;
+}
+
+
+void VG_(post_syscall) ( ThreadId tid, Bool restart )
+{
+   ThreadState* tst;
+   UInt syscallno;
+   const struct sys_info *sys;
+   Bool special = False;
+   Bool restarted = False;
+   void *pre_res;
+
+   VGP_PUSHCC(VgpCoreSysWrap);
+
+   tst = VG_(get_ThreadState)(tid);
+
+   /* Tell the skin about the syscall return value */
+   SET_SYSCALL_RETVAL(tst->tid, tst->m_eax);
+
+   syscallno = tst->syscallno;
+   pre_res = tst->sys_pre_res;
+
+   vg_assert(syscallno != -1);			/* must be a current syscall */
+
+   sys = get_sysinfo(syscallno, &special);
+
+   if (GETERROR(tst) == VKI_ERESTARTSYS) {
+      /* Applications never expect to see this, so we should either
+	 restart the syscall or fail it with EINTR, depending on what
+	 our caller wants.  Generally they'll want to restart, but if
+	 client set the signal state to not restart, then we fail with
+	 EINTR.  Either way, ERESTARTSYS means the syscall made no
+	 progress, and so can be failed or restarted without
+	 consequence. */
+      if (0)
+	 VG_(printf)("syscall %d returned ERESTARTSYS; restart=%d\n",
+		     syscallno, restart);
+
+      if (restart) {
+	 restarted = True;
+	 VG_(restart_syscall)(tid);
+      } else
+	 SETERROR(tst, VKI_EINTR);
+   } 
+
+   if (!restarted) {
+      if (!VG_(is_kerror)(tst->m_eax) && sys->after != NULL)
+	 (sys->after)(tst->tid, tst);
+
+      /* Do any post-syscall actions
+
+	 NOTE: this is only called if the syscall completed.  If the
+	 syscall was restarted, then it will call the Tool's
+	 pre_syscall again, without calling post_syscall (ie, more
+	 pre's than post's)
+       */
+      if (VG_(needs).syscall_wrapper) {
+	 VGP_PUSHCC(VgpSkinSysWrap);
+	 TL_(post_syscall)(tid, syscallno, pre_res, tst->m_eax, /*isBlocking*/True); // did block
+	 VGP_POPCC(VgpSkinSysWrap);
+      }
+   }
+
+   tst->status = VgTs_Runnable;	/* runnable again */
+   tst->syscallno = -1;
+
+   VGP_POPCC(VgpCoreSysWrap);
+}
+
+PRE(execve)
+{
+   /* int execve (const char *filename, 
+      char *const argv [], 
+      char *const envp[]); */
+   MAYBE_PRINTF("execve ( %p(%s), %p, %p ) --- NOT CHECKED\n", 
+		ARG(1), ARG(1), ARG(2), ARG(3));
+
+   /* Erk.  If the exec fails, then the following will have made a
+      mess of things which makes it hard for us to continue.  The
+      right thing to do is piece everything together again in
+      POST(execve), but that's hard work.  Instead, we make an effort
+      to check that the execve will work before actually calling
+      exec. */
+   {
+      struct vki_stat st;
+      Int ret = VG_(stat)((Char *)ARG(1), &st);
+
+      if (ret < 0) {
+	 RES = ret;
+	 return;
+      }
+      /* just look for any X bit set
+	 XXX do proper permissions check?
+       */
+      if ((st.st_mode & 0111) == 0) {
+	 SETERROR(tst, VKI_EACCES);
+	 return;
+      }
+   }
+
+   /* Resistance is futile.  Nuke all other threads.  POSIX mandates
+      this. (Really, nuke them all, since the new process will make
+      its own new thread.) */
+   VG_(nuke_all_threads_except)( VG_INVALID_THREADID );
+
+   {
+      /* Make the LD_LIBRARY_PATH/LD_PRELOAD disappear so that the
+	 child doesn't get our libpthread and other stuff.  This is
+	 done unconditionally, since if we are tracing the child,
+	 stage1/2 will set up the appropriate client environment. */
+      Int i;
+      Char** envp = (Char**)ARG(3);
+      Char*  ld_preload_str = NULL;
+      Char*  ld_library_path_str = NULL;
+
+      if (envp != NULL) {
+	 Char *buf;
+
+	 for (i = 0; envp[i] != NULL; i++) {
+	    if (VG_(strncmp)(envp[i], "LD_PRELOAD=", 11) == 0)
+	       ld_preload_str = &envp[i][11];
+	    if (VG_(strncmp)(envp[i], "LD_LIBRARY_PATH=", 16) == 0)
+	       ld_library_path_str = &envp[i][16];
+	 }
+
+	 buf = VG_(arena_malloc)(VG_AR_CORE, VG_(strlen)(VG_(libdir)) + 20);
+
+         VG_(sprintf)(buf, "%s*/vg_inject.so", VG_(libdir));
+         VG_(mash_colon_env)(ld_preload_str, buf);
+
+         VG_(sprintf)(buf, "%s*/vgpreload_*.so", VG_(libdir));
+         VG_(mash_colon_env)(ld_preload_str, buf);
+
+         VG_(sprintf)(buf, "%s*", VG_(libdir));
+         VG_(mash_colon_env)(ld_library_path_str, buf);
+
+         VG_(env_unsetenv)(envp, VALGRINDCLO);
+
+	 /* XXX if variable becomes empty, remove it completely? */
+      }
+   }
+
+   if (VG_(clo_trace_children)) {
+      /* If we're tracing the children, then we need to start it
+	 with our starter+arguments.
+      */
+      Int i;
+      Char *exec = (Char *)ARG(1);
+      Char **env = (Char **)ARG(3);
+      Char *cp;
+      Char *exename;
+      Bool sawexec = False;
+      Char *optvar;
+      Int  optlen;
+
+      optlen = 1;
+      for(i = 0; i < VG_(vg_argc); i++)
+	 optlen += VG_(strlen)(VG_(vg_argv)[i]) + 1;
+
+      /* All these are leaked - we're either going to exec, or panic
+	 when we fail. */
+      exename  = VG_(arena_malloc)(VG_AR_CORE, 64);
+      exec = VG_(arena_malloc)(VG_AR_CORE, VG_(strlen)(exec) + 7 /* --exec= */ + 1 /* \0 */);
+
+      VG_(sprintf)(exec, "--exec=%s", (Char *)ARG(1));
+      VG_(sprintf)(exename, "/proc/self/fd/%d", VG_(vgexecfd));
+
+      optlen += VG_(strlen)(exec)+1;
+
+      optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
+
+      /* valgrind arguments */
+      cp = optvar;
+      
+      for(i = 1; i < VG_(vg_argc); i++) {
+	 Char *arg = VG_(vg_argv)[i];
+	 Int len;
+	 
+	 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
+	    /* replace existing --exec= arg */
+	    sawexec = True;
+	    arg = exec;
+	 } else if (VG_(strcmp)(VG_(vg_argv)[i], "--") == 0)
+	    break;
+
+	 len = VG_(strlen)(arg);
+	 VG_(memcpy)(cp, arg, len);
+	 cp += len;
+	 *cp++ = '\01';
+      }
+
+      if (!sawexec) {
+	 Int execlen = VG_(strlen)(exec);
+	 VG_(memcpy)(cp, exec, execlen);
+	 cp += execlen;
+	 *cp++ = '\01';
+      }
+      *cp = '\0';
+
+      VG_(env_setenv)(&env, VALGRINDCLO, optvar);
+
+      SETARG(1, (UInt)exename);
+      SETARG(3, (UInt)env);
+   }
+
+   if (0) {
+      Char **cpp;
+
+      VG_(printf)("exec: %s\n", (Char *)ARG(1));
+      for(cpp = (Char **)ARG(2); cpp && *cpp; cpp++)
+	 VG_(printf)("argv: %s\n", *cpp);
+      for(cpp = (Char **)ARG(3); cpp && *cpp; cpp++)
+	 VG_(printf)("env: %s\n", *cpp);
+   }
+
+   /* Set our real sigmask to match the client's sigmask so that the
+      exec'd child will get the right mask.  First we need to clear
+      out any pending signals so they they don't get delivered, which
+      would confuse things.
+
+      XXX This is a bug - the signals should remain pending, and be
+      delivered to the new process after exec.  There's also a
+      race-condition, since if someone delivers us a signal between
+      the sigprocmask and the execve, we'll still get the signal. Oh
+      well.
+   */
+   {
+      vki_ksigset_t allsigs;
+      vki_ksiginfo_t info;
+      static const struct vki_timespec zero = { 0, 0 };
+    
+      VG_(ksigfillset)(&allsigs);
+      while(VG_(ksigtimedwait)(&allsigs, &info, &zero) > 0)
+	 ;
+
+      VG_(ksigprocmask)(VKI_SIG_SETMASK, &tst->sig_mask, NULL);
+   }
+
+   RES = VG_(do_syscall)(__NR_execve, ARG(1), ARG(2), ARG(3));
+
+   /* If we got here, then the execve failed.  We've already made too much of a mess
+      of ourselves to continue, so we have to abort. */
+   VG_(message)(Vg_UserMsg, "execve(%p \"%s\", %p, %p) failed, errno %d",
+		ARG(1), ARG(1), ARG(2), ARG(3), -RES);
+   VG_(core_panic)("EXEC FAILED: I can't recover from execve() failing, so I'm dying.\n"
+		   "Add more stringent tests in PRE(execve), or work out how to recover.");   
+}
+
+
+PRE(access)
+{
+   /* int access(const char *pathname, int mode); */
+   MAYBE_PRINTF("access ( %p, %d )\n", ARG(1),ARG(2));
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "access(pathname)", ARG(1) );
+}
+
+PRE(alarm)
+{
+   /* unsigned int alarm(unsigned int seconds); */
+   MAYBE_PRINTF("alarm ( %d )\n", ARG(1));
+}
+
+
+static vki_ksigset_t fork_saved_mask;
+
+PRE(fork)
+{
+   vki_ksigset_t mask;
+
+   vg_assert(VG_(gettid)() == VG_(main_pid));
+
+   /* Block all signals during fork, so that we can fix things up in
+      the child without being interrupted. */
+   VG_(ksigfillset)(&mask);
+   VG_(ksigprocmask)(VKI_SIG_SETMASK, &mask, &fork_saved_mask);
+
+   /* pid_t fork(void); */
+   MAYBE_PRINTF("fork ()\n");
+
+   do_atfork_pre(tid);
+}
+
+POST(fork)
+{
+   if (RES == 0) {
+      do_atfork_child(tid);
+
+      /* I am the child.  Nuke all other threads which I might
+	 have inherited from my parent.  POSIX mandates this. */
+      VG_(nuke_all_threads_except)( tid );
+
+      /* XXX TODO: tid 1 is special, and is presumed to be present.
+	 We should move this TID to 1 in the child. */
+
+      /* restore signal mask */
+      VG_(ksigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
+   } else {
+      MAYBE_PRINTF("   fork: process %d created child %d\n", VG_(main_pid), RES);
+
+      do_atfork_parent(tid);
+
+      /* restore signal mask */
+      VG_(ksigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
+   }
+}
+
+PRE(mknod)
+{
+   /* int mknod(const char *pathname, mode_t mode, dev_t dev); */
+   MAYBE_PRINTF("mknod ( %p, 0x%x, 0x%x )\n", ARG(1), ARG(2), ARG(3) );
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "mknod(pathname)", ARG(1) );
+}
+
+PRE(flock)
+{
+   /* int flock(int fd, int operation); */
+   MAYBE_PRINTF("flock ( %d, %d )\n", ARG(1), ARG(2) );
+}
+
+PRE(sync)
+{
+   /* int sync(); */
+   MAYBE_PRINTF("sync ( )\n");
+}
+
diff -puN /dev/null coregrind/arch/common-freebsd/vg_syscalls.c
--- /dev/null	2003-01-30 02:24:37.000000000 -0800
+++ valgrind-jeremy/coregrind/arch/common-freebsd/vg_syscalls.c	2004-01-27 11:09:10.000000000 -0800
@@ -0,0 +1,702 @@
+static
+UInt get_shm_size ( Int shmid )
+{
+   struct shmid_ds buf;
+   extern int shmctl(int, int, struct shmid_ds*);
+   int error = shmctl(shmid, IPC_STAT, &buf);
+   if (error < 0)
+      return 0;
+
+   return buf.shm_segsz;
+}
+
+PRE(__sysctl)
+{
+    /* int __sysctl(int *name, u_int namelen, void *old, size_t *oldlenp, void *new, size_t newlen); */
+    MAYBE_PRINTF("__sysctl( %p, %d, %p, %p, %p, %d )\n");
+    SYSCALL_TRACK( pre_mem_read, tid, "__sysctl(name)", arg1, arg2);
+    buf_and_len_pre_check( tid, arg3, arg4,
+			   "__sysctl(old)",
+			   "__sysctl(oldlen_in)" );
+    SYSCALL_TRACK( pre_mem_read, tid, "__sysctl(new)", arg5, arg6);
+}
+
+POST(__sysctl)
+{
+    buf_and_len_post_check( tid, res, arg3, arg4,
+			   "__sysctl(oldlen_out)" );
+}
+
+PRE(getdirentries)
+{
+   /* int getdirentries(int fd, char *buf, u_int count, long *basep); */
+   MAYBE_PRINTF("getdirentries ( %d, %p, %d, %p )\n",arg1,arg2,arg3,arg4);
+   SYSCALL_TRACK( pre_mem_write, tid, "getdents(dirp)", arg2, arg3 );
+   SYSCALL_TRACK( pre_mem_write, tid, "getdents(basep)", arg4, sizeof(UInt) );
+}
+
+POST(getdirentries)
+{
+   if (res > 0) {
+      VG_TRACK( post_mem_write, arg2, res );
+      VG_TRACK( post_mem_write, arg4, sizeof(UInt) );
+   }
+}
+
+PRE(__semctl)
+{
+   MAYBE_PRINTF("__semctl ( %d, %d, %p )\n", arg1, arg2, arg3);
+}
+
+PRE(semget)
+{
+   MAYBE_PRINTF("semget ( %d, %d, %d )\n", arg1, arg2, arg3);
+}
+
+PRE(semop)
+{
+   MAYBE_PRINTF("semop ( %d, %p, %d )\n", arg1, arg2, arg3);
+}
+
+PRE(msgctl)
+{
+   MAYBE_PRINTF("msgctl( %d %d %p )\n", arg1, arg2, arg3);
+   switch (arg2 /* cmd */) {
+   case IPC_STAT:
+      SYSCALL_TRACK( pre_mem_write, tid, "msgctl(buf)", arg3, 
+		     sizeof(struct msqid_ds) );
+      break;
+   case IPC_SET:
+      SYSCALL_TRACK( pre_mem_read, tid, "msgctl(buf)", arg3, 
+		     sizeof(struct msqid_ds) );
+      break;
+   default:
+      break;
+   }
+}
+
+POST(msgctl)
+{
+   switch (arg2 /* cmd */) {
+   case IPC_STAT:
+      if ( res > 0 ) {
+	 VG_TRACK( post_mem_write, arg3, 
+		   sizeof(struct msqid_ds) );
+      }
+      break;
+   case IPC_SET:
+      break;
+   default:
+      break;
+   }
+}
+
+PRE(msgget)
+{
+   MAYBE_PRINTF("msgget( %d, %d )\n", arg1, arg2);
+}
+
+PRE(msgsnd)
+{
+   struct mymsg *msgp = (struct mymsg *)arg2;
+   MAYBE_PRINTF("msgsnd( %d, %p, %d, %d )\n", arg1, arg2, arg3, arg4);
+   SYSCALL_TRACK( pre_mem_read, tid, "msgsnd(msgp->mtype)", 
+		  (UInt)&msgp->mtype, sizeof(msgp->mtype) );
+   SYSCALL_TRACK( pre_mem_read, tid, "msgsnd(msgp->mtext)", 
+		  (UInt)msgp->mtext, arg3 );
+}
+
+PRE(msgrcv)
+{
+   struct mymsg *msgp = (struct mymsg *)arg2;
+   Int msgsz = arg3;
+ 
+   MAYBE_PRINTF("msgrcv( %d, %p, %d, %d, %d )\n", arg1, arg2, arg3, arg4, arg5);
+   SYSCALL_TRACK( pre_mem_write, tid, "msgrcv(msgp->mtype)", 
+		  (UInt)&msgp->mtype, sizeof(msgp->mtype) );
+   SYSCALL_TRACK( pre_mem_write, tid, "msgrcv(msgp->mtext)", 
+		  (UInt)msgp->mtext, msgsz );
+}
+
+POST(msgrcv)
+{
+   struct mymsg *msgp = (struct mymsg *)arg2;
+ 
+   if ( res > 0 ) {
+      VG_TRACK( post_mem_write, (UInt)&msgp->mtype, 
+		sizeof(msgp->mtype) );
+      VG_TRACK( post_mem_write, (UInt)msgp->mtext, res );
+   }
+}
+
+PRE(shmat)
+{
+   UInt shmid = arg1;
+   UInt segmentSize = get_shm_size ( shmid );
+      
+   MAYBE_PRINTF("shmat( %d, %p, %d )\n", arg1, arg2, arg3);
+
+   /* If they didn't ask for a particular address, then place it
+      like an mmap. */
+   if (arg2 == 0)
+      arg2 = VG_(find_map_space)(0, segmentSize, True);
+   else if (!valid_client_addr(arg2, segmentSize, tid, "shmat"))
+      seterror(VKI_EINVAL);
+}
+
+POST(shmat)
+{
+   Int shmid = arg1;
+   Int shmflag = arg3;
+   Addr addr = res;
+
+   if ( addr > 0 ) { 
+      UInt segmentSize = get_shm_size ( shmid );
+      if ( segmentSize > 0 ) {
+	 UInt prot;
+	 /* we don't distinguish whether it's read-only or
+	  * read-write -- it doesn't matter really. */
+	 VG_TRACK( new_mem_mmap, addr, segmentSize, 
+		   True, True, False );
+
+	 prot = VKI_PROT_READ|VKI_PROT_WRITE;
+	 if (!(shmflag & 010000)) /* = SHM_RDONLY */
+	    prot &= ~VKI_PROT_WRITE;
+	 VG_(map_segment)(addr, segmentSize, prot,
+			  SF_SHARED | SF_SHM);
+      }
+   }
+}
+
+PRE(shmctl)
+{
+   MAYBE_PRINTF("shmctl( %d, %d, %p )\n", arg1, arg2, arg3);
+   switch (arg2) {
+   case IPC_INFO:
+      SYSCALL_TRACK( pre_mem_write, tid, "shmctl(IPC_INFO,buf)",
+		     arg3, sizeof(struct shminfo) );
+      break;
+   case SHM_INFO:
+      SYSCALL_TRACK( pre_mem_write, tid, "shmctl(SHM_INFO,buf)",
+		     arg3, sizeof(struct shm_info) );
+      break;
+   case SHM_STAT:
+   case IPC_STAT:
+      SYSCALL_TRACK( pre_mem_write, tid, "shmctl(SHM_STAT or IPC_STAT,buf)",
+		     arg3, sizeof(struct shmid_ds) );
+      break;
+   case IPC_SET:
+   case IPC_RMID:
+      SYSCALL_TRACK( pre_mem_read, tid, "shmctl(IPC_SET or IPC_RMID,buf)",
+		     arg3, sizeof(struct shmid_ds) );
+      break;
+   }
+}
+
+POST(shmctl)
+{
+   switch (arg2) {
+   case IPC_INFO:
+      VG_TRACK( post_mem_write, arg3, sizeof(struct shminfo) );
+      break;
+   case SHM_INFO:
+      VG_TRACK( post_mem_write, arg3, sizeof(struct shm_info) );
+      break;
+   case SHM_STAT:
+   case IPC_STAT:
+      VG_TRACK( post_mem_write, arg3, sizeof(struct shmid_ds) );
+      break;
+   }
+}
+
+PRE(shmdt)
+{
+   MAYBE_PRINTF("shmdt( %p )\n", arg1);
+   if (!valid_client_addr(arg1, 1, tid, "shmdt"))
+      seterror(VKI_EINVAL);
+}
+
+POST(shmdt)
+{
+   Segment *s = VG_(find_segment)(arg1);
+
+   if (s != NULL && (s->flags & SF_SHM) && VG_(seg_contains)(s, arg1, 1)) {
+      VG_TRACK( die_mem_munmap, s->addr, s->len );
+      VG_(unmap_range)(s->addr, s->len);
+   }
+}
+
+PRE(shmget)
+{
+   MAYBE_PRINTF("shmget( %d, %d, %d )\n", arg1, arg2, arg3);
+}
+
+PRE(ioctl)
+{
+   /* int ioctl(int d, int request, ...)
+      [The  "third"  argument  is traditionally char *argp, 
+      and will be so named for this discussion.]
+   */
+   size_t size = IOCPARM_LEN(arg2);
+   MAYBE_PRINTF("ioctl ( %d, 0x%x, %p )\n",arg1,arg2,arg3);
+   switch (arg2 & IOC_DIRMASK) {
+   case IOC_VOID:
+   case IOC_OUT:
+       SYSCALL_TRACK( pre_mem_write,tid, "ioctl(generic)", arg3, size);
+       break;
+   case IOC_INOUT:
+       SYSCALL_TRACK( pre_mem_write,tid, "ioctl(generic)", arg3, size);
+   case IOC_IN:
+       SYSCALL_TRACK( pre_mem_read, tid, "ioctl(generic)", arg3, size );
+   }
+}
+
+POST(ioctl)
+{
+   /* int ioctl(int d, int request, ...)
+      [The  "third"  argument  is traditionally char *argp, 
+      and will be so named for this discussion.]
+   */
+   /*
+     VG_(message)(
+     Vg_DebugMsg, 
+     "is an IOCTL,  request = 0x%x,   d = %d,   argp = 0x%x", 
+     arg2,arg1,arg3);
+   */
+   size_t size = IOCPARM_LEN(arg2);
+   MAYBE_PRINTF("ioctl ( %d, 0x%x, %p )\n",arg1,arg2,arg3);
+   switch (arg2 & IOC_DIRMASK) {
+   case IOC_VOID:
+   case IOC_IN:
+       break;
+   case IOC_OUT:
+   case IOC_INOUT:
+       VG_TRACK( post_mem_write, arg3, size );
+       break;
+   }
+}
+
+PRE(pathconf)
+{
+   /* long pathconf(const char *path, int name); */
+   MAYBE_PRINTF("pathconf ( %p(%s), %d )\n", arg1,arg1,arg2);
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "pathconf(pathname)", arg1 );
+}
+
+PRE(fpathconf)
+{
+   /* long fpathconf(int fd, int name); */
+   MAYBE_PRINTF("fpathconf ( %d, %d )\n", arg1,arg2);
+}
+
+PRE(lgetfh)
+{
+   /* int getfh(const char *path, fhandle_t *fhp); */
+   MAYBE_PRINTF("lgetfh ( %p(%s), %p )\n", arg1, arg1, arg2);
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "lgetfh(pathname)", arg1 );
+   SYSCALL_TRACK( pre_mem_write, tid, "lgetfh(fhp)", arg2, sizeof(fhandle_t) );
+}
+
+POST(lgetfh)
+{
+   VG_TRACK( post_mem_write, arg2, sizeof(fhandle_t) );
+}
+
+PRE(getfh)
+{
+   /* int getfh(const char *path, fhandle_t *fhp); */
+   MAYBE_PRINTF("getfh ( %p(%s), %p )\n", arg1, arg1, arg2);
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "getfh(pathname)", arg1 );
+   SYSCALL_TRACK( pre_mem_write, tid, "getfh(fhp)", arg2, sizeof(fhandle_t) );
+}
+
+POST(getfh)
+{
+   VG_TRACK( post_mem_write, arg2, sizeof(fhandle_t) );
+}
+
+PRE(kqueue)
+{
+   /* int kqueue(void); */
+   MAYBE_PRINTF("kqueue ( )\n");
+}
+
+PRE(kevent)
+{
+   /* int kevent(int fd, const struct kevent *changelist,
+      int nchanges, struct kevent *eventlist, int nevents,
+      const struct timespec *timeout); */
+   MAYBE_PRINTF("kevent ( %d, %p, %d, %p, %d, %p )\n", arg1, arg2, arg3, arg4, arg5, arg6);
+   SYSCALL_TRACK( pre_mem_read, tid, "kevent(changelist)",
+		  arg2, arg3 * sizeof(struct kevent) );
+   SYSCALL_TRACK( pre_mem_read, tid, "kevent(changelist)",
+		  arg2, arg3 * sizeof(struct kevent) );
+   SYSCALL_TRACK( pre_mem_write, tid, "kevent(eventlist)",
+		  arg4, arg5 * sizeof(struct kevent) );
+   if (arg6)
+      SYSCALL_TRACK( pre_mem_read, tid, "kevent(timeout)",
+		     arg6, sizeof(struct timespec) );
+}
+
+POST(kevent)
+{
+   VG_TRACK( post_mem_write, arg4, res * sizeof(struct kevent) );
+}   
+
+PRE(pipe)
+{
+    Int p[2];
+    Int error;
+
+    /* int pipe(int filedes[2]); */
+    MAYBE_PRINTF("pipe ( ) ...\n");
+    error = VG_(pipe)(p);
+    if (error >= 0) {
+	if (!fd_allowed(p[0], "pipe", tid) ||
+	    !fd_allowed(p[1], "pipe", tid)) {
+	    VG_(close)(p[0]);
+	    VG_(close)(p[1]);
+	    seterror(VKI_EMFILE);
+	} else {
+	    VG_TRACK( post_mem_write, arg1, 2*sizeof(int) );
+	    if(VG_(clo_track_fds)) {
+		record_fd_open(tid, p[0], NULL);
+		record_fd_open(tid, p[1], NULL);
+	    }
+	    tst->m_eflags &= ~EFlagC;
+	    tst->m_eax = p[0];
+	    tst->m_edx = p[1];
+	    MAYBE_PRINTF("SYSCALL[%d]       pipe --> %d (rd %d, wr %d)\n", 
+			 VG_(getpid)(), res,
+			 p[0], p[1] );
+	}
+    } else {
+	seterror(-error);
+    }
+}
+
+PRE(accept)
+{
+    /* int accept(int, struct sockaddr *, socklen_t *); */
+    MAYBE_PRINTF("accept ( %d, %p, %p )\n",arg1,arg2,arg3);
+
+    if (arg2 != (UInt)NULL) 
+	buf_and_len_pre_check ( tid, arg2, arg3,
+				"accept(name)",
+				"accept(namelen_in)" );
+}
+
+POST(accept)
+{
+   /* int accept(int, struct sockaddr *, socklen_t *); */
+   MAYBE_PRINTF("accept ( %d, %p, %p )\n",arg1,arg2,arg3);
+
+   /* Nb: name cannot be NULL */
+    if (arg2 != (UInt)NULL) 
+	buf_and_len_post_check ( tid, res, arg2, arg3,
+				 "accept(namelen_out)" );
+}
+
+PRE(bind)
+{
+    /* int bind(int, const struct sockaddr *, socklen_t); */
+    MAYBE_PRINTF("bind ( %d, %p, %d )\n",arg1,arg2,arg3);
+    
+    pre_mem_read_sockaddr( tid, "bind(my_addr.%s)",
+			   (struct sockaddr *) arg2, arg3);
+}
+
+PRE(connect)
+{
+    /* int connect(int, const struct sockaddr *, socklen_t); */
+    MAYBE_PRINTF("connect ( %d, %p, %d )\n",arg1,arg2,arg3);
+    
+    pre_mem_read_sockaddr( tid, "connect(my_addr.%s)",
+			   (struct sockaddr *) arg2, arg3);
+}
+
+PRE(getpeername)
+{
+   /* int getpeername(int, struct sockaddr *, socklen_t *); */
+   MAYBE_PRINTF("getpeername ( %d, %p, %p )\n",arg1,arg2,arg3);
+
+   /* Nb: name cannot be NULL */
+   buf_and_len_pre_check ( tid, arg2, arg3,
+			   "getpeername(name)",
+			   "getpeername(namelen_in)" );
+}
+
+POST(getpeername)
+{
+   /* int getpeername(int, struct sockaddr *, socklen_t *); */
+   MAYBE_PRINTF("getpeername ( %d, %p, %p )\n",arg1,arg2,arg3);
+
+   /* Nb: name cannot be NULL */
+   buf_and_len_post_check ( tid, res, arg2, arg3,
+			   "getpeername(namelen_out)" );
+}
+
+PRE(getsockname)
+{
+   /* int getsockname(int, struct sockaddr *, socklen_t *); */
+   MAYBE_PRINTF("getsockname ( %d, %p, %p )\n",arg1,arg2,arg3);
+
+   /* Nb: name cannot be NULL */
+   buf_and_len_pre_check ( tid, arg2, arg3,
+			   "getsockname(name)",
+			   "getsockname(namelen_in)" );
+}
+
+POST(getsockname)
+{
+   /* int getsockname(int, struct sockaddr *, socklen_t *); */
+   MAYBE_PRINTF("getsockname ( %d, %p, %p )\n",arg1,arg2,arg3);
+
+   /* Nb: name cannot be NULL */
+   buf_and_len_post_check ( tid, res, arg2, arg3,
+			   "getsockname(namelen_out)" );
+}
+
+PRE(getsockopt)
+{
+    /* int getsockopt(int, int, int, void *, socklen_t *); */
+    MAYBE_PRINTF("getsockopt ( %d, %d, %d, %p, %p )\n",arg1,arg2,arg3,arg4,arg5);
+    if (arg4 != (UInt)NULL)
+	buf_and_len_pre_check ( tid, arg4, arg5,
+				"getsockopt(opt)",
+				"getsockopt(optlen_in)" );
+}
+
+POST(getsockopt)
+{
+    /* int getsockopt(int, int, int, void *, socklen_t *); */
+
+    if (arg4 != (UInt)NULL)
+	buf_and_len_post_check ( tid, res, arg4, arg5,
+				 "getsockopt(optlen_out)" );
+
+}
+
+PRE(listen)
+{
+   /* int listen(int, int); */
+   MAYBE_PRINTF("listen ( %d, %d )\n",arg1,arg2);
+}
+
+PRE(recvfrom)
+{
+    /* ssize_t recvfrom(int, void *, size_t, int, struct sockaddr *, socklen_t *); */
+    MAYBE_PRINTF("recvfrom ( %d, %p, %d, %d, %p, %p )\n",arg1,arg2,arg3,arg4,arg5,arg6);
+
+    SYSCALL_TRACK( pre_mem_write, tid, "recvfrom(buf)", arg2, arg3);
+    if (arg5 != (UInt)NULL)
+	buf_and_len_pre_check ( tid, arg5, arg6,
+				"recvfrom(addr)",
+				"recvfrom(addrlen_in)" );
+}
+
+POST(recvfrom)
+{
+    /* ssize_t recvfrom(int, void *, size_t, int, struct sockaddr *, socklen_t *); */
+   if (arg5 != (UInt)NULL)
+      buf_and_len_post_check ( tid, res, arg5, arg6,
+			       "recvfrom(addrlen_out)" );
+   VG_TRACK( post_mem_write, arg2, arg3 );
+}
+
+PRE(recvmsg)
+{
+   /* ssize_t recvmsg(int, struct msghdr *, int); */
+   struct msghdr *msg = (struct msghdr *)arg2;
+
+   MAYBE_PRINTF("recvmsg ( %d, %p, %d )\n", arg1, arg2, arg3);
+   
+   msghdr_foreachfield ( tid, msg, pre_mem_write_recvmsg );
+}
+
+POST(recvmsg)
+{
+   struct msghdr *msg = (struct msghdr *)arg2;
+
+   msghdr_foreachfield( tid, msg, post_mem_write_recvmsg );
+   check_cmsg_for_fds( tid, msg );
+}
+
+PRE(sendto)
+{
+    /* ssize_t send(int, const void *, size_t, int, const struct sockaddr *, socklen_t); */
+   MAYBE_PRINTF("sendto ( %d, %p, %d, %d, %p, %d )\n",arg1,arg2,arg3,arg4,arg5,arg6);
+
+   SYSCALL_TRACK( pre_mem_read, tid, "sendto(buf)", arg2, arg3);
+   pre_mem_read_sockaddr( tid, "sendto(to.%s)",
+			  (struct sockaddr *) arg5, arg6 );
+}
+
+PRE(sendmsg)
+{
+    /* ssize_t sendmsg(int, const struct msghdr *, int); */
+    MAYBE_PRINTF("sendmsg ( %d, %p, %d )\n",arg1,arg2,arg3);
+
+    struct msghdr *msg = (struct msghdr *)arg2;
+    msghdr_foreachfield ( tid, msg, pre_mem_read_sendmsg );
+}
+
+PRE(setsockopt)
+{
+    /*int setsockopt(int, int, int, const void *, socklen_t); */
+    MAYBE_PRINTF("setsockopt ( %d, %d, %d, %p, %d )\n",arg1,arg2,arg3,arg4,arg5);
+    SYSCALL_TRACK( pre_mem_read, tid, "setsockopt(optval)", arg4, arg5 );
+}
+
+PRE(shutdown)
+{
+    /* int shutdown(int, int); */
+    MAYBE_PRINTF("shutdown ( %d, %d )\n",arg1,arg2);
+}
+
+PRE(socket)
+{
+   /* int socket(int, int, int); */
+   MAYBE_PRINTF("socket ( %d, %d, %d )\n",arg1,arg2,arg3);
+}
+
+PRE(socketpair)
+{
+    /* int socketpair(int, int, int, int *); */
+    MAYBE_PRINTF("socketpair( %d, %d, %d, %p )\n",arg1,arg2,arg3,arg4);
+    SYSCALL_TRACK( pre_mem_write, tid, "socketpair(sv)", 
+		   arg4, 2*sizeof(int) );
+}
+
+POST(socketpair)
+{
+    VG_TRACK( post_mem_write, arg4, 2*sizeof(int) );
+    if(VG_(clo_track_fds)) {
+	record_fd_open(tid, ((UInt*)arg4)[0], NULL);
+	record_fd_open(tid, ((UInt*)arg4)[1], NULL);
+    }
+}
+
+PRE(getdtablesize)
+{
+    /* int getdtablesize(void); */
+    MAYBE_PRINTF("getdtablesize( )\n");
+}
+
+PRE(adjtimex)
+{
+   struct timex *tx = (struct timex *)arg1;
+   MAYBE_PRINTF("adjtimex ( %p )\n", arg1);
+
+   SYSCALL_TRACK(pre_mem_read, tid, "adjtimex(timex->modes)", arg1, sizeof(tx->modes));
+
+#define ADJX(bit,field) 				\
+   if (tx->modes & bit)					\
+      SYSCALL_TRACK(pre_mem_read, tid,			\
+		    "adjtimex(timex->"#field")",	\
+		    (UInt)&tx->field, sizeof(tx->field))
+   ADJX(MOD_OFFSET, offset);
+   ADJX(MOD_FREQUENCY, freq);
+   ADJX(MOD_MAXERROR, maxerror);
+   ADJX(MOD_ESTERROR, esterror);
+   ADJX(MOD_STATUS, status);
+   ADJX(MOD_TIMECONST, constant);
+   ADJX(MOD_PPSMAX, shift);
+   ADJX(MOD_TAI, constant);
+#undef ADJX
+   
+   SYSCALL_TRACK(pre_mem_write, tid, "adjtimex(timex)", arg1, sizeof(struct timex));
+}
+
+POST(adjtimex)
+{
+   VG_TRACK(post_mem_write, arg1, sizeof(struct timex));
+}
+
+/*
+ * This is normally only ever used for mmap and lseek (for hysterical raisins).
+ */
+
+PRE(__syscall)
+{
+    if (ARG(1) == __NR_mmap) {
+	/* void* mmap(void *start, size_t length, int prot, 
+	   int flags, int fd, int pad, off_t offset); 
+	*/
+	UInt* args = ((UInt*) tst->m_esp) + 3;
+	Addr start = args[0];
+	size_t length = args[1];
+	int prot = args[2];
+	int flags = args[3];
+	int fd = args[4];
+	off_t offset = (off_t)args[6] + (((off_t)args[7])<<32);
+	MAYBE_PRINTF("__syscall.mmap ( %p, %d, %d, %d, %d, %lld )\n",
+		     start, length, prot, flags, fd, offset);
+
+	RES = 0;
+	if (flags & VKI_MAP_FIXED) {
+		if (!valid_client_addr(start, length, tid, "mmap")) {
+			MAYBE_PRINTF("mmap failing: %p-%p\n", start, start+length);
+			seterror(VKI_ENOMEM);
+		}
+	} else {
+		start = VG_(find_map_space)(start, length, True);
+		if (start == 0)
+			seterror(VKI_ENOMEM);
+		else
+			flags |= VKI_MAP_FIXED;
+	}
+
+	if (RES != VKI_ENOMEM) {
+		RES = (Int)VG_(mmap)((void *)start, length, prot, flags | VKI_MAP_CLIENT, fd, offset);
+      
+		if (RES == -1)
+			seterror(VKI_ENOMEM);
+		else if (!valid_client_addr(RES, length, tid, "mmap")) {
+			VG_(munmap)((void *)RES, length);
+			seterror(VKI_ENOMEM);
+		} else
+			mmap_segment( (Addr)RES, length, prot, flags, fd, offset );
+	}
+    } else if (ARG(1) == __NR_lseek) {
+	/* off_t lseek(int fd, int pad, off_t offset, int whence); */
+	UInt* args = ((UInt*) tst->m_esp) + 3;
+	int fd = args[0];
+	off_t off = args[2] + (((off_t)args[3])<<32);
+	int whence = args[4];
+	ULong newoff;
+	MAYBE_PRINTF("__syscall.lseek( %d, %lld, %d )\n", fd, off, whence);
+	newoff = VG_(do_syscall_err)(__NR_lseek,
+				     tst->m_edx,
+				     &tst->m_eflags,
+				     fd, 0, off, whence);
+	tst->m_eax = newoff;
+	tst->m_edx = newoff >> 32;
+    } else {
+	VG_(printf)("__syscall(%d, ...)\n", ARG(1));
+	VG_(core_panic)("unsupported call to __syscall");
+    }
+}
+
+POST(__syscall)
+{
+}
+
+PRE(select)
+{
+   /* int  select(int, fd_set *, fd_set *, fd_set *, struct timeval *); */
+   MAYBE_PRINTF("select ( %d, %p, %p, %p, %p )\n", 
+       arg1,arg2,arg3,arg4,arg5);
+   if (arg2 != (Addr)NULL)
+	   SYSCALL_TRACK( pre_mem_read, tid, "select(readfds)", arg2, 
+	       arg1/8 /* __FD_SETSIZE/8 */ );
+   if (arg3 != (Addr)NULL)
+	   SYSCALL_TRACK( pre_mem_read, tid, "select(writefds)", arg3, 
+	       arg1/8 /* __FD_SETSIZE/8 */ );
+   if (arg4 != (Addr)NULL)
+	   SYSCALL_TRACK( pre_mem_read, tid, "select(exceptfds)", arg4, 
+	       arg1/8 /* __FD_SETSIZE/8 */ );
+   if (arg5 != (Addr)NULL)
+	   SYSCALL_TRACK( pre_mem_read, tid, "select(timeout)", arg5, 
+	       sizeof(struct timeval) );
+}
diff -puN /dev/null coregrind/arch/i386-freebsd/vg_syscalls.c
--- /dev/null	2003-01-30 02:24:37.000000000 -0800
+++ valgrind-jeremy/coregrind/arch/i386-freebsd/vg_syscalls.c	2004-01-27 11:28:23.000000000 -0800
@@ -0,0 +1,263 @@
+#define SYSNO	(tst->m_eax)		/* in PRE(x)  */
+#define res	(tst->m_eax)	/* in POST(x) */
+#define ARG(n)	(((UInt*)(tst->m_esp))[n])
+#define SETARG(n, v) (((UInt*)(tst->m_esp))[n] = (v))
+
+static void run_syscall(UInt syscallno, ThreadState *tst);
+static Bool valid_client_addr(Addr start, UInt size, ThreadId tid, const Char *syscall);
+
+#include "../common-unix/vg_syscalls.c"
+#include "../common-freebsd/vg_syscalls.c"
+
+/* return true if address range entirely contained within client
+   address space */
+static Bool valid_client_addr(Addr start, UInt size, ThreadId tid, const Char *syscall)
+{
+   Addr end = start+size;
+   Addr cl_base = VG_(client_base);
+   Bool ret;
+
+   if (size == 0)
+      return True;
+
+   if (cl_base < 0x10000)
+      cl_base = 0x10000;
+
+   ret =
+      (end >= start) && 
+      start >= cl_base && start < VG_(client_end) &&
+      (end <= VG_(client_end));
+
+   if (0)
+      VG_(printf)("%s: test=%p-%p client=%p-%p ret=%d\n",
+		  syscall, start, end, cl_base, VG_(client_end), ret);
+
+   if (!ret && syscall != NULL) {
+      VG_(message)(Vg_UserMsg, "Warning: client syscall %s tried to modify addresses %p-%p",
+		   syscall, start, end);
+
+      if (VG_(clo_verbosity) > 1) {
+	 ExeContext *ec = VG_(get_ExeContext)(tid);
+	 VG_(pp_ExeContext)(ec);
+      }
+   }
+
+   return ret;
+}
+
+PRE(sysarch)
+{
+    Int error;
+    UInt *args = (UInt*) ARG(2);
+
+    /* int sysarch(int number, void *args); */
+    switch (ARG(1)) {
+    case 0:			/* get ldt */
+	MAYBE_PRINTF("sysarch.get_ldt ( %d, %p, %d )\n", args[0], args[1], args[2]);
+	SYSCALL_TRACK( pre_mem_write, tid,
+		       "sysarch.get_ldt(args)", (Addr)args, 3*sizeof(UInt));
+	SYSCALL_TRACK( pre_mem_write, tid,
+		       "sysarch.set_ldt(descs)",
+		       (Addr)args[1],
+		       args[2]*sizeof(ULong) );
+	error = VG_(sys_get_ldt)(tid, args[0], (ULong*)args[1], args[2]);
+	if (error < 0)
+	    seterror(-error);
+	else
+	    res = 0;
+	break;
+    case 1:			/* set ldt */
+	MAYBE_PRINTF("sysarch.set_ldt ( %d, %p, %d )\n", args[0], args[1], args[2]);
+	SYSCALL_TRACK( pre_mem_read, tid,
+		       "sysarch.set_ldt(args)", (Addr)args, 3*sizeof(UInt));
+	SYSCALL_TRACK( pre_mem_read, tid,
+		       "sysarch.set_ldt(descs)",
+		       (Addr)args[1],
+		       args[2]*sizeof(ULong) );
+	error = VG_(sys_set_ldt)(tid, &args[0], (ULong*)args[1], args[2]);
+	if (error < 0)
+	    seterror(-error);
+	else
+	    res = 0;
+	break;
+    case 3:			/* get ioperm */
+	SYSCALL_TRACK( pre_mem_write, tid,
+		       "sysarch.get_ioperm(args)", ARG(2), 3*sizeof(UInt));
+	tst->m_eax = VG_(do_syscall_err)(__NR_sysarch,
+					 tst->m_edx,
+					 &tst->m_eflags,
+					 ARG(1), ARG(2));
+	break;
+    case 4:			/* set ioperm */
+	SYSCALL_TRACK( pre_mem_read, tid,
+		       "sysarch.set_ioperm(args)", ARG(2), 3*sizeof(UInt));
+	tst->m_eax = VG_(do_syscall_err)(__NR_sysarch,
+					 tst->m_edx,
+					 &tst->m_eflags,
+					 ARG(1), ARG(2));
+	break;
+    case 6:			/* vm86 */
+	tst->m_eax = VG_(do_syscall_err)(__NR_sysarch,
+					 tst->m_edx,
+					 &tst->m_eflags,
+					 ARG(1), ARG(2));
+	break;
+    default:
+	VG_(core_panic)("Unhandled sysarch call");
+    }
+}
+
+POST(sysarch)
+{
+    switch (ARG(1)) {
+    case 0:			/* get ldt */
+	VG_TRACK( post_mem_write, ARG(2), 3*sizeof(UInt) );
+	VG_TRACK( post_mem_write, (Addr)((UInt*)ARG(2))[1],
+		  ((UInt*)ARG(2))[2]*sizeof(ULong) );
+	break;
+    case 1:			/* set ldt */
+	VG_TRACK( post_mem_write, ARG(2), sizeof(UInt) );
+	break;
+    case 3:			/* get ioperm */
+	VG_TRACK( post_mem_write, ARG(2), 3*sizeof(UInt));
+	break;
+    case 4:			/* set ioperm */
+	break;
+    case 6:			/* vm86 */
+	break;
+    default:
+	VG_(core_panic)("Unhandled sysarch call");
+    }
+}
+
+PRE(getcontext)
+{
+    /* int getcontext(struct __ucontext *ucp); */
+    MAYBE_PRINTF("getcontext ( %p )\n", ARG(1));
+    SYSCALL_TRACK( pre_mem_write, tid, "getcontext(ucp)", ARG(1), sizeof(vki_ucontext_t) );
+}
+
+POST(getcontext)
+{
+    VG_TRACK( post_mem_write, ARG(1), sizeof(vki_ucontext_t) );
+}
+
+PRE(setcontext)
+{
+    /* int setcontext(const struct __ucontext *ucp); */
+    MAYBE_PRINTF("setcontext ( %p )\n", ARG(1));
+    SYSCALL_TRACK( pre_mem_read, tid, "setcontext(ucp)", ARG(1), sizeof(vki_ucontext_t) );
+}
+
+PRE(pathconf)
+{
+   /* long pathconf(const char *path, int name); */
+   MAYBE_PRINTF("pathconf ( %p(%s), %d )\n", ARG(1),ARG(1),ARG(2));
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "pathconf(pathname)", ARG(1) );
+}
+
+PRE(fpathconf)
+{
+   /* long fpathconf(int fd, int name); */
+   MAYBE_PRINTF("fpathconf ( %d, %d )\n", ARG(1),ARG(2));
+}
+
+PRE(lgetfh)
+{
+   /* int getfh(const char *path, fhandle_t *fhp); */
+   MAYBE_PRINTF("lgetfh ( %p(%s), %p )\n", ARG(1), ARG(1), ARG(2));
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "lgetfh(pathname)", ARG(1) );
+   SYSCALL_TRACK( pre_mem_write, tid, "lgetfh(fhp)", ARG(2), sizeof(fhandle_t) );
+}
+
+POST(lgetfh)
+{
+   VG_TRACK( post_mem_write, ARG(2), sizeof(fhandle_t) );
+}
+
+PRE(getfh)
+{
+   /* int getfh(const char *path, fhandle_t *fhp); */
+   MAYBE_PRINTF("getfh ( %p(%s), %p )\n", ARG(1), ARG(1), ARG(2));
+   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "getfh(pathname)", ARG(1) );
+   SYSCALL_TRACK( pre_mem_write, tid, "getfh(fhp)", ARG(2), sizeof(fhandle_t) );
+}
+
+POST(getfh)
+{
+   VG_TRACK( post_mem_write, ARG(2), sizeof(fhandle_t) );
+}
+
+PRE(kqueue)
+{
+   /* int kqueue(void); */
+   MAYBE_PRINTF("kqueue ( )\n");
+}
+
+PRE(kevent)
+{
+   /* int kevent(int fd, const struct kevent *changelist,
+      int nchanges, struct kevent *eventlist, int nevents,
+      const struct timespec *timeout); */
+   MAYBE_PRINTF("kevent ( %d, %p, %d, %p, %d, %p )\n", ARG(1), ARG(2), ARG(3), ARG(4), ARG(5), ARG(6));
+   SYSCALL_TRACK( pre_mem_read, tid, "kevent(changelist)",
+		  ARG(2), ARG(3) * sizeof(struct kevent) );
+   SYSCALL_TRACK( pre_mem_read, tid, "kevent(changelist)",
+		  ARG(2), ARG(3) * sizeof(struct kevent) );
+   SYSCALL_TRACK( pre_mem_write, tid, "kevent(eventlist)",
+		  ARG(4), ARG(5) * sizeof(struct kevent) );
+   if (ARG(6))
+      SYSCALL_TRACK( pre_mem_read, tid, "kevent(timeout)",
+		     ARG(6), sizeof(struct timespec) );
+}
+
+POST(kevent)
+{
+   VG_TRACK( post_mem_write, ARG(4), res * sizeof(struct kevent) );
+}   
+
+void VG_(restart_syscall)(ThreadId tid)
+{
+   ThreadState* tst;
+   tst = VG_(get_ThreadState)(tid);
+
+   vg_assert(tst != NULL);
+   vg_assert(tst->status == VgTs_WaitSys);
+   vg_assert(tst->syscallno != -1);
+
+   tst->m_eax = tst->syscallno;
+   tst->m_eip -= 2;		/* sizeof(int $0x80) */
+
+   /* Make sure our caller is actually sane, and we're really backing
+      back over a syscall.
+
+      int $0x80 == CD 80 
+   */
+   {
+      UChar *p = (UChar *)tst->m_eip;
+      
+      if (p[0] != 0xcd || p[1] != 0x80)
+	 VG_(message)(Vg_DebugMsg, 
+		      "?! restarting over syscall at %p %02x %02x\n",
+		      tst->m_eip, p[0], p[1]);
+
+      vg_assert(p[0] == 0xcd && p[1] == 0x80);
+   }
+}
+
+static void run_syscall(UInt syscallno, ThreadState *tst)
+{
+   UInt* sp = (UInt*) tst->m_esp;
+   ULong retval;
+   retval = VG_(do_syscall_err)(syscallno,
+				tst->m_edx,
+				&tst->m_eflags,
+				sp[1],
+				sp[2],
+				sp[3],
+				sp[4],
+				sp[5],
+				sp[6]);
+   tst->m_eax = retval;
+   tst->m_edx = retval >> 32;
+}
diff -puN -L include/vg_kerneliface.h include/vg_kerneliface.h~archdep /dev/null
--- valgrind/include/vg_kerneliface.h
+++ /dev/null	2003-01-30 02:24:37.000000000 -0800
@@ -1,747 +0,0 @@
-
-/*--------------------------------------------------------------------*/
-/*--- A header file defining structures and constants which are    ---*/
-/*--- important at the kernel boundary for this platform.          ---*/
-/*---                                             vg_kerneliface.h ---*/
-/*--------------------------------------------------------------------*/
-
-/*
-   This file is part of Valgrind, an extensible x86 protected-mode
-   emulator for monitoring program execution on x86-Unixes.
-
-   Copyright (C) 2000-2004 Julian Seward 
-      jseward@acm.org
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307, USA.
-
-   The GNU General Public License is contained in the file COPYING.
-*/
-
-#ifndef __VG_KERNELIFACE_H
-#define __VG_KERNELIFACE_H
-
-/* This file is ONLY to be included into vg_include.h.  Do not include
-   it directly into valgrind source .c files.  This file defines types
-   and constants for the kernel interface, and to make that clear
-   everything is prefixed VKI. */
-
-/*--- All the following stuff is correct for Linux kernels 2.2.X and
-      2.4.X. 
----*/
-
-/* Should really get this from an include file somewhere. */
-#define VKI_BYTES_PER_PAGE_BITS 12
-#define VKI_BYTES_PER_PAGE (1 << VKI_BYTES_PER_PAGE_BITS)
-
-#define VKI_BYTES_PER_WORD 4
-#define VKI_WORDS_PER_PAGE (VKI_BYTES_PER_PAGE / VKI_BYTES_PER_WORD)
-
-
-/* An implementation of signal sets.  These are the same as the sigset
-   implementations in the relevant Linux kernels.  Note carefully that
-   this has nothing to do with glibc's signal sets.  We work entirely
-   at the kernel boundary, so the libc stuff is invisible and
-   irrelevant.  */
-
-/* The following is copied from
-   /usr/src/linux-2.4.9-13/include/asm-i386/signal.h */
-#define VKI_KNSIG       64  /* true for linux 2.2.X and 2.4.X */
-#define VKI_KNSIG_BPW   32  /* since we're using UInts */
-#define VKI_KNSIG_WORDS (VKI_KNSIG / VKI_KNSIG_BPW)
-
-typedef 
-   struct { 
-      UInt ws[VKI_KNSIG_WORDS]; 
-   }
-   vki_ksigset_t;
-
-
-typedef
-   struct {
-      void*         ksa_handler;
-      unsigned long ksa_flags;
-      void (*ksa_restorer)(void);
-      vki_ksigset_t ksa_mask;
-   }
-   vki_ksigaction;
-
-typedef 
-   struct {
-      void* ss_sp;
-      Int   ss_flags;
-      UInt  ss_size;
-   } 
-   vki_kstack_t;
-
-#define SI_MAX_SIZE	128
-#define SI_PAD_SIZE	((SI_MAX_SIZE/sizeof(int)) - 3)
-
-union vki_sigval {
-   Int sival_int;
-   void *sival_ptr;
-};
-
-typedef
-   struct {
-      Int si_signo;
-      Int si_errno;
-      Int si_code;
-
-      union {
-	 Int _pad[SI_PAD_SIZE];
-
-	 /* kill() */
-	 struct {
-	    Int _pid;		/* sender's pid */
-	    Short _uid;		/* sender's uid */
-	 } _kill;
-
-	 /* POSIX.1b timers */
-	 struct {
-	    UInt _timer1;
-	    UInt _timer2;
-	 } _timer;
-
-	 /* POSIX.1b signals */
-	 struct {
-	    Int _pid;		/* sender's pid */
-	    UShort _uid;		/* sender's uid */
-	    union vki_sigval _sigval;
-	 } _rt;
-
-	 /* SIGCHLD */
-	 struct {
-	    Int _pid;		/* which child */
-	    UShort _uid;		/* sender's uid */
-	    Int _status;		/* exit code */
-	    Int _utime;
-	    Int _stime;
-	 } _sigchld;
-
-	 /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
-	 struct {
-	    void *_addr; /* faulting insn/memory ref. */
-	 } _sigfault;
-
-	 /* SIGPOLL */
-	 struct {
-	    Int _band;	/* POLL_IN, POLL_OUT, POLL_MSG */
-	    Int _fd;
-	 } _sigpoll;
-      } _sifields;
-   } vki_ksiginfo_t;
-
-/* linux-2.6/include/asm-generic/siginfo.h */
-
-#define VKI_SI_USER	0
-#define VKI_SI_QUEUE	-1
-#define VKI_SI_TKILL	-6
-
-struct vki_fpreg {
-	UShort significand[4];
-	UShort exponent;
-};
-
-struct vki_fpxreg {
-	UShort significand[4];
-	UShort exponent;
-	UShort padding[3];
-};
-
-struct vki_xmmreg {
-	UInt element[4];
-};
-
-struct vki_fpstate {
-	/* Regular FPU environment */
-	unsigned long 	cw;
-	unsigned long	sw;
-	unsigned long	tag;
-	unsigned long	ipoff;
-	unsigned long	cssel;
-	unsigned long	dataoff;
-	unsigned long	datasel;
-	struct vki_fpreg	_st[8];
-	unsigned short	status;
-	unsigned short	magic;		/* 0xffff = regular FPU data only */
-
-	/* FXSR FPU environment */
-	unsigned long	_fxsr_env[6];	/* FXSR FPU env is ignored */
-	unsigned long	mxcsr;
-	unsigned long	reserved;
-	struct vki_fpxreg	_fxsr_st[8];	/* FXSR FPU reg data is ignored */
-	struct vki_xmmreg	_xmm[8];
-	unsigned long	padding[56];
-};
-
-#define X86_FXSR_MAGIC		0x0000
-
-struct vki_sigcontext {
-	UShort	gs, __gsh;
-	UShort	fs, __fsh;
-	UShort	es, __esh;
-	UShort	ds, __dsh;
-	UInt	edi;
-	UInt	esi;
-	UInt	ebp;
-	UInt	esp;
-	UInt	ebx;
-	UInt	edx;
-	UInt	ecx;
-	UInt	eax;
-	UInt	trapno;
-	UInt	err;
-	UInt	eip;
-	UShort	cs, __csh;
-	UInt	eflags;
-	UInt	esp_at_signal;
-	UShort	ss, __ssh;
-	struct	vki_fpstate * fpstate;
-	UInt	oldmask;
-	UInt	cr2;
-};
-
-struct vki_ucontext {
-	UInt		  uc_flags;
-	struct vki_ucontext  *uc_link;
-	vki_kstack_t	  uc_stack;
-	struct vki_sigcontext uc_mcontext;
-	vki_ksigset_t	  uc_sigmask;	/* mask last for extensibility */
-};
-
-
-/* sigaltstack controls */
-#define VKI_SS_ONSTACK      1
-#define VKI_SS_DISABLE      2
-
-#define VKI_MINSIGSTKSZ     2048
-#define VKI_SIGSTKSZ        8192
-
-
-
-#define VKI_SIG_BLOCK          0    /* for blocking signals */
-#define VKI_SIG_UNBLOCK        1    /* for unblocking signals */
-#define VKI_SIG_SETMASK        2    /* for setting the signal mask */
-
-#define VKI_SIG_DFL ((void*)0)     /* default signal handling */
-#define VKI_SIG_IGN ((void*)1)     /* ignore signal */
-#define VKI_SIG_ERR ((void*)-1)    /* error return from signal */
-
-#define VKI_SA_ONSTACK      0x08000000
-#define VKI_SA_RESTART      0x10000000
-#define VKI_SA_NOCLDSTOP    0x00000001
-#define VKI_SA_SIGINFO      0x00000004
-#define VKI_SA_RESETHAND    0x80000000
-#define VKI_SA_ONESHOT      VKI_SA_RESETHAND
-#define VKI_SA_NODEFER      0x40000000
-#define VKI_SA_NOMASK       VKI_SA_NODEFER
-#define VKI_SA_NOCLDWAIT    0x00000002
-#if 0
-#define VKI_SA_INTERRUPT    0x20000000 /* dummy -- ignored */
-#define VKI_SA_RESTORER     0x04000000
-#endif
-
-/* extra wait flags */
-#define	VKI_WNOHANG	1		/* Don't block waiting.  */
-#define	VKI_WUNTRACED	2		/* Report status of stopped children.  */
-#define VKI__WALL	0x40000000	/* Wait for any child.  */
-#define VKI__WCLONE	0x80000000	/* Wait for cloned process.  */
-
-#define	VKI_SIGHUP	1	/* Hangup (POSIX).  */
-#define	VKI_SIGINT	2	/* Interrupt (ANSI).  */
-#define	VKI_SIGQUIT	3	/* Quit (POSIX).  */
-#define	VKI_SIGILL	4	/* Illegal instruction (ANSI).  */
-#define	VKI_SIGTRAP	5	/* Trace trap (POSIX).  */
-#define	VKI_SIGABRT	6	/* Abort (ANSI).  */
-#define	VKI_SIGIOT	6	/* IOT trap (4.2 BSD).  */
-#define	VKI_SIGBUS	7	/* BUS error (4.2 BSD).  */
-#define	VKI_SIGFPE	8	/* Floating-point exception (ANSI).  */
-#define	VKI_SIGKILL	9	/* Kill, unblockable (POSIX).  */
-#define	VKI_SIGUSR1	10	/* User-defined signal 1 (POSIX).  */
-#define	VKI_SIGSEGV	11	/* Segmentation violation (ANSI).  */
-#define	VKI_SIGUSR2	12	/* User-defined signal 2 (POSIX).  */
-#define	VKI_SIGPIPE	13	/* Broken pipe (POSIX).  */
-#define	VKI_SIGALRM	14	/* Alarm clock (POSIX).  */
-#define	VKI_SIGTERM	15	/* Termination (ANSI).  */
-#define	VKI_SIGSTKFLT	16	/* Stack fault.  */
-#define	VKI_SIGCLD	SIGCHLD	/* Same as SIGCHLD (System V).  */
-#define	VKI_SIGCHLD	17	/* Child status has changed (POSIX).  */
-#define	VKI_SIGCONT	18	/* Continue (POSIX).  */
-#define	VKI_SIGSTOP	19	/* Stop, unblockable (POSIX).  */
-#define	VKI_SIGTSTP	20	/* Keyboard stop (POSIX).  */
-#define	VKI_SIGTTIN	21	/* Background read from tty (POSIX).  */
-#define	VKI_SIGTTOU	22	/* Background write to tty (POSIX).  */
-#define	VKI_SIGURG	23	/* Urgent condition on socket (4.2 BSD).  */
-#define	VKI_SIGXCPU	24	/* CPU limit exceeded (4.2 BSD).  */
-#define	VKI_SIGXFSZ	25	/* File size limit exceeded (4.2 BSD).  */
-#define	VKI_SIGVTALRM	26	/* Virtual alarm clock (4.2 BSD).  */
-#define	VKI_SIGPROF	27	/* Profiling alarm clock (4.2 BSD).  */
-#define	VKI_SIGWINCH	28	/* Window size change (4.3 BSD, Sun).  */
-#define	VKI_SIGPOLL	SIGIO	/* Pollable event occurred (System V).  */
-#define	VKI_SIGIO	29	/* I/O now possible (4.2 BSD).  */
-#define	VKI_SIGPWR	30	/* Power failure restart (System V).  */
-#define	VKI_SIGSYS	31	/* Bad system call.  */
-#define	VKI_SIGUNUSED	31
-
-#define VKI_SIGRTMIN	    32
-#define VKI_SIGRTMAX	    63
-
-#define VKI_SIGVGINT	    (VKI_SIGRTMIN+0) /* signal for internal use - interrupt */
-#define VKI_SIGVGKILL	    (VKI_SIGRTMIN+1) /* signal for internal use - kill */
-#define VKI_SIGRTUSERMIN    (VKI_SIGRTMIN+2) /* first user-usable RT signal */
-
-/* The following are copied from include/asm-i386/mman.h .*/
-
-#define VKI_PROT_NONE      0x0		   /* No page permissions */
-#define VKI_PROT_READ      0x1             /* Page can be read.  */
-#define VKI_PROT_WRITE     0x2             /* Page can be written.  */
-#define VKI_PROT_EXEC      0x4             /* Page can be executed.  */
-#define VKI_MAP_ANONYMOUS  0x20            /* Don't use a file.  */
-#define VKI_MAP_SHARED	   0x01		   /* Share changes.  */
-#define VKI_MAP_PRIVATE    0x02            /* Changes are private.  */
-#define VKI_MAP_FIXED      0x10            /* Interpret addr exactly */
-#define VKI_MAP_NOSYMS     0x40000000	   /* internal pseudo-flag to disable symbol loading */
-#define VKI_MAP_CLIENT     0x80000000	   /* internal pseudo-flag to distinguish client mappings */
-
-/* linux/mman.h */
-#define VKI_MREMAP_MAYMOVE	1
-#define VKI_MREMAP_FIXED	2
-
-/* Copied from linux-2.4.19/include/asm-i386/fcntl.h */
-
-#define VKI_O_ACCMODE	       0003
-#define VKI_O_RDONLY             00
-#define VKI_O_WRONLY             01
-#define VKI_O_RDWR               02
-#define VKI_O_CREAT            0100 /* not fcntl */
-#define VKI_O_EXCL             0200 /* not fcntl */
-#define VKI_O_TRUNC           01000 /* not fcntl */
-#define VKI_O_APPEND          02000
-#define VKI_O_NONBLOCK        04000
-#define VKI_O_SYNC           010000
-#define VKI_FASYNC           020000 /* fcntl, for BSD compatibility */
-#define VKI_O_DIRECT         040000 /* direct disk access hint */
-#define VKI_O_LARGEFILE     0100000
-#define VKI_O_DIRECTORY     0200000 /* must be a directory */
-#define VKI_O_NOFOLLOW      0400000 /* don't follow links */
-
-#define VKI_SEEK_SET              0
-#define VKI_SEEK_CUR              1
-#define VKI_SEEK_END              2
-
-/* Copied from linux-2.4.19/include/linux/stat.h */
-
-#define VKI_S_IRWXU 00700
-#define VKI_S_IRUSR 00400
-#define VKI_S_IWUSR 00200
-#define VKI_S_IXUSR 00100
-
-#define VKI_S_IRWXG 00070
-#define VKI_S_IRGRP 00040
-#define VKI_S_IWGRP 00020
-#define VKI_S_IXGRP 00010
-
-#define VKI_S_IRWXO 00007
-#define VKI_S_IROTH 00004
-#define VKI_S_IWOTH 00002
-#define VKI_S_IXOTH 00001
-
-
-/* Copied from /usr/src/linux-2.4.9-13/include/asm/errno.h */
-
-#define VKI_EPERM            1      /* Operation not permitted */
-#define VKI_ENOENT	     2	    /* No such file or directory */
-#define VKI_ESRCH            3      /* No such process */
-#define VKI_EINTR            4      /* Interrupted system call */
-#define VKI_EBADF            9      /* Bad file number */
-#define VKI_ENOMEM          12      /* Out of memory */
-#define VKI_EWOULDBLOCK     VKI_EAGAIN  /* Operation would block */
-#define VKI_EAGAIN          11      /* Try again */
-#define	VKI_EACCES	    13      /* Permission denied */
-#define	VKI_EFAULT          14      /* Bad address */
-#define VKI_EEXIST	    17	    /* File exists */
-#define VKI_EINVAL          22      /* Invalid argument */
-#define VKI_EMFILE	    24	    /* Too many open files */
-#define VKI_ENOSYS          38      /* Function not implemented */
-
-#define VKI_ERESTARTSYS	    512	    /* Restart the syscall */
-
-/* Copied from linux/isdn.h */
-
-#define VKI_IIOCGETCPS  _IO( 'I',21 )
-#define VKI_IIOCNETGPN  _IO( 'I',34 )
-
-#define ISDN_MSNLEN          32
-
-typedef struct {
-    char name[ 10 ];
-    char phone[ ISDN_MSNLEN ];
-    int  outgoing;
-} isdn_net_ioctl_phone;
-
-
-/* Gawd ... hack ... */
-
-typedef struct vki__user_cap_header_struct {
-        UInt version;
-        int pid;
-} vki_cap_user_header_t;
- 
-typedef struct vki__user_cap_data_struct {
-        UInt effective;
-        UInt permitted;
-        UInt inheritable;
-} vki_cap_user_data_t;
-  
-
-/* "Byrial Jensen" <byrial@image.dk> says:
-               [various] ioctls take a pointer to a "struct
-               termios" but this is another and shorter "struct
-               termios" than the one defined in <termios.h> and used
-               by tcgetattr(3) and tcsetattr(3) and other library
-               functions. GNU libc translate between its library
-               termios and the kernel termios. 
-*/
-
-#define VKI_SIZEOF_STRUCT_TERMIOS 36
-
-/* Adam Gundy <arg@cyberscience.com>, 20 Mar 2002, says: */
-#define VKI_SIZEOF_STRUCT_TERMIO 17
-
-
-/* File descriptor sets, for doing select().  Copied from
-   /usr/src/linux-2.4.9-31/include/linux/posix_types.h 
-*/
-/*
- * This allows for 1024 file descriptors: if NR_OPEN is ever grown
- * beyond that you'll have to change this too. But 1024 fd's seem to be
- * enough even for such "real" unices like OSF/1, so hopefully this is
- * one limit that doesn't have to be changed [again].
- *
- * Note that POSIX wants the FD_CLEAR(fd,fdsetp) defines to be in
- * <sys/time.h> (and thus <linux/time.h>) - but this is a more logical
- * place for them. Solved by having dummy defines in <sys/time.h>.
- */
-
-/*
- * Those macros may have been defined in <gnu/types.h>. But we always
- * use the ones here. 
- */
-#undef VKI_NFDBITS
-#define VKI_NFDBITS       (8 * sizeof(unsigned long))
-
-#undef VKI_FD_SETSIZE
-#define VKI_FD_SETSIZE    1024
-
-#undef VKI_FDSET_LONGS
-#define VKI_FDSET_LONGS   (VKI_FD_SETSIZE/VKI_NFDBITS)
-
-#undef VKI_FDELT
-#define VKI_FDELT(d)      ((d) / VKI_NFDBITS)
-
-#undef VKI_FDMASK
-#define VKI_FDMASK(d)     (1UL << ((d) % VKI_NFDBITS))
-
-typedef struct {
-        unsigned long vki_fds_bits [VKI_FDSET_LONGS];
-} vki_fd_set;
-
-
-/* Gawd ...
-   Copied from /usr/src/linux-2.4.9-31/./include/asm-i386/posix_types.h
-*/
-#undef  VKI_FD_SET
-#define VKI_FD_SET(fd,fdsetp) \
-                __asm__ __volatile__("btsl %1,%0": \
-                        "=m" (*(vki_fd_set *) (fdsetp)):"r" ((int) (fd)))
-
-#undef  VKI_FD_CLR
-#define VKI_FD_CLR(fd,fdsetp) \
-                __asm__ __volatile__("btrl %1,%0": \
-                        "=m" (*(vki_fd_set *) (fdsetp)):"r" ((int) (fd)))
-
-#undef  VKI_FD_ISSET
-#define VKI_FD_ISSET(fd,fdsetp) (__extension__ ({ \
-                unsigned char __result; \
-                __asm__ __volatile__("btl %1,%2 ; setb %0" \
-                        :"=q" (__result) :"r" ((int) (fd)), \
-                        "m" (*(vki_fd_set *) (fdsetp))); \
-                __result; }))
-
-#undef  VKI_FD_ZERO
-#define VKI_FD_ZERO(fdsetp) \
-do { \
-        int __d0, __d1; \
-        __asm__ __volatile__("cld ; rep ; stosl" \
-                        :"=m" (*(vki_fd_set *) (fdsetp)), \
-                          "=&c" (__d0), "=&D" (__d1) \
-                        :"a" (0), "1" (VKI_FDSET_LONGS), \
-                        "2" ((vki_fd_set *) (fdsetp)) : "memory"); \
-} while (0)
-
-
-
-struct vki_pollfd {
-   Int		fd;
-   Short	events;
-   Short	revents;
-};
-
-/* asm/poll.h */
-#define VKI_POLLIN          0x0001
-#define VKI_POLLPRI         0x0002
-#define VKI_POLLOUT         0x0004
-#define VKI_POLLERR         0x0008
-#define VKI_POLLHUP         0x0010
-#define VKI_POLLNVAL        0x0020
-
-
-
-/* 
-./include/asm-i386/posix_types.h:typedef long           __kernel_suseconds_t;
-./include/linux/types.h:typedef __kernel_suseconds_t    suseconds_t;
-
-./include/asm-i386/posix_types.h:typedef long           __kernel_time_t;
-./include/linux/types.h:typedef __kernel_time_t         time_t;
-*/
-
-struct vki_timeval {
-        /* time_t */ long         tv_sec;         /* seconds */
-        /* suseconds_t */ long    tv_usec;        /* microseconds */
-};
-
-
-
-/* For fcntl on fds ..
-   from ./include/asm-i386/fcntl.h */
-#define VKI_F_DUPFD	    0	    /* dup */
-#define VKI_F_GETFD	    1	    /* get close_on_exec */
-#define VKI_F_SETFD	    2	    /* set/clear close_on_exec */
-#define VKI_F_GETFL         3       /* get file->f_flags */
-#define VKI_F_SETFL         4       /* set file->f_flags */
-
-/* for F_[GET|SET]FL */
-#define VKI_FD_CLOEXEC	    1	    /* actually anything with low bit set goes */
-
-#define VKI_O_NONBLOCK        04000
-
-/* For nanosleep ... 
-   from ./include/linux/time.h */
-struct vki_timespec {
-        /* time_t */ long tv_sec;         /* seconds */
-        long    tv_nsec;        /* nanoseconds */
-};
-
-
-/* STAT stuff 
-   from /usr/src/linux-2.4.9-31/include/asm-i386/stat.h */
-struct vki_stat {
-        unsigned short st_dev;
-        unsigned short __pad1;
-        unsigned long st_ino;
-        unsigned short st_mode;
-        unsigned short st_nlink;
-        unsigned short st_uid;
-        unsigned short st_gid;
-        unsigned short st_rdev;
-        unsigned short __pad2;
-        unsigned long  st_size;
-        unsigned long  st_blksize;
-        unsigned long  st_blocks;
-        unsigned long  st_atime;
-        unsigned long  __unused1;
-        unsigned long  st_mtime;
-        unsigned long  __unused2;
-        unsigned long  st_ctime;
-        unsigned long  __unused3;
-        unsigned long  __unused4;
-        unsigned long  __unused5;
-};
-
-
-/* To do with the ELF frame constructed by the kernel on a process'
-   stack just before it transfers control to the program's interpreter
-   (to use the ELF parlance).
-   Constants from /usr/src/linux-2.4.9-31/include/linux/elf.h
-   Logic from     /usr/src/linux-2.4.9-31/fs/binfmt_elf.c
-                  and its counterpart in the 2.2.14 kernel sources 
-                  in Red Hat 6.2.  */
-#define VKI_AT_NULL   0
-#define VKI_AT_SYSINFO 32   /* address of system info page */
-#define VKI_AT_CLKTCK 17    /* frequency at which times() increments */
-#define VKI_AT_HWCAP  16    /* arch dependent hints at CPU capabilities */
-#define VKI_AT_BASE   7     /* base address of interpreter */
-#define VKI_AT_PAGESZ 6     /* system page size */
-#define VKI_AT_PHNUM  5     /* number of program headers */
-#define VKI_AT_PHENT  4     /* size of program header entry */
-#define VKI_AT_PHDR   3     /* program headers for program */
-#define VKI_AT_USER_AUX_SEGMENT 23  /* tell glibc what address segment
-                                       0x3B points to.  (Needed for
-                                       Red Hat Limbo, 7.3.92) */
-
-/* Including <linux/module.h> leads to loads of hassle because then we
-   need <asm/atomic.h> sometimes (RedHat 7.3) and that is a
-   kernel-only header which deliberately #errors on gcc-3.1.  Mucho
-   hassle considering that we only want to know sizeof(struct module).
-   Hence ...
- 
-   #include <stdio.h>
-   #include <asm/atomic.h>
-   #include <linux/module.h>
-
-   int main ( void )
-   {
-      printf ("sizeof(struct module) = %d\n", sizeof(struct module) );
-      return 0;
-    }
-*/
-
-#define VKI_SIZEOF_STRUCT_MODULE 96
-
-
-/* This is the structure passed to the modify_ldt syscall.  Just so as
-   to confuse and annoy everyone, this is _not_ the same as an
-   VgLdtEntry and has to be translated into such.  The logic for doing
-   so, in vg_ldt.c, is copied from the kernel sources. */
-/*
- * ldt.h
- *
- * Definitions of structures used with the modify_ldt system call.
- */
-typedef struct vki_modify_ldt_ldt_s {
-        unsigned int  entry_number;
-        unsigned long base_addr;
-        unsigned int  limit;
-        unsigned int  seg_32bit:1;
-        unsigned int  contents:2;
-        unsigned int  read_exec_only:1;
-        unsigned int  limit_in_pages:1;
-        unsigned int  seg_not_present:1;
-        unsigned int  useable:1;
-        unsigned int  reserved:25;
-} vki_modify_ldt_t;
-
-#define VKI_MODIFY_LDT_CONTENTS_DATA        0
-#define VKI_MODIFY_LDT_CONTENTS_STACK       1
-#define VKI_MODIFY_LDT_CONTENTS_CODE        2
-
-#define VKI_GDT_TLS_ENTRIES 3
-#define VKI_GDT_TLS_MIN     6
-#define VKI_GDT_TLS_MAX     (VKI_GDT_TLS_MIN + VKI_GDT_TLS_ENTRIES)
-
-/* Flags for clone() */
-/* linux/sched.h */
-#define VKI_CSIGNAL		0x000000ff	/* signal mask to be sent at exit */
-#define VKI_CLONE_VM		0x00000100	/* set if VM shared between processes */
-#define VKI_CLONE_FS		0x00000200	/* set if fs info shared between processes */
-#define VKI_CLONE_FILES		0x00000400	/* set if open files shared between processes */
-#define VKI_CLONE_SIGHAND	0x00000800	/* set if signal handlers and blocked signals shared */
-#define VKI_CLONE_IDLETASK	0x00001000	/* set if new pid should be 0 (kernel only)*/
-#define VKI_CLONE_PTRACE	0x00002000	/* set if we want to let tracing continue on the child too */
-#define VKI_CLONE_VFORK		0x00004000	/* set if the parent wants the child to wake it up on mm_release */
-#define VKI_CLONE_PARENT	0x00008000	/* set if we want to have the same parent as the cloner */
-#define VKI_CLONE_THREAD	0x00010000	/* Same thread group? */
-#define VKI_CLONE_NEWNS		0x00020000	/* New namespace group? */
-#define VKI_CLONE_SYSVSEM	0x00040000	/* share system V SEM_UNDO semantics */
-#define VKI_CLONE_SETTLS	0x00080000	/* create a new TLS for the child */
-#define VKI_CLONE_PARENT_SETTID	0x00100000	/* set the TID in the parent */
-#define VKI_CLONE_CHILD_CLEARTID	0x00200000	/* clear the TID in the child */
-#define VKI_CLONE_DETACHED	0x00400000	/* parent wants no child-exit signal */
-#define VKI_CLONE_UNTRACED	0x00800000	/* set if the tracing process can't force VKI_CLONE_PTRACE on this clone */
-#define VKI_CLONE_CHILD_SETTID	0x01000000	/* set the TID in the child */
-
-/* This is the structure passed to the getdents syscall. */
-/*
- * linux/dirent.h
- */
-typedef struct vki_dirent {
-	long           d_ino;
-	long           d_off;
-	unsigned short d_reclen;
-	char           d_name[256];
-} vki_dirent;
-
-
-
-/* This is the structure passed to the getrlimit syscall. */
-/*
- * bits/resource.h
- */
-typedef struct vki_rlimit {
-	unsigned long rlim_cur;
-	unsigned long rlim_max;
-} vki_rlimit;
-
-#define VKI_RLIMIT_NOFILE 7
-
-/* Socket stuff. */
-/*
- * sys/socket.h
- */
-typedef unsigned short vki_sa_family_t;
-struct vki_sockaddr {
-  vki_sa_family_t sa_family;     /* Address family. */
-  char            sa_data[14];   /* Address data. */
-};
-
-/* statfs structs */
-/*
- * bits/statfs.h
- */
-
-struct statfs {
-        unsigned int f_type;
-        unsigned int f_bsize;
-        unsigned int f_blocks;
-        unsigned int f_bfree;
-        unsigned int f_bavail;
-        unsigned int f_files;
-        unsigned int f_ffree;
-        int f_fsid[ 2 ];
-        unsigned int f_namelen;
-        unsigned int f_frsize;
-        unsigned int f_spare[5];
-};
-
-struct statfs64 {
-        unsigned int f_type;
-        unsigned int f_bsize;
-        unsigned long long f_blocks;
-        unsigned long long f_bfree;
-        unsigned long long f_bavail;
-        unsigned long long f_files;
-        unsigned long long f_ffree;
-        int f_fsid[ 2 ];
-        unsigned int f_namelen;
-        unsigned int f_frsize;
-        unsigned int f_spare[5];
-};
-
-/* 
- * linux/futex.h
- */
-
-#define VKI_FUTEX_WAIT    0
-#define VKI_FUTEX_WAKE    1
-#define VKI_FUTEX_FD      2
-#define VKI_FUTEX_REQUEUE 3
-
-
-#endif /*  __VG_KERNELIFACE_H */
-
-/*--------------------------------------------------------------------*/
-/*--- end                                         vg_kerneliface.h ---*/
-/*--------------------------------------------------------------------*/
diff -puN /dev/null coregrind/arch/i386-freebsd/vg_helpers.S
--- /dev/null	2003-01-30 02:24:37.000000000 -0800
+++ valgrind-jeremy/coregrind/arch/i386-freebsd/vg_helpers.S	2004-01-27 11:09:10.000000000 -0800
@@ -0,0 +1,87 @@
+##--------------------------------------------------------------------##
+##--- Support routines for the JITter output.                      ---##
+##---                                                 vg_helpers.S ---##
+##--------------------------------------------------------------------##
+
+/*
+  This file is part of Valgrind, an extensible x86 protected-mode
+  emulator for monitoring program execution on x86-Unixes.
+
+  Copyright (C) 2000-2004 Julian Seward 
+     jseward@acm.org
+
+  This program is free software; you can redistribute it and/or
+  modify it under the terms of the GNU General Public License as
+  published by the Free Software Foundation; either version 2 of the
+  License, or (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  02111-1307, USA.
+
+  The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "vg_constants.h"
+
+/* A stubs for a return which we want to catch: a signal return.
+   returns and pthread returns.  In the latter case, the thread's
+   return value is in %EAX, so we pass this as the first argument
+   to the request.  In both cases we use the user request mechanism.
+   You need to to read the definition of VALGRIND_MAGIC_SEQUENCE
+   in valgrind.h to make sense of this.
+
+   This isn't used in-place.  It is copied into the client address space
+   at an arbitary address.  Therefore, this code must be completely
+   position-independent.
+*/
+.global VG_(trampoline_code_start)
+.global VG_(trampoline_code_length)
+.global VG_(tramp_sigreturn_offset)
+.global VG_(tramp_syscall_offset)
+	
+VG_(trampoline_code_start):
+sigreturn_start:	
+	subl	$20, %esp	# allocate arg block
+	movl	%esp, %edx	# %edx == &_zzq_args[0]
+	movl	$VG_USERREQ__SIGNAL_RETURNS, 0(%edx)	# request
+	movl	$0, 4(%edx)	# arg1
+	movl	$0, 8(%edx)	# arg2
+	movl	$0, 12(%edx)	# arg3
+	movl	$0, 16(%edx)	# arg4
+	movl	%edx, %eax
+	# and now the magic sequence itself:
+	roll $29, %eax
+	roll $3, %eax
+	rorl $27, %eax
+	rorl $5, %eax
+	roll $13, %eax
+	roll $19, %eax
+	# should never get here
+	ud2
+
+	.align 16
+	# We can point our sysinfo stuff here
+syscall_start:	
+	int	$0x80
+	ret
+tramp_code_end:
+			
+.data
+VG_(trampoline_code_length):
+	.long tramp_code_end - VG_(trampoline_code_start)
+VG_(tramp_sigreturn_offset):
+	.long sigreturn_start - VG_(trampoline_code_start)
+VG_(tramp_syscall_offset):
+	.long syscall_start - VG_(trampoline_code_start)
+.text
+
+##--------------------------------------------------------------------##
+##--- end                                             vg_helpers.S ---##
+##--------------------------------------------------------------------##
diff -puN /dev/null coregrind/arch/i386-freebsd/ume_archdefs.c
--- /dev/null	2003-01-30 02:24:37.000000000 -0800
+++ valgrind-jeremy/coregrind/arch/i386-freebsd/ume_archdefs.c	2004-01-27 11:09:10.000000000 -0800
@@ -0,0 +1,29 @@
+
+/*
+   This file is part of Valgrind, an extensible x86 protected-mode
+   emulator for monitoring program execution on x86-Unixes.
+
+   Copyright (C) 2000-2004 Julian Seward 
+      jseward@acm.org
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "ume_archdefs.h"
+
+const unsigned long CLIENT_START = 0;
diff -puN /dev/null coregrind/arch/i386-freebsd/ume_entry.S
--- /dev/null	2003-01-30 02:24:37.000000000 -0800
+++ valgrind-jeremy/coregrind/arch/i386-freebsd/ume_entry.S	2004-01-27 11:09:10.000000000 -0800
@@ -0,0 +1,38 @@
+
+/*
+   This file is part of Valgrind, an extensible x86 protected-mode
+   emulator for monitoring program execution on x86-Unixes.
+
+   Copyright (C) 2000-2004 Julian Seward 
+      jseward@acm.org
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+	.text
+	.globl _ume_entry
+
+	/* Record the very initial value of %esp before starting the
+	   rest of the executable */
+_ume_entry:
+	movl	%esp, ume_exec_esp
+	jmp	_start
+
+	.data
+	.globl ume_exec_esp
+ume_exec_esp:	.long 0
diff -puN /dev/null coregrind/arch/i386-freebsd/ume_go.c
--- /dev/null	2003-01-30 02:24:37.000000000 -0800
+++ valgrind-jeremy/coregrind/arch/i386-freebsd/ume_go.c	2004-01-27 11:09:10.000000000 -0800
@@ -0,0 +1,51 @@
+
+/*
+   This file is part of Valgrind, an extensible x86 protected-mode
+   emulator for monitoring program execution on x86-Unixes.
+
+   Copyright (C) 2000-2004 Julian Seward 
+      jseward@acm.org
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "ume_arch.h"
+
+/* 
+   Jump to a particular EIP with a particular ESP.  This is intended
+   to simulate the initial CPU state when the kernel starts an program
+   after exec; it therefore also clears all the other registers.
+ */
+void ume_go(addr_t eip, addr_t esp)
+{
+   asm volatile ("movl %1, %%esp;"	/* set esp */
+		 "pushl %%eax;"		/* push esp */
+		 "xorl	%%eax,%%eax;"	/* clear registers */
+		 "xorl	%%ebx,%%ebx;"
+		 "xorl	%%ecx,%%ecx;"
+		 "xorl	%%edx,%%edx;"
+		 "xorl	%%esi,%%esi;"
+		 "xorl	%%edi,%%edi;"
+		 "xorl	%%ebp,%%ebp;"
+
+		 "ret"			/* return into entry */
+		 : : "a" (eip), "r" (esp));
+   /* we should never get here */
+   for(;;)
+	   asm volatile("ud2");
+} 
diff -puN /dev/null coregrind/arch/i386-linux/vg_proxylwp.c
--- /dev/null	2003-01-30 02:24:37.000000000 -0800
+++ valgrind-jeremy/coregrind/arch/i386-linux/vg_proxylwp.c	2004-01-27 11:09:10.000000000 -0800
@@ -0,0 +1,186 @@
+#include "vg_include.h"
+#include "vg_proxylwp.h"
+
+extern void do_thread_syscall(Int sys, 
+			      Int arg1, Int arg2, Int arg3, Int arg4, Int arg5, Int arg6,
+			      Int *result, enum PXState *statep, enum PXState poststate);
+
+asm(
+".text\n"
+"	.type do_thread_syscall,@function\n"
+
+"do_thread_syscall:\n"
+"	push	%esi\n"
+"	push	%edi\n"
+"	push	%ebx\n"
+"	push	%ebp\n"
+".sys_before:\n"
+"	movl	16+ 4(%esp),%eax\n" /* syscall */
+"	movl	16+ 8(%esp),%ebx\n" /* arg1 */
+"	movl	16+12(%esp),%ecx\n" /* arg2 */
+"	movl	16+16(%esp),%edx\n" /* arg3 */
+"	movl	16+20(%esp),%esi\n" /* arg4 */
+"	movl	16+24(%esp),%edi\n" /* arg5 */
+"	movl	16+28(%esp),%ebp\n" /* arg6 */
+".sys_restarted:\n"
+"	int	$0x80\n"
+".sys_after:\n"
+"	movl	16+32(%esp),%ebx\n"	/* ebx = Int *res */
+"	movl	%eax, (%ebx)\n"		/* write the syscall retval */
+
+"	movl	16+36(%esp),%ebx\n"	/* ebx = enum PXState * */
+"	testl	%ebx, %ebx\n"
+"	jz	1f\n"
+
+"	movl	16+40(%esp),%ecx\n"	/* write the post state (must be after retval write) */
+"	movl	%ecx,(%ebx)\n"
+
+".sys_done:\n"				/* OK, all clear from here */
+"1:	popl	%ebp\n"
+"	popl	%ebx\n"
+"	popl	%edi\n"
+"	popl	%esi\n"
+"	ret\n"
+"	.size do_thread_syscall,.-do_thread_syscall\n"
+".previous\n"
+
+".section .rodata\n"
+".globl sys_before, sys_restarted, sys_after, sys_done\n"
+"sys_before:	.long	.sys_before\n"
+"sys_restarted:	.long	.sys_restarted\n"
+"sys_after:	.long	.sys_after\n"
+"sys_done:	.long	.sys_done\n"
+".previous\n"
+);
+
+/* Run a syscall for a particular thread, getting the arguments from
+   the thread's registers, and returning the result in the thread's
+   eax.
+
+   Assumes that the only thread state which matters is the contents of
+   %eax-%ebp and the return value in %eax.
+ */
+void proxy_syscall(Int syscallno, ThreadState *tst, 
+		   enum PXState *state , enum PXState poststate)
+{
+   do_thread_syscall(syscallno,   /* syscall no. */
+		     tst->m_ebx,  /* arg 1 */
+		     tst->m_ecx,  /* arg 2 */
+		     tst->m_edx,  /* arg 3 */
+		     tst->m_esi,  /* arg 4 */
+		     tst->m_edi,  /* arg 5 */
+		     tst->m_ebp,  /* arg 6 */
+		     &tst->m_eax, /* result */
+		     state,	  /* state to update */
+		     poststate);  /* state when syscall has finished */
+}
+
+static Int do_futex(void *addr, Int op, Int val, struct vki_timespec *time, void *addr2)
+{
+   return VG_(do_syscall)(__NR_futex, addr, op, val, time, addr2);
+}
+
+static Int have_settid = -1;	/* -1 -> unknown */
+
+
+/*
+  Create a proxy LWP using whatever varient of clone makes the most
+   sense for the current kernel.  We use futexes for termination
+   notification wherever possible.  Returns 0 on success, or a -ve
+   error code on failure.
+*/
+Int proxy_makethread(ProxyLWP *proxy)
+{
+   Int ret = -1;
+
+   if (have_settid != 0) {
+      ret = VG_(clone)(proxy_lwp, 
+		       LWP_stack(proxy),
+		       VKI_CLONE_FS | VKI_CLONE_FILES | VKI_CLONE_VM |
+		       VKI_CLONE_SIGHAND | VKI_CLONE_THREAD | 
+		       VKI_CLONE_PARENT_SETTID |
+		       VKI_CLONE_CHILD_CLEARTID | VKI_CLONE_DETACHED,
+		       proxy, &proxy->lwp, &proxy->lwp);
+
+      if ( have_settid == -1 && (ret < 0 || proxy->lwp == 0) ) {
+         have_settid = 0;
+	 
+	 /* Assume that not having parent_settid also means that we've
+	    got 2.4-style signal handling, which means we need to do
+	    more work. */
+         VG_(do_signal_routing) = True;
+
+	 if (ret > 0) {
+	    /* If clone actually succeeded and just ignored the
+	       CLONE_PARENT_SETTID flag, then use the LWP it created
+	       for us. */
+	    proxy->lwp = ret;
+	 }
+       }
+       else 
+           have_settid = 1;
+   }
+
+   if (ret < 0) {
+      vg_assert(have_settid == 0);
+      vg_assert(proxy->lwp == 0);
+
+      ret = VG_(clone)(proxy_lwp, 
+		       LWP_stack(proxy),
+		       VKI_CLONE_FS | VKI_CLONE_FILES | VKI_CLONE_VM |
+		       VKI_CLONE_SIGHAND | VKI_CLONE_THREAD, 
+		       proxy, NULL, NULL);
+      proxy->lwp = ret;
+   }
+
+   return (ret < 0) ? ret : 0;
+}
+
+/* Wait on a proxy LWP.  Returns True if the LWP has exited. */
+Bool proxy_wait(ProxyLWP *proxy, Bool block, Int *status)
+{
+   Bool ret = False;
+
+   if (have_settid == -1)
+      return False;
+
+   if (have_settid) {
+      if (block) {
+	 Int lwp = proxy->lwp;
+
+
+	 if(proxy->lwp != 0)
+	    do_futex(&proxy->lwp, VKI_FUTEX_WAIT, lwp, NULL, NULL);
+
+	 if (status)
+	    *status = proxy->exitcode;
+	 ret = True;
+      } else {
+	 if (proxy->lwp == 0) {
+	    *status = proxy->exitcode;
+	    ret = True;
+	 }
+      }
+   } else {
+      Int flags = VKI__WCLONE;
+      Int res;
+
+      if (!block)
+	 flags |= VKI_WNOHANG;
+      res = VG_(waitpid)(proxy->lwp, status, flags);
+      if (res == proxy->lwp) {
+	 vg_assert(*status == proxy->exitcode);
+	 ret = True;
+      }
+   }
+
+   return ret;
+}
+
+void proxy_arch_start(ProxyLWP *px)
+{
+}
+
+void proxy_arch_finish(ProxyLWP *px, Int ret)
+{
+}
diff -puN /dev/null coregrind/arch/i386-linux/vg_syscalls.h
--- /dev/null	2003-01-30 02:24:37.000000000 -0800
+++ valgrind-jeremy/coregrind/arch/i386-linux/vg_syscalls.h	2004-01-27 11:09:10.000000000 -0800
@@ -0,0 +1,17 @@
+#ifndef _I386_LINUX_VG_SYSCALLS_H
+#define _I386_LINUX_VG_SYSCALLS_H
+/* 
+   Various archtecture/OS details around syscalls (and associated
+   things like signals)
+ */
+
+
+/* Set an error in the thread state, as if a syscall had failed */
+#define SETERROR(tst, err)	((tst)->m_eax = -(err))
+#define GETERROR(tst)		(((Int)(tst)->m_eax) < 0 ? -(tst)->m_eax : 0)
+
+#define EIP_FROM_SIGCONTEXT(sc)	((sc)->eip)
+#define EAX_FROM_SIGCONTEXT(sc) ((sc)->eax)
+#define EFLAGS_FROM_SIGCONTEXT(sc) ((sc)->eflags)
+
+#endif /* _I386_LINUX_VG_SYSCALLS_H */
diff -puN /dev/null coregrind/arch/i386-freebsd/vg_syscalls.h
--- /dev/null	2003-01-30 02:24:37.000000000 -0800
+++ valgrind-jeremy/coregrind/arch/i386-freebsd/vg_syscalls.h	2004-01-27 11:09:10.000000000 -0800
@@ -0,0 +1,26 @@
+#ifndef _I386_FREEBSD_VG_SYSCALLS_H
+#define _I386_FREEBSD_VG_SYSCALLS_H
+/* 
+   Various archtecture/OS details around syscalls (and associated
+   things like signals)
+ */
+
+
+/* Set an error in the thread state, as if a syscall had failed */
+#define SETERROR(tst, err)	do { (tst)->m_eax = (err); (tst)->m_eflags |= EFlagC; } while(0)
+#define GETERROR(tst)		(((tst)->m_eflags & EFlagC) ? (tst0)->m_eax : 0)
+
+#define EIP_FROM_SIGCONTEXT(sc)	((sc)->sc_eip)
+#define EAX_FROM_SIGCONTEXT(sc) ((sc)->sc_eax)
+#define EFLAGS_FROM_SIGCONTEXT(sc) ((sc)->sc_eflags)
+
+struct vki_umtx {
+   UInt u_owner;	/* Owner of the mutex. */
+};
+
+typedef struct {
+   struct vki_mutex	mutex;
+} ProxyArchExtra;
+#define _ARCH_PROXY_EXTRA
+
+#endif /* _I386_FREEBSD_VG_SYSCALLS_H */
diff -puN coregrind/vg_proxylwp.c~archdep coregrind/vg_proxylwp.c
--- valgrind/coregrind/vg_proxylwp.c~archdep	2004-01-27 11:09:02.000000000 -0800
+++ valgrind-jeremy/coregrind/vg_proxylwp.c	2004-01-27 11:09:10.000000000 -0800
@@ -30,6 +30,8 @@
 
 
 #include "vg_include.h"
+#include "vg_proxylwp.h"
+#include "vg_syscalls.h"
 
 /* We need our own copy of VG_(do_syscall)() to handle a special
    race-condition.  If we've got signals unblocked, and we take a
@@ -67,17 +69,6 @@
 	value.
 */
 
-enum PXState
-{
-   PXS_BAD = -1,
-   PXS_WaitReq,		/* waiting for a request */
-   PXS_RunSyscall,	/* running a syscall */
-   PXS_IntReply,	/* request interrupted - need to send reply */
-   PXS_SysDone,		/* small window between syscall
-			   complete and results written out */
-   PXS_SigACK,		/* waiting for a signal ACK */
-};
-
 enum RequestType {
    PX_BAD = -1,
    PX_SetSigmask,		/* sched->proxy; proxy->sched */
@@ -225,7 +216,7 @@ static void px_printf(const Char *fmt, .
 }
 #endif
 
-static const Char *pxs_name(enum PXState s)
+const Char *pxs_name(enum PXState s)
 {
    switch(s) {
 #define S(x)	case PXS_##x: return #x
@@ -256,63 +247,6 @@ static const Char *px_name(enum RequestT
    }
 }
 
-#define PROXYLWP_OFFSET	(VKI_BYTES_PER_PAGE - sizeof(ProxyLWP))
-
-/* 
-   Allocate a page for the ProxyLWP and its stack.
-
-   This uses the trick for finding the LWP's private data by knowing
-   that the stack is a single page, and that the ProxyLWP structure is
-   at the end of it.  Therefore, given any %esp in the stack, you can
-   find the ProxyLWP structure (see LWP_TSD()).
- */
-static ProxyLWP *LWP_alloc(void)
-{
-   UChar *p = VG_(get_memory_from_mmap)(VKI_BYTES_PER_PAGE, "alloc_LWP");
-   ProxyLWP *ret;
-   vg_assert(p == (UChar *)PGROUNDDN(p)); /* px must be page aligned */
-
-   ret = (ProxyLWP *)(p + PROXYLWP_OFFSET);
-
-   ret->magic = VG_PROXY_MAGIC;
-
-   return ret;
-}
-
-/* Free a thread structure */
-static void LWP_free(ProxyLWP *px)
-{
-   UChar *p = (UChar *)PGROUNDDN(px);
-   
-   vg_assert(px->magic == VG_PROXY_MAGIC);
-   px->magic = 0;
-   vg_assert((p + PROXYLWP_OFFSET) == (UChar *)px);
-
-   VG_(munmap)(p, VKI_BYTES_PER_PAGE);
-}
-
-/* Get a particular ProxyLWP's LWP structure from its esp (relies on
-   stacks being page aligned, with the ProxyLWP structure at the
-   end). */
-static inline ProxyLWP *LWP_TSD(void *esp)
-{
-   UChar *p = (UChar *)PGROUNDDN(esp);
-   ProxyLWP *ret;
-
-   ret = (ProxyLWP *)(p + PROXYLWP_OFFSET);
-   vg_assert(ret->magic == VG_PROXY_MAGIC);
-
-   return ret;
-}
-
-/* Get top of stack */
-static inline void *LWP_stack(ProxyLWP *px)
-{
-   vg_assert(px->magic == VG_PROXY_MAGIC);
-
-   return (void *)(((void **)px) - 1);
-}
-
 static void proxy_fork_cleanup(ThreadId tid);
 
 /* Init the proxy mechanism */
@@ -396,56 +330,6 @@ void VG_(proxy_shutdown)(void)
    result_recv = result_send = -1;
 }
 
-/* This is called from within a proxy LWP signal handler.  This
-   function records the siginfo, then longjmps back into the proxy
-   main state machine loop.  The presumption is that the signal
-   handler is being run with all signals blocked; the longjmp is
-   there to make sure they stay masked until the application thread is
-   ready to run its signal handler. */
-void VG_(proxy_handlesig)(const vki_ksiginfo_t *siginfo, 
-			  const struct vki_sigcontext *sigcontext)
-{
-   UChar local;
-   ProxyLWP *px = LWP_TSD(&local);
-   Addr eip = sigcontext->eip;
-   Int eax = sigcontext->eax;
-
-   vg_assert(siginfo->si_signo != 0);
-   if (px->siginfo.si_signo != 0) {
-      px_printf("proxy_handlesig: tid %d already has %d pending, new sig %d\n",
-		px->lwp, px->siginfo.si_signo, siginfo->si_signo);
-   }
-   vg_assert(px->siginfo.si_signo == 0);
-
-   px->siginfo = *siginfo;
-
-   px_printf("proxy got signal %d\n", siginfo->si_signo);
-
-   /* First look to see if the EIP is within our interesting ranges
-      near a syscall to work out what should happen. */
-   if (sys_before <= eip && eip <= sys_restarted) {
-      /* We are before the syscall actually ran, or it did run and
-	 wants to be restarted.  Either way, set the return code to
-	 indicate a restart.  This is not really any different from
-	 anywhere else, except that we can make some assertions about
-	 the proxy and machine state here. */
-      vg_assert(px->state == PXS_RunSyscall);
-      vg_assert(px->tst->m_eax == -VKI_ERESTARTSYS);
-   } else if (sys_after <= eip && eip <= sys_done) {
-      /* We're after the syscall.  Either it was interrupted by the
-	 signal, or the syscall completed normally.  In either case
-	 eax contains the correct syscall return value, and the new
-	 state is effectively PXS_SysDone. */
-      vg_assert(px->state == PXS_RunSyscall ||
-		px->state == PXS_SysDone);
-      px->state = PXS_SysDone;
-      px->tst->m_eax = eax;
-   }
-   px_printf("  signalled in state %s\n", pxs_name(px->state));
-
-   __builtin_longjmp(px->jumpbuf, 1);
-}
-
 static Bool send_reply(const struct PX_Reply *reply)
 {
    const Int size = sizeof(struct PX_Reply);
@@ -466,7 +350,7 @@ static Bool recv_reply(struct PX_Reply *
    look at and update the thread's register state.  It interacts with
    the rest of Valgrind by receiving messages through its pipe and
    sending results through result_send. */
-static Int proxylwp(void *v)
+Int proxy_lwp(void *v)
 {
    ProxyLWP *px = (ProxyLWP *)v;
    Int frommain = px->frommain;
@@ -476,6 +360,8 @@ static Int proxylwp(void *v)
    Int ret = 1000;
    static const vki_kstack_t ss = { .ss_flags = VKI_SS_DISABLE };
 
+   proxy_arch_start(px);
+
    /* Block everything until we're told otherwise (LWP should have
       been started with all signals blocked anyway) */
    VG_(ksigfillset)(&allsig);
@@ -740,7 +626,7 @@ static Int proxylwp(void *v)
 
 	       /* ST:4 */
 	       
-	       thread_syscall(syscallno, tst, &px->state, PXS_SysDone);
+	       proxy_syscall(syscallno, tst, &px->state, PXS_SysDone);
 
 	       /* ST:5 */
 
@@ -805,6 +691,9 @@ static Int proxylwp(void *v)
    VG_(close)(frommain);
 
    px->exitcode = ret;
+
+   proxy_arch_finish(px, ret);
+
    return ret;
 }
 
@@ -839,7 +728,7 @@ void VG_(proxy_sendsig)(ThreadId tid, In
       /* If the LWP is actually blocked in a sigtimedwait, then it
 	 will eat the signal rather than make it pending and deliver
 	 it by the normal mechanism.  In this case, just wait for the
-	 syscall to dinish. */
+	 syscall to finish. */
       if (tst->status == VgTs_WaitSys && tst->syscallno == __NR_rt_sigtimedwait)
 	 sys_wait_results(True, tid, PX_RunSyscall, True);
       else
@@ -871,112 +760,6 @@ void VG_(proxy_abort_syscall)(ThreadId t
    vg_assert(tst->status == VgTs_Runnable);
 }
 
-static Int do_futex(void *addr, Int op, Int val, struct vki_timespec *time, void *addr2)
-{
-   return VG_(do_syscall)(__NR_futex, addr, op, val, time, addr2);
-}
-
-#define VKI_FUTEX_WAIT		0
-#define VKI_FUTEX_WAKE		1
-#define VKI_FUTEX_FD		2
-#define VKI_FUTEX_REQUEUE	3
-
-static Int have_settid = -1;	/* -1 -> unknown */
-
-/*
-  Create a proxy LWP using whatever varient of clone makes the most
-   sense for the current kernel.  We use futexes for termination
-   notification wherever possible.  Returns 0 on success, or a -ve
-   error code on failure.
-*/
-static Int proxy_clone(ProxyLWP *proxy)
-{
-   Int ret = -1;
-
-   if (have_settid != 0) {
-      ret = VG_(clone)(proxylwp, 
-		       LWP_stack(proxy),
-		       VKI_CLONE_FS | VKI_CLONE_FILES | VKI_CLONE_VM |
-		       VKI_CLONE_SIGHAND | VKI_CLONE_THREAD | 
-		       VKI_CLONE_PARENT_SETTID |
-		       VKI_CLONE_CHILD_CLEARTID | VKI_CLONE_DETACHED,
-		       proxy, &proxy->lwp, &proxy->lwp);
-
-      if ( have_settid == -1 && (ret < 0 || proxy->lwp == 0) ) {
-         have_settid = 0;
-	 
-	 /* Assume that not having parent_settid also means that we've
-	    got 2.4-style signal handling, which means we need to do
-	    more work. */
-         VG_(do_signal_routing) = True;
-
-	 if (ret > 0) {
-	    /* If clone actually succeeded and just ignored the
-	       CLONE_PARENT_SETTID flag, then use the LWP it created
-	       for us. */
-	    proxy->lwp = ret;
-	 }
-       }
-       else 
-           have_settid = 1;
-   }
-
-   if (ret < 0) {
-      vg_assert(have_settid == 0);
-      vg_assert(proxy->lwp == 0);
-
-      ret = VG_(clone)(proxylwp, 
-		       LWP_stack(proxy),
-		       VKI_CLONE_FS | VKI_CLONE_FILES | VKI_CLONE_VM |
-		       VKI_CLONE_SIGHAND | VKI_CLONE_THREAD, 
-		       proxy, NULL, NULL);
-      proxy->lwp = ret;
-   }
-
-   return (ret < 0) ? ret : 0;
-}
-
-/* Wait on a proxy LWP.  Returns True if the LWP has exited. */
-static Bool proxy_wait(ProxyLWP *proxy, Bool block, Int *status)
-{
-   Bool ret = False;
-
-   if (have_settid == -1)
-      return False;
-
-   if (have_settid) {
-      if (block) {
-	 Int lwp = proxy->lwp;
-
-
-	 if(proxy->lwp != 0)
-	    do_futex(&proxy->lwp, VKI_FUTEX_WAIT, lwp, NULL, NULL);
-
-	 if (status)
-	    *status = proxy->exitcode;
-	 ret = True;
-      } else {
-	 if (proxy->lwp == 0) {
-	    *status = proxy->exitcode;
-	    ret = True;
-	 }
-      }
-   } else {
-      Int flags = VKI__WCLONE;
-      Int res;
-
-      if (!block)
-	 flags |= VKI_WNOHANG;
-      res = VG_(waitpid)(proxy->lwp, status, flags);
-      if (res == proxy->lwp) {
-	 vg_assert(*status == proxy->exitcode);
-	 ret = True;
-      }
-   }
-
-   return ret;
-}
-
 /* Create a proxy for a new thread */
 void VG_(proxy_create)(ThreadId tid)
 {
@@ -1007,7 +790,7 @@ void VG_(proxy_create)(ThreadId tid)
       SEGV, BUS, ILL or FPE) */
    VG_(block_all_host_signals)(&mask);
 
-   ret = proxy_clone(proxy);
+   ret = proxy_makethread(proxy);
    if (ret < 0) {
 	   VG_(printf)("Error %d trying to create proxy LWP for tid %d\n",
 		       ret, tid);
diff -puN coregrind/vg_include.h~archdep coregrind/vg_include.h
--- valgrind/coregrind/vg_include.h~archdep	2004-01-27 11:09:02.000000000 -0800
+++ valgrind-jeremy/coregrind/vg_include.h	2004-01-27 11:09:10.000000000 -0800
@@ -679,7 +679,7 @@ typedef
    }
    ForkHandlerEntry;
 
-typedef struct ProxyLWP ProxyLWP;
+typedef struct _ProxyLWP ProxyLWP;
 
 typedef
    struct _ThreadState {
@@ -1592,6 +1592,7 @@ extern void VG_(proxy_handlesig)( const 
 extern Int VG_(proxy_id)(ThreadId tid);
 
 
+
 /* ---------------------------------------------------------------------
    Exports of vg_syscalls.c
    ------------------------------------------------------------------ */
diff -puN /dev/null coregrind/arch/i386-common/vg_proxylwp.c
--- /dev/null	2003-01-30 02:24:37.000000000 -0800
+++ valgrind-jeremy/coregrind/arch/i386-common/vg_proxylwp.c	2004-01-27 11:09:10.000000000 -0800
@@ -0,0 +1,132 @@
+#include "vg_syscalls.h"
+#include "vg_proxylwp.h"
+
+/* reentrant printf for proxy use */
+#if 0
+static void px_printf(const Char *fmt, ...)
+{
+   Char buf[1024];
+   Char *cp = buf;
+   va_list vargs;
+
+   void addbuf(Char c) { *cp++ = c; }
+
+   cp += VG_(sprintf)(buf, "[%d, %d]: ", VG_(getpid)(), VG_(gettid)());
+
+   va_start(vargs,fmt);
+   VG_(vprintf)(addbuf, fmt, vargs);
+   va_end(vargs);
+   VG_(send_bytes_to_logging_sink)(buf, cp-buf);
+}
+#else
+static void px_printf(const Char *fmt, ...)
+{
+}
+#endif
+
+/* 
+   Allocate a page for the ProxyLWP and its stack.
+
+   This uses the trick for finding the LWP's private data by knowing
+   that the stack is a single page, and that the ProxyLWP structure is
+   at the end of it.  Therefore, given any %esp in the stack, you can
+   find the ProxyLWP structure (see LWP_TSD()).
+ */
+ProxyLWP *LWP_alloc(void)
+{
+   UChar *p = VG_(get_memory_from_mmap)(VKI_BYTES_PER_PAGE, "alloc_LWP");
+   ProxyLWP *ret;
+   vg_assert(p == (UChar *)PGROUNDDN(p)); /* px must be page aligned */
+
+   ret = (ProxyLWP *)(p + PROXYLWP_OFFSET);
+
+   ret->magic = VG_PROXY_MAGIC;
+
+   return ret;
+}
+
+/* Free a thread structure */
+void LWP_free(ProxyLWP *px)
+{
+   UChar *p = (UChar *)PGROUNDDN(px);
+   
+   vg_assert(px->magic == VG_PROXY_MAGIC);
+   px->magic = 0;
+   vg_assert((p + PROXYLWP_OFFSET) == (UChar *)px);
+
+   VG_(munmap)(p, VKI_BYTES_PER_PAGE);
+}
+
+/* Get a particular ProxyLWP's LWP structure from its esp (relies on
+   stacks being page aligned, with the ProxyLWP structure at the
+   end). */
+ProxyLWP *LWP_TSD(void *esp)
+{
+   UChar *p = (UChar *)PGROUNDDN(esp);
+   ProxyLWP *ret;
+
+   ret = (ProxyLWP *)(p + PROXYLWP_OFFSET);
+   vg_assert(ret->magic == VG_PROXY_MAGIC);
+
+   return ret;
+}
+
+/* Get top of stack */
+void *LWP_stack(ProxyLWP *px)
+{
+   vg_assert(px->magic == VG_PROXY_MAGIC);
+
+   return (void *)(((void **)px) - 1);
+}
+
+/* This is called from within a proxy LWP signal handler.  This
+   function records the siginfo, then longjmps back into the proxy
+   main state machine loop.  The presumption is that the signal
+   handler is being run with all signals blocked; the longjmp is
+   there to make sure they stay masked until the application thread is
+   ready to run its signal handler. */
+void VG_(proxy_handlesig)(const vki_ksiginfo_t *siginfo, 
+			  const struct vki_sigcontext *sigcontext)
+{
+   UChar local;
+   ProxyLWP *px = LWP_TSD(&local);
+   Addr eip = EIP_FROM_SIGCONTEXT(sigcontext);
+   UInt eax = EAX_FROM_SIGCONTEXT(sigcontext);
+   UInt eflags = EFLAGS_FROM_SIGCONTEXT(sigcontext);
+
+   vg_assert(siginfo->si_signo != 0);
+   if (px->siginfo.si_signo != 0) {
+      px_printf("proxy_handlesig: tid %d already has %d pending, new sig %d\n",
+		px->lwp, px->siginfo.si_signo, siginfo->si_signo);
+   }
+   vg_assert(px->siginfo.si_signo == 0);
+
+   px->siginfo = *siginfo;
+
+   px_printf("proxy got signal %d\n", siginfo->si_signo);
+
+   /* First look to see if the EIP is within our interesting ranges
+      near a syscall to work out what should happen. */
+   if (sys_before <= eip && eip <= sys_restarted) {
+      /* We are before the syscall actually ran, or it did run and
+	 wants to be restarted.  Either way, set the return code to
+	 indicate a restart.  This is not really any different from
+	 anywhere else, except that we can make some assertions about
+	 the proxy and machine state here. */
+      vg_assert(px->state == PXS_RunSyscall);
+      vg_assert(px->tst->m_eax == -VKI_ERESTARTSYS);
+   } else if (sys_after <= eip && eip <= sys_done) {
+      /* We're after the syscall.  Either it was interrupted by the
+	 signal, or the syscall completed normally.  In either case
+	 eax contains the correct syscall return value, and the new
+	 state is effectively PXS_SysDone. */
+      vg_assert(px->state == PXS_RunSyscall ||
+		px->state == PXS_SysDone);
+      px->state = PXS_SysDone;
+      px->tst->m_eax = eax;
+      px->tst->m_eflags = eflags; /* for FreeBSD (and *BSD?) */
+   }
+   px_printf("  signalled in state %s\n", pxs_name(px->state));
+
+   __builtin_longjmp(px->jumpbuf, 1);
+}
diff -puN /dev/null coregrind/vg_proxylwp.h
--- /dev/null	2003-01-30 02:24:37.000000000 -0800
+++ valgrind-jeremy/coregrind/vg_proxylwp.h	2004-01-27 11:09:10.000000000 -0800
@@ -0,0 +1,62 @@
+#ifndef _COREGRIND_PROXYLWP_H
+#define _COREGRIND_PROXYLWP_H
+
+#include "vg_include.h"
+#include "vg_syscalls.h"
+
+enum PXState
+{
+   PXS_BAD = -1,
+   PXS_WaitReq,		/* waiting for a request */
+   PXS_RunSyscall,	/* running a syscall */
+   PXS_IntReply,	/* request interrupted - need to send reply */
+   PXS_SysDone,		/* small window between syscall
+			   complete and results written out */
+   PXS_SigACK,		/* waiting for a signal ACK */
+};
+
+#define VG_PROXY_MAGIC	0xef83b192
+
+struct _ProxyLWP {
+   UInt			magic;		/* magic number */
+   ThreadId		tid;		/* scheduler's tid */
+   ThreadState		*tst;		/* thread state */
+   Int			lwp;		/* kernel's ID for LWP */
+   Int			exitcode;	/* ProxyLWP exit code */
+
+   Int			topx, frommain;	/* pipe fds */
+   vki_ksiginfo_t	siginfo;	/* received signal */
+   Bool			terminating;	/* in the middle of exiting */
+
+   /* State of proxy */
+   enum PXState		state;
+
+   jmp_buf		jumpbuf;
+
+#ifdef _ARCH_PROXY_EXTRA
+   ProxyArchExtra	archextra;	/* anything arch/OS-dependent */
+#endif /* _ARCH_PROXY_EXTRA */
+};
+
+#define PROXYLWP_OFFSET	(VKI_BYTES_PER_PAGE - sizeof(ProxyLWP))
+
+void proxy_syscall(Int syscallno, ThreadState *tst, 
+		   enum PXState *state , enum PXState poststate);
+Int  proxy_makethread(ProxyLWP *proxy);
+Bool proxy_wait(ProxyLWP *proxy, Bool block, Int *status);
+void proxy_arch_start(ProxyLWP *);
+void proxy_arch_finish(ProxyLWP *, Int);
+
+Int proxy_lwp(void *);
+
+/* state->string for debug messages */
+const Char *pxs_name(enum PXState s);
+
+extern const Addr sys_before, sys_restarted, sys_after, sys_done;
+
+ProxyLWP       *LWP_alloc(void);
+void		LWP_free(ProxyLWP *);
+ProxyLWP       *LWP_TSD(void *esp);
+void	       *LWP_stack(ProxyLWP *);
+
+#endif /* _COREGRIND_PROXYLWP_H */
diff -puN /dev/null coregrind/arch/i386-linux/vg_kerneliface.h
--- /dev/null	2003-01-30 02:24:37.000000000 -0800
+++ valgrind-jeremy/coregrind/arch/i386-linux/vg_kerneliface.h	2004-01-27 11:09:10.000000000 -0800
@@ -0,0 +1,781 @@
+
+/*--------------------------------------------------------------------*/
+/*--- A header file defining structures and constants which are    ---*/
+/*--- important at the kernel boundary for this platform.          ---*/
+/*---                                             vg_kerneliface.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+   This file is part of Valgrind, an extensible x86 protected-mode
+   emulator for monitoring program execution on x86-Unixes.
+
+   Copyright (C) 2000-2004 Julian Seward 
+      jseward@acm.org
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __I386_LINUX_VG_KERNELIFACE_H
+#define __I386_LINUX_VG_KERNELIFACE_H
+
+/* This file is ONLY to be included into vg_include.h.  Do not include
+   it directly into valgrind source .c files.  This file defines types
+   and constants for the kernel interface, and to make that clear
+   everything is prefixed VKI. */
+
+/*--- All the following stuff is correct for Linux kernels 2.2.X and
+      2.4.X. 
+---*/
+
+/* Should really get this from an include file somewhere. */
+#define VKI_BYTES_PER_PAGE_BITS 12
+#define VKI_BYTES_PER_PAGE (1 << VKI_BYTES_PER_PAGE_BITS)
+
+#define VKI_BYTES_PER_WORD 4
+#define VKI_WORDS_PER_PAGE (VKI_BYTES_PER_PAGE / VKI_BYTES_PER_WORD)
+
+
+/* An implementation of signal sets.  These are the same as the sigset
+   implementations in the relevant Linux kernels.  Note carefully that
+   this has nothing to do with glibc's signal sets.  We work entirely
+   at the kernel boundary, so the libc stuff is invisible and
+   irrelevant.  */
+
+/* The following is copied from
+   /usr/src/linux-2.4.9-13/include/asm-i386/signal.h */
+#define VKI_KNSIG       64  /* true for linux 2.2.X and 2.4.X */
+#define VKI_KNSIG_BPW   32  /* since we're using UInts */
+#define VKI_KNSIG_WORDS (VKI_KNSIG / VKI_KNSIG_BPW)
+
+typedef 
+   struct { 
+      UInt ws[VKI_KNSIG_WORDS]; 
+   }
+   vki_ksigset_t;
+
+
+typedef
+   struct {
+      void*         ksa_handler;
+      unsigned long ksa_flags;
+      void (*ksa_restorer)(void);
+      vki_ksigset_t ksa_mask;
+   }
+   vki_ksigaction;
+
+typedef 
+   struct {
+      void* ss_sp;
+      Int   ss_flags;
+      UInt  ss_size;
+   } 
+   vki_kstack_t;
+
+#define SI_MAX_SIZE	128
+#define SI_PAD_SIZE	((SI_MAX_SIZE/sizeof(int)) - 3)
+
+union vki_sigval {
+   Int sival_int;
+   void *sival_ptr;
+};
+
+typedef
+   struct {
+      Int si_signo;
+      Int si_errno;
+      Int si_code;
+
+      union {
+	 Int _pad[SI_PAD_SIZE];
+
+	 /* kill() */
+	 struct {
+	    Int _pid;		/* sender's pid */
+	    Short _uid;		/* sender's uid */
+	 } _kill;
+
+	 /* POSIX.1b timers */
+	 struct {
+	    UInt _timer1;
+	    UInt _timer2;
+	 } _timer;
+
+	 /* POSIX.1b signals */
+	 struct {
+	    Int _pid;		/* sender's pid */
+	    UShort _uid;		/* sender's uid */
+	    union vki_sigval _sigval;
+	 } _rt;
+
+	 /* SIGCHLD */
+	 struct {
+	    Int _pid;		/* which child */
+	    UShort _uid;		/* sender's uid */
+	    Int _status;		/* exit code */
+	    Int _utime;
+	    Int _stime;
+	 } _sigchld;
+
+	 /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+	 struct {
+	    void *_addr; /* faulting insn/memory ref. */
+	 } _sigfault;
+
+	 /* SIGPOLL */
+	 struct {
+	    Int _band;	/* POLL_IN, POLL_OUT, POLL_MSG */
+	    Int _fd;
+	 } _sigpoll;
+      } _sifields;
+   } vki_ksiginfo_t;
+
+/* linux-2.6/include/asm-generic/siginfo.h */
+
+#define VKI_SI_USER	0
+#define VKI_SI_QUEUE	-1
+#define VKI_SI_TKILL	-6
+
+struct vki_fpreg {
+	UShort significand[4];
+	UShort exponent;
+};
+
+struct vki_fpxreg {
+	UShort significand[4];
+	UShort exponent;
+	UShort padding[3];
+};
+
+struct vki_xmmreg {
+	UInt element[4];
+};
+
+struct vki_fpstate {
+	/* Regular FPU environment */
+	unsigned long 	cw;
+	unsigned long	sw;
+	unsigned long	tag;
+	unsigned long	ipoff;
+	unsigned long	cssel;
+	unsigned long	dataoff;
+	unsigned long	datasel;
+	struct vki_fpreg	_st[8];
+	unsigned short	status;
+	unsigned short	magic;		/* 0xffff = regular FPU data only */
+
+	/* FXSR FPU environment */
+	unsigned long	_fxsr_env[6];	/* FXSR FPU env is ignored */
+	unsigned long	mxcsr;
+	unsigned long	reserved;
+	struct vki_fpxreg	_fxsr_st[8];	/* FXSR FPU reg data is ignored */
+	struct vki_xmmreg	_xmm[8];
+	unsigned long	padding[56];
+};
+
+#define X86_FXSR_MAGIC		0x0000
+
+struct vki_sigcontext {
+	UShort	gs, __gsh;
+	UShort	fs, __fsh;
+	UShort	es, __esh;
+	UShort	ds, __dsh;
+	UInt	edi;
+	UInt	esi;
+	UInt	ebp;
+	UInt	esp;
+	UInt	ebx;
+	UInt	edx;
+	UInt	ecx;
+	UInt	eax;
+	UInt	trapno;
+	UInt	err;
+	UInt	eip;
+	UShort	cs, __csh;
+	UInt	eflags;
+	UInt	esp_at_signal;
+	UShort	ss, __ssh;
+	struct	vki_fpstate * fpstate;
+	UInt	oldmask;
+	UInt	cr2;
+};
+
+struct vki_ucontext {
+	UInt		  uc_flags;
+	struct vki_ucontext  *uc_link;
+	vki_kstack_t	  uc_stack;
+	struct vki_sigcontext uc_mcontext;
+	vki_ksigset_t	  uc_sigmask;	/* mask last for extensibility */
+};
+
+
+/* sigaltstack controls */
+#define VKI_SS_ONSTACK      1
+#define VKI_SS_DISABLE      2
+
+#define VKI_MINSIGSTKSZ     2048
+#define VKI_SIGSTKSZ        8192
+
+
+
+#define VKI_SIG_BLOCK          0    /* for blocking signals */
+#define VKI_SIG_UNBLOCK        1    /* for unblocking signals */
+#define VKI_SIG_SETMASK        2    /* for setting the signal mask */
+
+#define VKI_SIG_DFL ((void*)0)     /* default signal handling */
+#define VKI_SIG_IGN ((void*)1)     /* ignore signal */
+#define VKI_SIG_ERR ((void*)-1)    /* error return from signal */
+
+#define VKI_SA_ONSTACK      0x08000000
+#define VKI_SA_RESTART      0x10000000
+#define VKI_SA_NOCLDSTOP    0x00000001
+#define VKI_SA_SIGINFO      0x00000004
+#define VKI_SA_RESETHAND    0x80000000
+#define VKI_SA_ONESHOT      VKI_SA_RESETHAND
+#define VKI_SA_NODEFER      0x40000000
+#define VKI_SA_NOMASK       VKI_SA_NODEFER
+#define VKI_SA_NOCLDWAIT    0x00000002
+#if 0
+#define VKI_SA_INTERRUPT    0x20000000 /* dummy -- ignored */
+#define VKI_SA_RESTORER     0x04000000
+#endif
+
+/* extra wait flags */
+#define	VKI_WNOHANG	1		/* Don't block waiting.  */
+#define	VKI_WUNTRACED	2		/* Report status of stopped children.  */
+#define VKI__WALL	0x40000000	/* Wait for any child.  */
+#define VKI__WCLONE	0x80000000	/* Wait for cloned process.  */
+
+#define	VKI_SIGHUP	1	/* Hangup (POSIX).  */
+#define	VKI_SIGINT	2	/* Interrupt (ANSI).  */
+#define	VKI_SIGQUIT	3	/* Quit (POSIX).  */
+#define	VKI_SIGILL	4	/* Illegal instruction (ANSI).  */
+#define	VKI_SIGTRAP	5	/* Trace trap (POSIX).  */
+#define	VKI_SIGABRT	6	/* Abort (ANSI).  */
+#define	VKI_SIGIOT	6	/* IOT trap (4.2 BSD).  */
+#define	VKI_SIGBUS	7	/* BUS error (4.2 BSD).  */
+#define	VKI_SIGFPE	8	/* Floating-point exception (ANSI).  */
+#define	VKI_SIGKILL	9	/* Kill, unblockable (POSIX).  */
+#define	VKI_SIGUSR1	10	/* User-defined signal 1 (POSIX).  */
+#define	VKI_SIGSEGV	11	/* Segmentation violation (ANSI).  */
+#define	VKI_SIGUSR2	12	/* User-defined signal 2 (POSIX).  */
+#define	VKI_SIGPIPE	13	/* Broken pipe (POSIX).  */
+#define	VKI_SIGALRM	14	/* Alarm clock (POSIX).  */
+#define	VKI_SIGTERM	15	/* Termination (ANSI).  */
+#define	VKI_SIGSTKFLT	16	/* Stack fault.  */
+#define	VKI_SIGCLD	SIGCHLD	/* Same as SIGCHLD (System V).  */
+#define	VKI_SIGCHLD	17	/* Child status has changed (POSIX).  */
+#define	VKI_SIGCONT	18	/* Continue (POSIX).  */
+#define	VKI_SIGSTOP	19	/* Stop, unblockable (POSIX).  */
+#define	VKI_SIGTSTP	20	/* Keyboard stop (POSIX).  */
+#define	VKI_SIGTTIN	21	/* Background read from tty (POSIX).  */
+#define	VKI_SIGTTOU	22	/* Background write to tty (POSIX).  */
+#define	VKI_SIGURG	23	/* Urgent condition on socket (4.2 BSD).  */
+#define	VKI_SIGXCPU	24	/* CPU limit exceeded (4.2 BSD).  */
+#define	VKI_SIGXFSZ	25	/* File size limit exceeded (4.2 BSD).  */
+#define	VKI_SIGVTALRM	26	/* Virtual alarm clock (4.2 BSD).  */
+#define	VKI_SIGPROF	27	/* Profiling alarm clock (4.2 BSD).  */
+#define	VKI_SIGWINCH	28	/* Window size change (4.3 BSD, Sun).  */
+#define	VKI_SIGPOLL	SIGIO	/* Pollable event occurred (System V).  */
+#define	VKI_SIGIO	29	/* I/O now possible (4.2 BSD).  */
+#define	VKI_SIGPWR	30	/* Power failure restart (System V).  */
+#define	VKI_SIGSYS	31	/* Bad system call.  */
+#define	VKI_SIGUNUSED	31
+
+#define VKI_SIGRTMIN	    32
+#define VKI_SIGRTMAX	    63
+
+#define VKI_SIGVGINT	    (VKI_SIGRTMIN+0) /* signal for internal use - interrupt */
+#define VKI_SIGVGKILL	    (VKI_SIGRTMIN+1) /* signal for internal use - kill */
+#define VKI_SIGRTUSERMIN    (VKI_SIGRTMIN+2) /* first user-usable RT signal */
+
+/* The following are copied from include/asm-i386/mman.h .*/
+
+#define VKI_PROT_NONE      0x0		   /* No page permissions */
+#define VKI_PROT_READ      0x1             /* Page can be read.  */
+#define VKI_PROT_WRITE     0x2             /* Page can be written.  */
+#define VKI_PROT_EXEC      0x4             /* Page can be executed.  */
+#define VKI_MAP_ANONYMOUS  0x20            /* Don't use a file.  */
+#define VKI_MAP_SHARED	   0x01		   /* Share changes.  */
+#define VKI_MAP_PRIVATE    0x02            /* Changes are private.  */
+#define VKI_MAP_FIXED      0x10            /* Interpret addr exactly */
+#define VKI_MAP_NOSYMS     0x40000000	   /* internal pseudo-flag to disable symbol loading */
+#define VKI_MAP_CLIENT     0x80000000	   /* internal pseudo-flag to distinguish client mappings */
+
+/* linux/mman.h */
+#define VKI_MREMAP_MAYMOVE	1
+#define VKI_MREMAP_FIXED	2
+
+/* Copied from linux-2.4.19/include/asm-i386/fcntl.h */
+
+#define VKI_O_ACCMODE	       0003
+#define VKI_O_RDONLY             00
+#define VKI_O_WRONLY             01
+#define VKI_O_RDWR               02
+#define VKI_O_CREAT            0100 /* not fcntl */
+#define VKI_O_EXCL             0200 /* not fcntl */
+#define VKI_O_TRUNC           01000 /* not fcntl */
+#define VKI_O_APPEND          02000
+#define VKI_O_NONBLOCK        04000
+#define VKI_O_SYNC           010000
+#define VKI_FASYNC           020000 /* fcntl, for BSD compatibility */
+#define VKI_O_DIRECT         040000 /* direct disk access hint */
+#define VKI_O_LARGEFILE     0100000
+#define VKI_O_DIRECTORY     0200000 /* must be a directory */
+#define VKI_O_NOFOLLOW      0400000 /* don't follow links */
+
+#define VKI_SEEK_SET              0
+#define VKI_SEEK_CUR              1
+#define VKI_SEEK_END              2
+
+/* Copied from linux-2.4.19/include/linux/stat.h */
+
+#define VKI_S_IRWXU 00700
+#define VKI_S_IRUSR 00400
+#define VKI_S_IWUSR 00200
+#define VKI_S_IXUSR 00100
+
+#define VKI_S_IRWXG 00070
+#define VKI_S_IRGRP 00040
+#define VKI_S_IWGRP 00020
+#define VKI_S_IXGRP 00010
+
+#define VKI_S_IRWXO 00007
+#define VKI_S_IROTH 00004
+#define VKI_S_IWOTH 00002
+#define VKI_S_IXOTH 00001
+
+
+/* Copied from /usr/src/linux-2.4.9-13/include/asm/errno.h */
+
+#define VKI_EPERM            1      /* Operation not permitted */
+#define VKI_ENOENT	     2	    /* No such file or directory */
+#define VKI_ESRCH            3      /* No such process */
+#define VKI_EINTR            4      /* Interrupted system call */
+#define VKI_EBADF            9      /* Bad file number */
+#define VKI_ENOMEM          12      /* Out of memory */
+#define VKI_EWOULDBLOCK     VKI_EAGAIN  /* Operation would block */
+#define VKI_EAGAIN          11      /* Try again */
+#define	VKI_EACCES	    13      /* Permission denied */
+#define	VKI_EFAULT          14      /* Bad address */
+#define VKI_EEXIST	    17	    /* File exists */
+#define VKI_EINVAL          22      /* Invalid argument */
+#define VKI_EMFILE	    24	    /* Too many open files */
+#define VKI_ENOSYS          38      /* Function not implemented */
+
+#define VKI_ERESTARTSYS	    512	    /* Restart the syscall */
+
+/* Copied from linux/isdn.h */
+
+#define VKI_IIOCGETCPS  _IO( 'I',21 )
+#define VKI_IIOCNETGPN  _IO( 'I',34 )
+
+#define ISDN_MSNLEN          32
+
+typedef struct {
+    char name[ 10 ];
+    char phone[ ISDN_MSNLEN ];
+    int  outgoing;
+} isdn_net_ioctl_phone;
+
+
+/* Gawd ... hack ... */
+
+typedef struct vki__user_cap_header_struct {
+        UInt version;
+        int pid;
+} vki_cap_user_header_t;
+ 
+typedef struct vki__user_cap_data_struct {
+        UInt effective;
+        UInt permitted;
+        UInt inheritable;
+} vki_cap_user_data_t;
+  
+
+/* "Byrial Jensen" <byrial@image.dk> says:
+               [various] ioctls take a pointer to a "struct
+               termios" but this is another and shorter "struct
+               termios" than the one defined in <termios.h> and used
+               by tcgetattr(3) and tcsetattr(3) and other library
+               functions. GNU libc translate between its library
+               termios and the kernel termios. 
+*/
+
+#define VKI_SIZEOF_STRUCT_TERMIOS 36
+
+/* Adam Gundy <arg@cyberscience.com>, 20 Mar 2002, says: */
+#define VKI_SIZEOF_STRUCT_TERMIO 17
+
+
+/* File descriptor sets, for doing select().  Copied from
+   /usr/src/linux-2.4.9-31/include/linux/posix_types.h 
+*/
+/*
+ * This allows for 1024 file descriptors: if NR_OPEN is ever grown
+ * beyond that you'll have to change this too. But 1024 fd's seem to be
+ * enough even for such "real" unices like OSF/1, so hopefully this is
+ * one limit that doesn't have to be changed [again].
+ *
+ * Note that POSIX wants the FD_CLEAR(fd,fdsetp) defines to be in
+ * <sys/time.h> (and thus <linux/time.h>) - but this is a more logical
+ * place for them. Solved by having dummy defines in <sys/time.h>.
+ */
+
+/*
+ * Those macros may have been defined in <gnu/types.h>. But we always
+ * use the ones here. 
+ */
+#undef VKI_NFDBITS
+#define VKI_NFDBITS       (8 * sizeof(unsigned long))
+
+#undef VKI_FD_SETSIZE
+#define VKI_FD_SETSIZE    1024
+
+#undef VKI_FDSET_LONGS
+#define VKI_FDSET_LONGS   (VKI_FD_SETSIZE/VKI_NFDBITS)
+
+#undef VKI_FDELT
+#define VKI_FDELT(d)      ((d) / VKI_NFDBITS)
+
+#undef VKI_FDMASK
+#define VKI_FDMASK(d)     (1UL << ((d) % VKI_NFDBITS))
+
+typedef struct {
+        unsigned long vki_fds_bits [VKI_FDSET_LONGS];
+} vki_fd_set;
+
+
+/* Gawd ...
+   Copied from /usr/src/linux-2.4.9-31/./include/asm-i386/posix_types.h
+*/
+#undef  VKI_FD_SET
+#define VKI_FD_SET(fd,fdsetp) \
+                __asm__ __volatile__("btsl %1,%0": \
+                        "=m" (*(vki_fd_set *) (fdsetp)):"r" ((int) (fd)))
+
+#undef  VKI_FD_CLR
+#define VKI_FD_CLR(fd,fdsetp) \
+                __asm__ __volatile__("btrl %1,%0": \
+                        "=m" (*(vki_fd_set *) (fdsetp)):"r" ((int) (fd)))
+
+#undef  VKI_FD_ISSET
+#define VKI_FD_ISSET(fd,fdsetp) (__extension__ ({ \
+                unsigned char __result; \
+                __asm__ __volatile__("btl %1,%2 ; setb %0" \
+                        :"=q" (__result) :"r" ((int) (fd)), \
+                        "m" (*(vki_fd_set *) (fdsetp))); \
+                __result; }))
+
+#undef  VKI_FD_ZERO
+#define VKI_FD_ZERO(fdsetp) \
+do { \
+        int __d0, __d1; \
+        __asm__ __volatile__("cld ; rep ; stosl" \
+                        :"=m" (*(vki_fd_set *) (fdsetp)), \
+                          "=&c" (__d0), "=&D" (__d1) \
+                        :"a" (0), "1" (VKI_FDSET_LONGS), \
+                        "2" ((vki_fd_set *) (fdsetp)) : "memory"); \
+} while (0)
+
+
+
+struct vki_pollfd {
+   Int		fd;
+   Short	events;
+   Short	revents;
+};
+
+/* asm/poll.h */
+#define VKI_POLLIN          0x0001
+#define VKI_POLLPRI         0x0002
+#define VKI_POLLOUT         0x0004
+#define VKI_POLLERR         0x0008
+#define VKI_POLLHUP         0x0010
+#define VKI_POLLNVAL        0x0020
+
+
+
+/* 
+./include/asm-i386/posix_types.h:typedef long           __kernel_suseconds_t;
+./include/linux/types.h:typedef __kernel_suseconds_t    suseconds_t;
+
+./include/asm-i386/posix_types.h:typedef long           __kernel_time_t;
+./include/linux/types.h:typedef __kernel_time_t         time_t;
+*/
+
+struct vki_timeval {
+        /* time_t */ long         tv_sec;         /* seconds */
+        /* suseconds_t */ long    tv_usec;        /* microseconds */
+};
+
+
+
+/* For fcntl on fds ..
+   from ./include/asm-i386/fcntl.h */
+#define VKI_F_DUPFD	    0	    /* dup */
+#define VKI_F_GETFD	    1	    /* get close_on_exec */
+#define VKI_F_SETFD	    2	    /* set/clear close_on_exec */
+#define VKI_F_GETFL         3       /* get file->f_flags */
+#define VKI_F_SETFL         4       /* set file->f_flags */
+
+/* for F_[GET|SET]FL */
+#define VKI_FD_CLOEXEC	    1	    /* actually anything with low bit set goes */
+
+#define VKI_O_NONBLOCK        04000
+
+/* For nanosleep ... 
+   from ./include/linux/time.h */
+struct vki_timespec {
+        /* time_t */ long tv_sec;         /* seconds */
+        long    tv_nsec;        /* nanoseconds */
+};
+
+
+/* STAT stuff 
+   from /usr/src/linux-2.4.9-31/include/asm-i386/stat.h */
+struct vki_stat {
+        unsigned short st_dev;
+        unsigned short __pad1;
+        unsigned long st_ino;
+        unsigned short st_mode;
+        unsigned short st_nlink;
+        unsigned short st_uid;
+        unsigned short st_gid;
+        unsigned short st_rdev;
+        unsigned short __pad2;
+        unsigned long  st_size;
+        unsigned long  st_blksize;
+        unsigned long  st_blocks;
+        unsigned long  st_atime;
+        unsigned long  __unused1;
+        unsigned long  st_mtime;
+        unsigned long  __unused2;
+        unsigned long  st_ctime;
+        unsigned long  __unused3;
+        unsigned long  __unused4;
+        unsigned long  __unused5;
+};
+
+struct vki_stat64 {
+	unsigned long long	st_dev;
+	unsigned char	__pad0[4];
+
+#define STAT64_HAS_BROKEN_ST_INO	1
+	unsigned long	__st_ino;
+
+	unsigned int	st_mode;
+	unsigned int	st_nlink;
+
+	unsigned long	st_uid;
+	unsigned long	st_gid;
+
+	unsigned long long	st_rdev;
+	unsigned char	__pad3[4];
+
+	long long	st_size;
+	unsigned long	st_blksize;
+
+	unsigned long	st_blocks;	/* Number 512-byte blocks allocated. */
+	unsigned long	__pad4;		/* future possible st_blocks high bits */
+
+	unsigned long	st_atime;
+	unsigned long	st_atime_nsec;
+
+	unsigned long	st_mtime;
+	unsigned int	st_mtime_nsec;
+
+	unsigned long	st_ctime;
+	unsigned long	st_ctime_nsec;
+
+	unsigned long long	st_ino;
+};
+
+
+/* To do with the ELF frame constructed by the kernel on a process'
+   stack just before it transfers control to the program's interpreter
+   (to use the ELF parlance).
+   Constants from /usr/src/linux-2.4.9-31/include/linux/elf.h
+   Logic from     /usr/src/linux-2.4.9-31/fs/binfmt_elf.c
+                  and its counterpart in the 2.2.14 kernel sources 
+                  in Red Hat 6.2.  */
+#define VKI_AT_NULL   0
+#define VKI_AT_SYSINFO 32   /* address of system info page */
+#define VKI_AT_CLKTCK 17    /* frequency at which times() increments */
+#define VKI_AT_HWCAP  16    /* arch dependent hints at CPU capabilities */
+#define VKI_AT_BASE   7     /* base address of interpreter */
+#define VKI_AT_PAGESZ 6     /* system page size */
+#define VKI_AT_PHNUM  5     /* number of program headers */
+#define VKI_AT_PHENT  4     /* size of program header entry */
+#define VKI_AT_PHDR   3     /* program headers for program */
+#define VKI_AT_USER_AUX_SEGMENT 23  /* tell glibc what address segment
+                                       0x3B points to.  (Needed for
+                                       Red Hat Limbo, 7.3.92) */
+
+/* Including <linux/module.h> leads to loads of hassle because then we
+   need <asm/atomic.h> sometimes (RedHat 7.3) and that is a
+   kernel-only header which deliberately #errors on gcc-3.1.  Mucho
+   hassle considering that we only want to know sizeof(struct module).
+   Hence ...
+ 
+   #include <stdio.h>
+   #include <asm/atomic.h>
+   #include <linux/module.h>
+
+   int main ( void )
+   {
+      printf ("sizeof(struct module) = %d\n", sizeof(struct module) );
+      return 0;
+    }
+*/
+
+#define VKI_SIZEOF_STRUCT_MODULE 96
+
+
+/* This is the structure passed to the modify_ldt syscall.  Just so as
+   to confuse and annoy everyone, this is _not_ the same as an
+   VgLdtEntry and has to be translated into such.  The logic for doing
+   so, in vg_ldt.c, is copied from the kernel sources. */
+/*
+ * ldt.h
+ *
+ * Definitions of structures used with the modify_ldt system call.
+ */
+typedef struct vki_modify_ldt_ldt_s {
+        unsigned int  entry_number;
+        unsigned long base_addr;
+        unsigned int  limit;
+        unsigned int  seg_32bit:1;
+        unsigned int  contents:2;
+        unsigned int  read_exec_only:1;
+        unsigned int  limit_in_pages:1;
+        unsigned int  seg_not_present:1;
+        unsigned int  useable:1;
+        unsigned int  reserved:25;
+} vki_modify_ldt_t;
+
+#define VKI_MODIFY_LDT_CONTENTS_DATA        0
+#define VKI_MODIFY_LDT_CONTENTS_STACK       1
+#define VKI_MODIFY_LDT_CONTENTS_CODE        2
+
+#define VKI_GDT_TLS_ENTRIES 3
+#define VKI_GDT_TLS_MIN     6
+#define VKI_GDT_TLS_MAX     (VKI_GDT_TLS_MIN + VKI_GDT_TLS_ENTRIES)
+
+/* Flags for clone() */
+/* linux/sched.h */
+#define VKI_CSIGNAL		0x000000ff	/* signal mask to be sent at exit */
+#define VKI_CLONE_VM		0x00000100	/* set if VM shared between processes */
+#define VKI_CLONE_FS		0x00000200	/* set if fs info shared between processes */
+#define VKI_CLONE_FILES		0x00000400	/* set if open files shared between processes */
+#define VKI_CLONE_SIGHAND	0x00000800	/* set if signal handlers and blocked signals shared */
+#define VKI_CLONE_IDLETASK	0x00001000	/* set if new pid should be 0 (kernel only)*/
+#define VKI_CLONE_PTRACE	0x00002000	/* set if we want to let tracing continue on the child too */
+#define VKI_CLONE_VFORK		0x00004000	/* set if the parent wants the child to wake it up on mm_release */
+#define VKI_CLONE_PARENT	0x00008000	/* set if we want to have the same parent as the cloner */
+#define VKI_CLONE_THREAD	0x00010000	/* Same thread group? */
+#define VKI_CLONE_NEWNS		0x00020000	/* New namespace group? */
+#define VKI_CLONE_SYSVSEM	0x00040000	/* share system V SEM_UNDO semantics */
+#define VKI_CLONE_SETTLS	0x00080000	/* create a new TLS for the child */
+#define VKI_CLONE_PARENT_SETTID	0x00100000	/* set the TID in the parent */
+#define VKI_CLONE_CHILD_CLEARTID	0x00200000	/* clear the TID in the child */
+#define VKI_CLONE_DETACHED	0x00400000	/* parent wants no child-exit signal */
+#define VKI_CLONE_UNTRACED	0x00800000	/* set if the tracing process can't force VKI_CLONE_PTRACE on this clone */
+#define VKI_CLONE_CHILD_SETTID	0x01000000	/* set the TID in the child */
+
+/* 
+ * linux/futex.h
+ */
+
+#define VKI_FUTEX_WAIT    0
+#define VKI_FUTEX_WAKE    1
+#define VKI_FUTEX_FD      2
+#define VKI_FUTEX_REQUEUE 3
+
+/* This is the structure passed to the getdents syscall. */
+/*
+ * linux/dirent.h
+ */
+typedef struct vki_dirent {
+	long           d_ino;
+	long           d_off;
+	unsigned short d_reclen;
+	char           d_name[256];
+} vki_dirent;
+
+
+
+/* This is the structure passed to the getrlimit syscall. */
+/*
+ * bits/resource.h
+ */
+typedef struct vki_rlimit {
+	unsigned long rlim_cur;
+	unsigned long rlim_max;
+} vki_rlimit;
+
+#define VKI_RLIMIT_NOFILE 7
+
+/* Socket stuff. */
+/*
+ * sys/socket.h
+ */
+typedef unsigned short vki_sa_family_t;
+struct vki_sockaddr {
+  vki_sa_family_t sa_family;     /* Address family. */
+  char            sa_data[14];   /* Address data. */
+};
+
+/* statfs structs */
+/*
+ * bits/statfs.h
+ */
+
+struct statfs {
+        unsigned int f_type;
+        unsigned int f_bsize;
+        unsigned int f_blocks;
+        unsigned int f_bfree;
+        unsigned int f_bavail;
+        unsigned int f_files;
+        unsigned int f_ffree;
+        int f_fsid[ 2 ];
+        unsigned int f_namelen;
+        unsigned int f_frsize;
+        unsigned int f_spare[5];
+};
+
+struct statfs64 {
+        unsigned int f_type;
+        unsigned int f_bsize;
+        unsigned long long f_blocks;
+        unsigned long long f_bfree;
+        unsigned long long f_bavail;
+        unsigned long long f_files;
+        unsigned long long f_ffree;
+        int f_fsid[ 2 ];
+        unsigned int f_namelen;
+        unsigned int f_frsize;
+        unsigned int f_spare[5];
+};
+
+
+#endif /*  __I386_LINUX_VG_KERNELIFACE_H */
+
+/*--------------------------------------------------------------------*/
+/*--- end                                         vg_kerneliface.h ---*/
+/*--------------------------------------------------------------------*/
diff -puN /dev/null coregrind/arch/i386-freebsd/vg_kerneliface.h
--- /dev/null	2003-01-30 02:24:37.000000000 -0800
+++ valgrind-jeremy/coregrind/arch/i386-freebsd/vg_kerneliface.h	2004-01-27 11:09:10.000000000 -0800
@@ -0,0 +1,724 @@
+
+/*--------------------------------------------------------------------*/
+/*--- A header file defining structures and constants which are    ---*/
+/*--- important at the kernel boundary for this platform.          ---*/
+/*---                                             vg_kerneliface.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+   This file is part of Valgrind, an extensible x86 protected-mode
+   emulator for monitoring program execution on x86-Unixes.
+
+   Copyright (C) 2000-2004 Julian Seward 
+      jseward@acm.org
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __I386_FREEBSD_VG_KERNELIFACE_H
+#define __I386_FREEBSD_VG_KERNELIFACE_H
+
+/* This file is ONLY to be included into vg_include.h.  Do not include
+   it directly into valgrind source .c files.  This file defines types
+   and constants for the kernel interface, and to make that clear
+   everything is prefixed VKI. */
+
+/*--- All the following stuff is correct for Linux kernels 2.2.X and
+      2.4.X. 
+---*/
+
+/* Should really get this from an include file somewhere. */
+#define VKI_BYTES_PER_PAGE_BITS 12
+#define VKI_BYTES_PER_PAGE (1 << VKI_BYTES_PER_PAGE_BITS)
+
+#define VKI_BYTES_PER_WORD 4
+#define VKI_WORDS_PER_PAGE (VKI_BYTES_PER_PAGE / VKI_BYTES_PER_WORD)
+
+
+/* An implementation of signal sets.  These are the same as the sigset
+   implementations in the relevant Linux kernels.  Note carefully that
+   this has nothing to do with glibc's signal sets.  We work entirely
+   at the kernel boundary, so the libc stuff is invisible and
+   irrelevant.  */
+
+/* The following is copied from
+   /usr/src/linux-2.4.9-13/include/asm-i386/signal.h */
+#define VKI_KNSIG	128
+#define VKI_KNSIG_WORDS	4
+#define VKI_KNSIG_BPW	32
+
+typedef 
+   struct { 
+      UInt ws[VKI_KNSIG_WORDS]; 
+   }
+   vki_ksigset_t;
+
+
+typedef
+   struct {
+      void*         ksa_handler;
+      int	    ksa_flags;
+      vki_ksigset_t ksa_mask;
+   }
+   vki_ksigaction;
+
+typedef 
+   struct {
+      void* ss_sp;
+      UInt  ss_size;
+      Int   ss_flags;
+   } 
+   vki_kstack_t;
+
+#define SI_MAX_SIZE	128
+#define SI_PAD_SIZE	((SI_MAX_SIZE/sizeof(int)) - 3)
+
+union vki_sigval {
+   Int sival_int;
+   void *sival_ptr;
+};
+
+typedef
+   struct {
+      Int si_signo;
+      Int si_errno;
+      Int si_code;
+
+      Int si_pid;		/* sender's pid */
+      Int si_uid;		/* sender's ruid */
+      Int si_status;		/* exit value */
+      void *si_addr;		/* faulting instruction */
+      union {
+	 Int sigval_int;
+	 void *sigval_ptr;
+      };
+      Long	si_band;	/* band event for SIGPOLL */
+      Int	__spare__[7];	/* gimme some slack */
+   } vki_ksiginfo_t;
+
+/* FreeBSD-5.2/sys/sys/signal.h */
+
+#define VKI_SI_USER	0x10001
+#define VKI_SI_QUEUE	0x10002
+#define VKI_SI_TIMER	0x10003	
+#define VKI_SI_ASYNCIO	0x10004
+#define VKI_SI_MESGQ	0x10005	
+
+struct vki_fpreg {
+	UShort significand[4];
+	UShort exponent;
+};
+
+struct vki_fpxreg {
+	UShort significand[4];
+	UShort exponent;
+	UShort padding[3];
+};
+
+struct vki_xmmreg {
+	UInt element[4];
+};
+
+struct vki_fpstate {
+	/* Regular FPU environment */
+	unsigned long 	cw;
+	unsigned long	sw;
+	unsigned long	tag;
+	unsigned long	ipoff;
+	unsigned long	cssel;
+	unsigned long	dataoff;
+	unsigned long	datasel;
+	struct vki_fpreg	_st[8];
+	unsigned short	status;
+	unsigned short	magic;		/* 0xffff = regular FPU data only */
+
+	/* FXSR FPU environment */
+	unsigned long	_fxsr_env[6];	/* FXSR FPU env is ignored */
+	unsigned long	mxcsr;
+	unsigned long	reserved;
+	struct vki_fpxreg	_fxsr_st[8];	/* FXSR FPU reg data is ignored */
+	struct vki_xmmreg	_xmm[8];
+	unsigned long	padding[56];
+};
+
+#define X86_FXSR_MAGIC		0x0000
+
+struct vki_sigcontext {
+	vki_ksigset_t sc_mask;	/* signal mask to restore */
+	int	sc_onstack;		/* sigstack state to restore */
+	int	sc_gs;			/* machine state (struct trapframe) */
+	int	sc_fs;
+	int	sc_es;
+	int	sc_ds;
+	int	sc_edi;
+	int	sc_esi;
+	int	sc_ebp;
+	int	sc_isp;
+	int	sc_ebx;
+	int	sc_edx;
+	int	sc_ecx;
+	int	sc_eax;
+	int	sc_trapno;
+	int	sc_err;
+	int	sc_eip;
+	int	sc_cs;
+	int	sc_efl;
+	int	sc_esp;
+	int	sc_ss;
+	int	sc_len;			/* sizeof(mcontext_t) */
+	/*
+	 * XXX - See <machine/ucontext.h> and <machine/npx.h> for
+	 *       the following fields.
+	 */
+	int	sc_fpformat;
+	int	sc_ownedfp;
+	int	sc_spare1[1];
+	int	sc_fpstate[128] __aligned(16);
+	int	sc_spare2[8];
+};
+
+typedef struct vki_mcontext {
+	/*
+	 * The first 20 fields must match the definition of
+	 * sigcontext. So that we can support sigcontext
+	 * and ucontext_t at the same time.
+	 */
+	int	mc_onstack;		/* XXX - sigcontext compat. */
+	int	mc_gs;			/* machine state (struct trapframe) */
+	int	mc_fs;
+	int	mc_es;
+	int	mc_ds;
+	int	mc_edi;
+	int	mc_esi;
+	int	mc_ebp;
+	int	mc_isp;
+	int	mc_ebx;
+	int	mc_edx;
+	int	mc_ecx;
+	int	mc_eax;
+	int	mc_trapno;
+	int	mc_err;
+	int	mc_eip;
+	int	mc_cs;
+	int	mc_eflags;
+	int	mc_esp;
+	int	mc_ss;
+
+	int	mc_len;			/* sizeof(mcontext_t) */
+#define	VKI_MC_FPFMT_NODEV		0x10000	/* device not present or configured */
+#define	VKI_MC_FPFMT_387		0x10001
+#define	VKI_MC_FPFMT_XMM		0x10002
+	int	mc_fpformat;
+#define	VKI_MC_FPOWNED_NONE	0x20000	/* FP state not used */
+#define	VKI_MC_FPOWNED_FPU		0x20001	/* FP state came from FPU */
+#define	VKI_MC_FPOWNED_PCB		0x20002	/* FP state came from PCB */
+	int	mc_ownedfp;
+	int	mc_spare1[1];		/* align next field to 16 bytes */
+	/*
+	 * See <machine/npx.h> for the internals of mc_fpstate[].
+	 */
+	int	mc_fpstate[128] __aligned(16);
+	int	mc_spare2[8];
+} vki_mcontext_t;
+
+typedef struct vki_ucontext {
+	/*
+	 * Keep the order of the first two fields. Also,
+	 * keep them the first two fields in the structure.
+	 * This way we can have a union with struct
+	 * sigcontext and ucontext_t. This allows us to
+	 * support them both at the same time.
+	 * note: the union is not defined, though.
+	 */
+	vki_ksigset_t	uc_sigmask;
+	vki_mcontext_t	uc_mcontext;
+
+	struct vki_ucontext *uc_link;
+	vki_kstack_t	uc_stack;
+	Int		uc_flags;
+#define	VKI_UCF_SWAPPED	0x00000001	/* Used by swapcontext(3). */
+	Int		__spare__[4];
+} vki_ucontext_t;;
+
+
+/* sigaltstack controls */
+#define VKI_SS_ONSTACK      1
+#define VKI_SS_DISABLE      2
+
+#define VKI_MINSIGSTKSZ     2048
+#define VKI_SIGSTKSZ        8192
+
+
+
+#define VKI_SIG_BLOCK          1    /* for blocking signals */
+#define VKI_SIG_UNBLOCK        2    /* for unblocking signals */
+#define VKI_SIG_SETMASK        3    /* for setting the signal mask */
+
+#define VKI_SIG_DFL ((void*)0)     /* default signal handling */
+#define VKI_SIG_IGN ((void*)1)     /* ignore signal */
+#define VKI_SIG_ERR ((void*)-1)    /* error return from signal */
+
+#define	VKI_SA_NOCLDSTOP	0x0008	/* do not generate SIGCHLD on child stop */
+#define	VKI_SA_ONSTACK		0x0001	/* take signal on signal stack */
+#define	VKI_SA_RESTART		0x0002	/* restart system call on signal return */
+#define	VKI_SA_RESETHAND	0x0004	/* reset to SIG_DFL when taking signal */
+#define	VKI_SA_NODEFER		0x0010	/* don't mask the signal we're delivering */
+#define	VKI_SA_NOCLDWAIT	0x0020	/* don't keep zombies around */
+#define	VKI_SA_SIGINFO		0x0040	/* signal handler with SA_SIGINFO args */
+
+/* extra wait flags */
+#define	VKI_WNOHANG	1		/* Don't block waiting.  */
+#define	VKI_WUNTRACED	2		/* Report status of stopped children.  */
+#define VKI__WALL	0x40000000	/* Wait for any child.  */
+#define VKI__WCLONE	0x80000000	/* Wait for cloned process.  */
+
+#define	VKI_SIGHUP		1	/* hangup */
+#define	VKI_SIGINT		2	/* interrupt */
+#define	VKI_SIGQUIT		3	/* quit */
+#define	VKI_SIGILL		4	/* illegal instr. (not reset when caught) */
+#define	VKI_SIGTRAP		5	/* trace trap (not reset when caught) */
+#define	VKI_SIGABRT		6	/* abort() */
+#define	VKI_SIGIOT		VKI_SIGABRT	/* compatibility */
+#define	VKI_SIGEMT		7	/* EMT instruction */
+#define	VKI_SIGFPE		8	/* floating point exception */
+#define	VKI_SIGKILL		9	/* kill (cannot be caught or ignored) */
+#define	VKI_SIGBUS		10	/* bus error */
+#define	VKI_SIGSEGV		11	/* segmentation violation */
+#define	VKI_SIGSYS		12	/* non-existent system call invoked */
+#define	VKI_SIGPIPE		13	/* write on a pipe with no one to read it */
+#define	VKI_SIGALRM		14	/* alarm clock */
+#define	VKI_SIGTERM		15	/* software termination signal from kill */
+#define	VKI_SIGURG		16	/* urgent condition on IO channel */
+#define	VKI_SIGSTOP		17	/* sendable stop signal not from tty */
+#define	VKI_SIGTSTP		18	/* stop signal from tty */
+#define	VKI_SIGCONT		19	/* continue a stopped process */
+#define	VKI_SIGCHLD		20	/* to parent on child stop or exit */
+#define	VKI_SIGTTIN		21	/* to readers pgrp upon background tty read */
+#define	VKI_SIGTTOU		22	/* like TTIN if (tp->t_local&LTOSTOP) */
+#define	VKI_SIGIO		23	/* input/output possible signal */
+#define	VKI_SIGXCPU		24	/* exceeded CPU time limit */
+#define	VKI_SIGXFSZ		25	/* exceeded file size limit */
+#define	VKI_SIGVTALRM	26	/* virtual time alarm */
+#define	VKI_SIGPROF		27	/* profiling time alarm */
+#define	VKI_SIGWINCH	28	/* window size changes */
+#define	VKI_SIGINFO		29	/* information request */
+#define	VKI_SIGUSR1		30	/* user defined signal 1 */
+#define	VKI_SIGUSR2		31	/* user defined signal 2 */
+#define	VKI_SIGTHR		32	/* Thread interrupt. */
+
+#define VKI_SIGRTMIN		64
+#define VKI_SIGRTMAX		96
+#define VKI_SIGVGINT	    (VKI_SIGRTMIN+0) /* signal for internal use - interrupt */
+#define VKI_SIGVGKILL	    (VKI_SIGRTMIN+1) /* signal for internal use - kill */
+#define VKI_SIGRTUSERMIN    (VKI_SIGRTMIN+2) /* first user-usable RT signal */
+
+/* The following are copied from include/asm-i386/mman.h .*/
+
+#define VKI_PROT_NONE      0x0		   /* No page permissions */
+#define VKI_PROT_READ      0x1             /* Page can be read.  */
+#define VKI_PROT_WRITE     0x2             /* Page can be written.  */
+#define VKI_PROT_EXEC      0x4             /* Page can be executed.  */
+#define VKI_MAP_SHARED	   0x01		   /* Share changes.  */
+#define VKI_MAP_PRIVATE    0x02            /* Changes are private.  */
+#define VKI_MAP_FIXED      0x10            /* Interpret addr exactly */
+#define VKI_MAP_ANONYMOUS  0x1000          /* Don't use a file.  */
+#define VKI_MAP_NOSYMS     0x40000000	   /* internal pseudo-flag to disable symbol loading */
+#define VKI_MAP_CLIENT     0x80000000	   /* internal pseudo-flag to distinguish client mappings */
+
+/* linux/mman.h */
+#define VKI_MREMAP_MAYMOVE	1
+#define VKI_MREMAP_FIXED	2
+
+/* Copied from linux-2.4.19/include/asm-i386/fcntl.h */
+
+#define VKI_O_ACCMODE	       0003
+#define VKI_O_RDONLY             00
+#define VKI_O_WRONLY             01
+#define VKI_O_RDWR               02
+#define VKI_O_NONBLOCK           04
+#define VKI_O_CREAT            0100 /* not fcntl */
+#define VKI_O_EXCL             0200 /* not fcntl */
+#define VKI_O_TRUNC           01000 /* not fcntl */
+#define VKI_O_APPEND          02000
+#define VKI_O_SYNC           010000
+#define VKI_FASYNC           020000 /* fcntl, for BSD compatibility */
+#define VKI_O_DIRECT         040000 /* direct disk access hint */
+#define VKI_O_LARGEFILE     0100000
+#define VKI_O_DIRECTORY     0200000 /* must be a directory */
+#define VKI_O_NOFOLLOW      0400000 /* don't follow links */
+
+#define VKI_SEEK_SET              0
+#define VKI_SEEK_CUR              1
+#define VKI_SEEK_END              2
+
+/* Copied from linux-2.4.19/include/linux/stat.h */
+
+#define VKI_S_IRWXU 00700
+#define VKI_S_IRUSR 00400
+#define VKI_S_IWUSR 00200
+#define VKI_S_IXUSR 00100
+
+#define VKI_S_IRWXG 00070
+#define VKI_S_IRGRP 00040
+#define VKI_S_IWGRP 00020
+#define VKI_S_IXGRP 00010
+
+#define VKI_S_IRWXO 00007
+#define VKI_S_IROTH 00004
+#define VKI_S_IWOTH 00002
+#define VKI_S_IXOTH 00001
+
+
+/* Copied from /usr/src/linux-2.4.9-13/include/asm/errno.h */
+
+#define VKI_EPERM            1      /* Operation not permitted */
+#define VKI_ENOENT	     2	    /* No such file or directory */
+#define VKI_ESRCH            3      /* No such process */
+#define VKI_EINTR            4      /* Interrupted system call */
+#define VKI_EBADF            9      /* Bad file number */
+#define VKI_ENOMEM          12      /* Out of memory */
+#define VKI_EWOULDBLOCK     VKI_EAGAIN  /* Operation would block */
+#define VKI_EAGAIN          11      /* Try again */
+#define	VKI_EACCES	    13      /* Permission denied */
+#define	VKI_EFAULT          14      /* Bad address */
+#define VKI_EEXIST	    17	    /* File exists */
+#define VKI_EINVAL          22      /* Invalid argument */
+#define VKI_EMFILE	    24	    /* Too many open files */
+#define VKI_ENOSYS          38      /* Function not implemented */
+
+#define VKI_ERESTARTSYS	    512	    /* Restart the syscall */
+
+/* Copied from linux/isdn.h */
+
+#define VKI_IIOCGETCPS  _IO( 'I',21 )
+#define VKI_IIOCNETGPN  _IO( 'I',34 )
+
+#define ISDN_MSNLEN          32
+
+typedef struct {
+    char name[ 10 ];
+    char phone[ ISDN_MSNLEN ];
+    int  outgoing;
+} isdn_net_ioctl_phone;
+
+
+/* Gawd ... hack ... */
+
+typedef struct vki__user_cap_header_struct {
+        UInt version;
+        int pid;
+} vki_cap_user_header_t;
+ 
+typedef struct vki__user_cap_data_struct {
+        UInt effective;
+        UInt permitted;
+        UInt inheritable;
+} vki_cap_user_data_t;
+  
+
+/* "Byrial Jensen" <byrial@image.dk> says:
+               [various] ioctls take a pointer to a "struct
+               termios" but this is another and shorter "struct
+               termios" than the one defined in <termios.h> and used
+               by tcgetattr(3) and tcsetattr(3) and other library
+               functions. GNU libc translate between its library
+               termios and the kernel termios. 
+*/
+
+#define VKI_SIZEOF_STRUCT_TERMIOS 36
+
+/* Adam Gundy <arg@cyberscience.com>, 20 Mar 2002, says: */
+#define VKI_SIZEOF_STRUCT_TERMIO 17
+
+
+/* File descriptor sets, for doing select().  Copied from
+   /usr/src/linux-2.4.9-31/include/linux/posix_types.h 
+*/
+/*
+ * This allows for 1024 file descriptors: if NR_OPEN is ever grown
+ * beyond that you'll have to change this too. But 1024 fd's seem to be
+ * enough even for such "real" unices like OSF/1, so hopefully this is
+ * one limit that doesn't have to be changed [again].
+ *
+ * Note that POSIX wants the FD_CLEAR(fd,fdsetp) defines to be in
+ * <sys/time.h> (and thus <linux/time.h>) - but this is a more logical
+ * place for them. Solved by having dummy defines in <sys/time.h>.
+ */
+
+/*
+ * Those macros may have been defined in <gnu/types.h>. But we always
+ * use the ones here. 
+ */
+#undef VKI_NFDBITS
+#define VKI_NFDBITS       (8 * sizeof(unsigned long))
+
+#undef VKI_FD_SETSIZE
+#define VKI_FD_SETSIZE    1024
+
+#undef VKI_FDSET_LONGS
+#define VKI_FDSET_LONGS   (VKI_FD_SETSIZE/VKI_NFDBITS)
+
+#undef VKI_FDELT
+#define VKI_FDELT(d)      ((d) / VKI_NFDBITS)
+
+#undef VKI_FDMASK
+#define VKI_FDMASK(d)     (1UL << ((d) % VKI_NFDBITS))
+
+typedef struct {
+        unsigned long vki_fds_bits [VKI_FDSET_LONGS];
+} vki_fd_set;
+
+
+/* Gawd ...
+   Copied from /usr/src/linux-2.4.9-31/./include/asm-i386/posix_types.h
+*/
+#undef  VKI_FD_SET
+#define VKI_FD_SET(fd,fdsetp) \
+                __asm__ __volatile__("btsl %1,%0": \
+                        "=m" (*(vki_fd_set *) (fdsetp)):"r" ((int) (fd)))
+
+#undef  VKI_FD_CLR
+#define VKI_FD_CLR(fd,fdsetp) \
+                __asm__ __volatile__("btrl %1,%0": \
+                        "=m" (*(vki_fd_set *) (fdsetp)):"r" ((int) (fd)))
+
+#undef  VKI_FD_ISSET
+#define VKI_FD_ISSET(fd,fdsetp) (__extension__ ({ \
+                unsigned char __result; \
+                __asm__ __volatile__("btl %1,%2 ; setb %0" \
+                        :"=q" (__result) :"r" ((int) (fd)), \
+                        "m" (*(vki_fd_set *) (fdsetp))); \
+                __result; }))
+
+#undef  VKI_FD_ZERO
+#define VKI_FD_ZERO(fdsetp) \
+do { \
+        int __d0, __d1; \
+        __asm__ __volatile__("cld ; rep ; stosl" \
+                        :"=m" (*(vki_fd_set *) (fdsetp)), \
+                          "=&c" (__d0), "=&D" (__d1) \
+                        :"a" (0), "1" (VKI_FDSET_LONGS), \
+                        "2" ((vki_fd_set *) (fdsetp)) : "memory"); \
+} while (0)
+
+
+
+struct vki_pollfd {
+   Int		fd;
+   Short	events;
+   Short	revents;
+};
+
+/* asm/poll.h */
+#define VKI_POLLIN          0x0001
+#define VKI_POLLPRI         0x0002
+#define VKI_POLLOUT         0x0004
+#define VKI_POLLERR         0x0008
+#define VKI_POLLHUP         0x0010
+#define VKI_POLLNVAL        0x0020
+
+
+
+/* 
+./include/asm-i386/posix_types.h:typedef long           __kernel_suseconds_t;
+./include/linux/types.h:typedef __kernel_suseconds_t    suseconds_t;
+
+./include/asm-i386/posix_types.h:typedef long           __kernel_time_t;
+./include/linux/types.h:typedef __kernel_time_t         time_t;
+*/
+
+struct vki_timeval {
+        /* time_t */ long         tv_sec;         /* seconds */
+        /* suseconds_t */ long    tv_usec;        /* microseconds */
+};
+
+
+
+/* For fcntl on fds ..
+   from ./include/asm-i386/fcntl.h */
+#define VKI_F_DUPFD	    0	    /* dup */
+#define VKI_F_GETFD	    1	    /* get close_on_exec */
+#define VKI_F_SETFD	    2	    /* set/clear close_on_exec */
+#define VKI_F_GETFL         3       /* get file->f_flags */
+#define VKI_F_SETFL         4       /* set file->f_flags */
+
+/* for F_[GET|SET]FL */
+#define VKI_FD_CLOEXEC	    1	    /* actually anything with low bit set goes */
+
+#define VKI_O_NONBLOCK        04000
+
+/* For nanosleep ... 
+   from ./include/linux/time.h */
+struct vki_timespec {
+        /* time_t */ long tv_sec;         /* seconds */
+        long    tv_nsec;        /* nanoseconds */
+};
+
+
+/* STAT stuff 
+   from /usr/src/sys/sys/stat.h */
+struct vki_stat {
+        unsigned int st_dev;
+        unsigned long st_ino;
+        unsigned short st_mode;
+        unsigned short st_nlink;
+        unsigned int st_uid;
+        unsigned int st_gid;
+        unsigned int st_rdev;
+	unsigned long st_atime;
+	unsigned long st_atimensec;
+	unsigned long st_mtime;
+	unsigned long st_mtimensec;
+	unsigned long st_ctime;
+	unsigned long st_ctimensec;
+	unsigned long long st_size;
+	unsigned long long st_blocks;
+        unsigned long  st_blksize;
+	unsigned int st_flags;
+	unsigned int st_gen;
+	unsigned int st_lspare;
+	unsigned long st_birthtime;
+	unsigned long st_birthtimensec;
+	unsigned long st_pad1;
+	unsigned long st_pad2;
+};
+
+
+/* To do with the ELF frame constructed by the kernel on a process'
+   stack just before it transfers control to the program's interpreter
+   (to use the ELF parlance).
+   Constants from /usr/src/linux-2.4.9-31/include/linux/elf.h
+   Logic from     /usr/src/linux-2.4.9-31/fs/binfmt_elf.c
+                  and its counterpart in the 2.2.14 kernel sources 
+                  in Red Hat 6.2.  */
+#define VKI_AT_NULL   0
+#define VKI_AT_SYSINFO 32   /* address of system info page */
+#define VKI_AT_CLKTCK 17    /* frequency at which times() increments */
+#define VKI_AT_HWCAP  16    /* arch dependent hints at CPU capabilities */
+#define VKI_AT_BASE   7     /* base address of interpreter */
+#define VKI_AT_PAGESZ 6     /* system page size */
+#define VKI_AT_PHNUM  5     /* number of program headers */
+#define VKI_AT_PHENT  4     /* size of program header entry */
+#define VKI_AT_PHDR   3     /* program headers for program */
+#define VKI_AT_USER_AUX_SEGMENT 23  /* tell glibc what address segment
+                                       0x3B points to.  (Needed for
+                                       Red Hat Limbo, 7.3.92) */
+
+/* Including <linux/module.h> leads to loads of hassle because then we
+   need <asm/atomic.h> sometimes (RedHat 7.3) and that is a
+   kernel-only header which deliberately #errors on gcc-3.1.  Mucho
+   hassle considering that we only want to know sizeof(struct module).
+   Hence ...
+ 
+   #include <stdio.h>
+   #include <asm/atomic.h>
+   #include <linux/module.h>
+
+   int main ( void )
+   {
+      printf ("sizeof(struct module) = %d\n", sizeof(struct module) );
+      return 0;
+    }
+*/
+
+#define VKI_SIZEOF_STRUCT_MODULE 96
+
+
+/* This is the structure passed to the modify_ldt syscall.  Just so as
+   to confuse and annoy everyone, this is _not_ the same as an
+   VgLdtEntry and has to be translated into such.  The logic for doing
+   so, in vg_ldt.c, is copied from the kernel sources. */
+/*
+ * ldt.h
+ *
+ * Definitions of structures used with the modify_ldt system call.
+ */
+typedef struct vki_modify_ldt_ldt_s {
+        unsigned int  entry_number;
+        unsigned long base_addr;
+        unsigned int  limit;
+        unsigned int  seg_32bit:1;
+        unsigned int  contents:2;
+        unsigned int  read_exec_only:1;
+        unsigned int  limit_in_pages:1;
+        unsigned int  seg_not_present:1;
+        unsigned int  useable:1;
+} vki_modify_ldt_t;
+
+#define VKI_MODIFY_LDT_CONTENTS_DATA        0
+#define VKI_MODIFY_LDT_CONTENTS_STACK       1
+#define VKI_MODIFY_LDT_CONTENTS_CODE        2
+
+/* Flags for rfork */
+#define	VKI_RFNAMEG		(1<<0)	/* UNIMPL new plan9 `name space' */
+#define	VKI_RFENVG		(1<<1)	/* UNIMPL copy plan9 `env space' */
+#define	VKI_RFFDG		(1<<2)	/* copy fd table */
+#define	VKI_RFNOTEG		(1<<3)	/* UNIMPL create new plan9 `note group' */
+#define	VKI_RFPROC		(1<<4)	/* change child (else changes curproc) */
+#define	VKI_RFMEM		(1<<5)	/* share `address space' */
+#define	VKI_RFNOWAIT	(1<<6)	/* give child to init */
+#define	VKI_RFCNAMEG	(1<<10)	/* UNIMPL zero plan9 `name space' */
+#define	VKI_RFCENVG		(1<<11)	/* UNIMPL zero plan9 `env space' */
+#define	VKI_RFCFDG		(1<<12)	/* close all fds, zero fd table */
+#define	VKI_RFTHREAD	(1<<13)	/* enable kernel thread support */
+#define	VKI_RFSIGSHARE	(1<<14)	/* share signal handlers */
+#define	VKI_RFLINUXTHPN	(1<<16)	/* do linux clone exit parent notification */
+#define	VKI_RFSTOPPED	(1<<17)	/* leave child in a stopped state */
+#define	VKI_RFHIGHPID	(1<<18)	/* use a pid higher then 10 (idleproc) */
+#define	VKI_RFPPWAIT	(1<<31)	/* parent sleeps until child exits (vfork) */
+#define	VKI_RFKERNELONLY	(RFSTOPPED | RFHIGHPID | RFPPWAIT)
+
+/* This is the structure passed to the getdents syscall. */
+/*
+ * linux/dirent.h
+ */
+typedef struct vki_dirent {
+	long           d_ino;
+	long           d_off;
+	unsigned short d_reclen;
+	char           d_name[256];
+} vki_dirent;
+
+
+
+/* This is the structure passed to the getrlimit syscall. */
+/*
+ * bits/resource.h
+ */
+typedef struct vki_rlimit {
+	unsigned long long rlim_cur;
+	unsigned long long rlim_max;
+} vki_rlimit;
+
+#define VKI_RLIMIT_NOFILE 8
+
+/* Socket stuff. */
+/*
+ * sys/socket.h
+ */
+typedef unsigned short vki_sa_family_t;
+struct vki_sockaddr {
+  vki_sa_family_t sa_family;     /* Address family. */
+  char            sa_data[14];   /* Address data. */
+};
+
+#endif /* __I386_FREEBSD_VG_KERNELIFACE_H */
+
+/*--------------------------------------------------------------------*/
+/*--- end                                         vg_kerneliface.h ---*/
+/*--------------------------------------------------------------------*/
diff -puN -L coregrind/vg_syscalls.c coregrind/vg_syscalls.c~archdep /dev/null
--- valgrind/coregrind/vg_syscalls.c
+++ /dev/null	2003-01-30 02:24:37.000000000 -0800
@@ -1,5495 +0,0 @@
-
-/*--------------------------------------------------------------------*/
-/*--- Handle system calls.                           vg_syscalls.c ---*/
-/*--------------------------------------------------------------------*/
-
-/*
-   This file is part of Valgrind, an extensible x86 protected-mode
-   emulator for monitoring program execution on x86-Unixes.
-
-   Copyright (C) 2000-2004 Julian Seward 
-      jseward@acm.org
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of the
-   License, or (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307, USA.
-
-   The GNU General Public License is contained in the file COPYING.
-*/
-
-#include "vg_include.h"
-
-/* vg_unsafe.h should NOT be included into any file except this
-   one. */
-#include "vg_unsafe.h"
-
-
-/* All system calls are channelled through here, doing two things:
-
-   * notify the skin of the memory events (reads, writes) happening
-
-   * perform the syscall, usually by passing it along to the kernel
-     unmodified.
-
-   A magical piece of assembly code, VG_(do_syscall)(), in vg_syscall.S
-   does the tricky bit of passing a syscall to the kernel, whilst
-   having the simulator retain control.
-*/
-
-#define SYSCALL_TRACK(fn, args...)  VG_TRACK(fn, Vg_CoreSysCall, ## args)
-
-#define MAYBE_PRINTF(format, args...)  \
-   if (VG_(clo_trace_syscalls))        \
-      VG_(printf)(format, ## args)
-
-
-/* ---------------------------------------------------------------------
-   A simple atfork() facility for Valgrind's internal use
-   ------------------------------------------------------------------ */
-
-struct atfork {
-   vg_atfork_t	pre;
-   vg_atfork_t	parent;
-   vg_atfork_t	child;
-};
-
-#define VG_MAX_ATFORK	10
-
-static struct atfork atforks[VG_MAX_ATFORK];
-static Int n_atfork;
-
-void VG_(atfork)(vg_atfork_t pre, vg_atfork_t parent, vg_atfork_t child)
-{
-   Int i;
-
-   for(i = 0; i < n_atfork; i++) {
-      if (atforks[i].pre == pre &&
-	  atforks[i].parent == parent &&
-	  atforks[i].child == child)
-	 return;
-   }
-
-   if (n_atfork >= VG_MAX_ATFORK)
-      VG_(core_panic)("Too many VG_(atfork) handlers requested: raise VG_MAX_ATFORK");
-
-   atforks[n_atfork].pre    = pre;
-   atforks[n_atfork].parent = parent;
-   atforks[n_atfork].child  = child;
-
-   n_atfork++;
-}
-
-static void do_atfork_pre(ThreadId tid)
-{
-   Int i;
-
-   for(i = 0; i < n_atfork; i++)
-      if (atforks[i].pre != NULL)
-	 (*atforks[i].pre)(tid);
-}
-
-static void do_atfork_parent(ThreadId tid)
-{
-   Int i;
-
-   for(i = 0; i < n_atfork; i++)
-      if (atforks[i].parent != NULL)
-	 (*atforks[i].parent)(tid);
-}
-
-static void do_atfork_child(ThreadId tid)
-{
-   Int i;
-
-   for(i = 0; i < n_atfork; i++)
-      if (atforks[i].child != NULL)
-	 (*atforks[i].child)(tid);
-}
-
-/* return true if address range entirely contained within client
-   address space */
-static Bool valid_client_addr(Addr start, UInt size, ThreadId tid, const Char *syscall)
-{
-   Addr end = start+size;
-   Addr cl_base = VG_(client_base);
-   Bool ret;
-
-   if (size == 0)
-      return True;
-
-   if (cl_base < 0x10000)
-      cl_base = 0x10000;
-
-   ret =
-      (end >= start) && 
-      start >= cl_base && start < VG_(client_end) &&
-      (end <= VG_(client_end));
-
-   if (0)
-      VG_(printf)("%s: test=%p-%p client=%p-%p ret=%d\n",
-		  syscall, start, end, cl_base, VG_(client_end), ret);
-
-   if (!ret && syscall != NULL) {
-      VG_(message)(Vg_UserMsg, "Warning: client syscall %s tried to modify addresses %p-%p",
-		   syscall, start, end);
-
-      if (VG_(clo_verbosity) > 1) {
-	 ExeContext *ec = VG_(get_ExeContext)(tid);
-	 VG_(pp_ExeContext)(ec);
-      }
-   }
-
-   return ret;
-}
-
-/* Walk through a colon-separated environment variable, and remove the
-   entries which matches file_pattern.  It slides everything down over
-   the removed entries, and pads the remaining space with '\0'.  It
-   modifies the entries in place (in the client address space), but it
-   shouldn't matter too much, since we only do this just before an
-   execve().
-
-   This is also careful to mop up any excess ':'s, since empty strings
-   delimited by ':' are considered to be '.' in a path.
-*/
-void VG_(mash_colon_env)(Char *varp, const Char *remove_pattern)
-{
-   Char *const start = varp;
-   Char *entry_start = varp;
-   Char *output = varp;
-
-   if (varp == NULL)
-      return;
-
-   while(*varp) {
-      if (*varp == ':') {
-	 Char prev;
-	 Bool match;
-
-	 /* This is a bit subtle: we want to match against the entry
-	    we just copied, because it may have overlapped with
-	    itself, junking the original. */
-
-	 prev = *output;
-	 *output = '\0';
-
-	 match = VG_(string_match)(remove_pattern, entry_start);
-
-	 *output = prev;
-	 
-	 if (match) {
-	    output = entry_start;
-	    varp++;			/* skip ':' after removed entry */
-	 } else
-	    entry_start = output+1;	/* entry starts after ':' */
-      }
-
-      *output++ = *varp++;
-   }
-
-   /* match against the last entry */
-   if (VG_(string_match)(remove_pattern, entry_start)) {
-      output = entry_start;
-      if (output > start) {
-	 /* remove trailing ':' */
-	 output--;
-	 vg_assert(*output == ':');
-      }
-   }	 
-
-   /* pad out the left-overs with '\0' */
-   while(output < varp)
-      *output++ = '\0';
-}
-
-
-/* ---------------------------------------------------------------------
-   Doing mmap, munmap, mremap, mprotect
-   ------------------------------------------------------------------ */
-
-// Nb: this isn't done as precisely as possible, but it seems that programs
-// are usually sufficiently well-behaved that the more obscure corner cases
-// aren't important.  Various comments in the few functions below give more
-// details... njn 2002-Sep-17
-
-/* AFAICT from kernel sources (mm/mprotect.c) and general experimentation,
-   munmap, mprotect (and mremap??) work at the page level.  So addresses
-   and lengths must be adjusted for this. */
-
-/* Mash around start and length so that the area exactly covers
-   an integral number of pages.  If we don't do that, memcheck's
-   idea of addressible memory diverges from that of the
-   kernel's, which causes the leak detector to crash. */
-static 
-void mash_addr_and_len( Addr* a, UInt* len)
-{
-   Addr ra;
-   
-   ra = PGROUNDDN(*a);
-   *len = PGROUNDUP(*a + *len) - ra;
-   *a = ra;
-}
-
-static
-void mmap_segment ( Addr a, UInt len, UInt prot, UInt mm_flags, Int fd, ULong offset )
-{
-   Bool rr, ww, xx;
-   UInt flags;
-
-   flags = SF_MMAP;
-   
-   if (mm_flags & VKI_MAP_FIXED)
-      flags |= SF_FIXED;
-   if (!(mm_flags & VKI_MAP_PRIVATE))
-      flags |= SF_SHARED;
-
-   if (fd != -1)
-      flags |= SF_FILE;
-
-   VG_(map_fd_segment)(a, len, prot, flags, fd, offset, NULL);
-
-   rr = prot & VKI_PROT_READ;
-   ww = prot & VKI_PROT_WRITE;
-   xx = prot & VKI_PROT_EXEC;
-
-   VG_TRACK( new_mem_mmap, a, len, rr, ww, xx );
-}
-
-static
-void munmap_segment ( Addr a, UInt len )
-{
-   /* Addr orig_a   = a;
-      Addr orig_len = len; */
-
-   mash_addr_and_len(&a, &len);
-
-   VG_(unmap_range)(a, len);
-
-   /*
-   VG_(printf)("MUNMAP: correct (%p for %d) to (%p for %d) %s\n", 
-      orig_a, orig_len, a, len, (orig_a!=start || orig_len!=length) 
-                                    ? "CHANGE" : "");
-   */
-
-   VG_TRACK( die_mem_munmap, a, len );
-}
-
-static 
-void mprotect_segment ( Addr a, UInt len, Int prot )
-{
-   Bool rr, ww, xx;
-
-   VG_(mprotect_range)(a, len, prot);
-
-   rr = prot & VKI_PROT_READ;
-   ww = prot & VKI_PROT_WRITE;
-   xx = prot & VKI_PROT_EXEC;
-
-   // if removing exe permission, should check and remove from exe_seg list
-   // if adding, should check and add to exe_seg list
-   // easier to ignore both cases -- both v. unlikely?
-   mash_addr_and_len(&a, &len);
-   VG_TRACK( change_mem_mprotect, a, len, rr, ww, xx );
-}
-
-static 
-Addr mremap_segment ( Addr old_addr, UInt old_size,
-		      Addr new_addr, UInt new_size,
-		      UInt flags, ThreadId tid)
-{
-   Addr ret;
-   Segment *seg, *next;
-
-   old_size = PGROUNDUP(old_size);
-   new_size = PGROUNDUP(new_size);
-
-   if (PGROUNDDN(old_addr) != old_addr)
-      return -VKI_EINVAL;
-
-   if (!valid_client_addr(old_addr, old_size, tid, "mremap(old_addr)"))
-      return -VKI_EFAULT;
-
-   /* fixed at the current address means we don't move it */
-   if ((flags & VKI_MREMAP_FIXED) && (old_addr == new_addr))
-      flags &= ~(VKI_MREMAP_FIXED|VKI_MREMAP_MAYMOVE);
-
-   if (flags & VKI_MREMAP_FIXED) {
-      if (PGROUNDDN(new_addr) != new_addr)
-	 return -VKI_EINVAL;
-
-      if (!valid_client_addr(new_addr, new_size, tid, "mremap(new_addr)"))
-	 return -VKI_ENOMEM;
-
-      /* check for overlaps */
-      if ((old_addr < (new_addr+new_size) &&
-	   (old_addr+old_size) > new_addr) ||
-	  (new_addr < (old_addr+new_size) &&
-	   (new_addr+new_size) > old_addr))
-	 return -VKI_EINVAL;
-   }
-
-   /* Do nothing */
-   if (!(flags & VKI_MREMAP_FIXED) && new_size == old_size)
-      return old_addr;
-
-   seg = VG_(find_segment)(old_addr);
-
-   /* range must be contained within segment */
-   if (seg == NULL || !VG_(seg_contains)(seg, old_addr, old_size))
-      return -VKI_EINVAL;
-
-   next = VG_(next_segment)(seg);
-
-   if (0)
-      VG_(printf)("mremap: old_addr+new_size=%p next->addr=%p flags=%d\n",
-		  old_addr+new_size, next->addr, flags);
-   
-   if ((flags & VKI_MREMAP_FIXED) ||
-       (next != NULL && (old_addr+new_size) > next->addr)) {
-      /* we're moving the block */
-      Addr a;
-      
-      if ((flags & (VKI_MREMAP_FIXED|VKI_MREMAP_MAYMOVE)) == 0)
-	 return -VKI_ENOMEM;	/* not allowed to move */
-
-      if ((flags & VKI_MREMAP_FIXED) == 0)
-	  new_addr = 0;
-
-      a = VG_(find_map_space)(new_addr, new_size, True);
-
-      if ((flags & VKI_MREMAP_FIXED) && a != new_addr)
-	 return -VKI_ENOMEM;	/* didn't find the place we wanted */
-
-      new_addr = a;
-      ret = a;
-
-      /* we've nailed down the location */
-      flags |=  VKI_MREMAP_FIXED|VKI_MREMAP_MAYMOVE;
-
-      ret = VG_(do_syscall)(__NR_mremap, old_addr, old_size, new_size, 
-			    flags, new_addr);
-
-      if (ret != new_addr) {
-	 vg_assert(VG_(is_kerror)(ret));
-	 return ret;
-      }
-
-      VG_TRACK(copy_mem_remap, old_addr, new_addr, 
-	       (old_size < new_size) ? old_size : new_size);
-
-      if (new_size > old_size)
-	 VG_TRACK(new_mem_mmap, new_addr+old_size, new_size-old_size,
-		  seg->prot & VKI_PROT_READ, 
-		  seg->prot & VKI_PROT_WRITE, 
-		  seg->prot & VKI_PROT_EXEC);
-      VG_TRACK(die_mem_munmap, old_addr, old_size);
-
-      VG_(map_file_segment)(new_addr, new_size,
-			    seg->prot, 
-			    seg->flags,
-			    seg->dev, seg->ino,
-			    seg->offset, seg->filename);
-
-      VG_(munmap)((void *)old_addr, old_size);
-   } else {
-      /* staying in place */
-      ret = old_addr;
-
-      if (new_size < old_size) {
-	 VG_TRACK(die_mem_munmap, old_addr+new_size, old_size-new_size);
-	 VG_(munmap)((void *)(old_addr+new_size), old_size-new_size);
-      } else {
-	 /* we've nailed down the location */
-	 flags &= ~VKI_MREMAP_MAYMOVE;
-
-	 if (0)
-	    VG_(printf)("mremap: old_addr=%p old_size=%d new_size=%d flags=%d\n",
-			old_addr, old_size, new_size, flags);
-
-	 ret = VG_(do_syscall)(__NR_mremap, old_addr, old_size, new_size, 
-			       flags, 0);
-
-	 if (ret != old_addr)
-	    return ret;
-
-	 VG_TRACK(new_mem_mmap, old_addr+old_size, new_size-old_size,
-		  seg->prot & VKI_PROT_READ, 
-		  seg->prot & VKI_PROT_WRITE, 
-		  seg->prot & VKI_PROT_EXEC);
-
-	 VG_(map_file_segment)(old_addr+old_size, new_size-old_size,
-			       seg->prot, 
-			       seg->flags,
-			       seg->dev, seg->ino,
-			       seg->offset, seg->filename);	 
-      }
-   }
-
-   return ret;
-}
-
-
-/* Is this a Linux kernel error return value? */
-/* From:
-   http://sources.redhat.com/cgi-bin/cvsweb.cgi/libc/sysdeps/unix/sysv/
-   linux/i386/sysdep.h?
-   rev=1.28&content-type=text/x-cvsweb-markup&cvsroot=glibc
-
-   \begin{quote}:
-
-   Linux uses a negative return value to indicate syscall errors,
-   unlike most Unices, which use the condition codes' carry flag.
-
-   Since version 2.1 the return value of a system call might be
-   negative even if the call succeeded.  E.g., the `lseek' system call
-   might return a large offset.  Therefore we must not anymore test
-   for < 0, but test for a real error by making sure the value in %eax
-   is a real error number.  Linus said he will make sure the no syscall
-   returns a value in -1 .. -4095 as a valid result so we can safely
-   test with -4095.  
-
-   END QUOTE
-*/
-Bool VG_(is_kerror) ( Int res )
-{
-   if (res >= -4095 && res <= -1)
-      return True;
-   else
-      return False;
-}
-
-/* One of these is allocated for each open file descriptor.  */
-
-typedef struct OpenFd
-{
-   Int fd;                        /* The file descriptor */
-   Char *pathname;                /* NULL if not a regular file or unknown */
-   ExeContext *where;             /* NULL if inherited from parent */
-   struct OpenFd *next, *prev;
-} OpenFd;
-
-/* List of allocated file descriptors. */
-
-static OpenFd *allocated_fds;
-
-/* Count of open file descriptors. */
-
-static int fd_count = 0;
-
-/* Given a file descriptor, attempt to deduce it's filename.  To do this,
-   we use /proc/self/fd/<FD>.  If this doesn't point to a file, or if it
-   doesn't exist, we just return NULL.  Otherwise, we return a pointer
-   to the file name, which the caller is responsible for freeing. */
-
-Char *VG_(resolve_filename)(Int fd)
-{
-   char tmp[28], buf[PATH_MAX];
-
-   VG_(sprintf)(tmp, "/proc/self/fd/%d", fd);
-   VG_(memset)(buf, 0, PATH_MAX);
-
-   if(VG_(readlink)(tmp, buf, PATH_MAX) == -1)
-      return NULL;
-
-   return ((buf[0] == '/') ? VG_(arena_strdup)(VG_AR_CORE, buf) : NULL);
-}
-
-
-/* Note the fact that a file descriptor was just closed. */
-
-static
-void record_fd_close(Int tid, Int fd)
-{
-   OpenFd *i = allocated_fds;
-
-   if (fd > VG_(max_fd))
-      return;			/* Valgrind internal */
-
-   while(i) {
-      if(i->fd == fd) {
-         if(i->prev)
-            i->prev->next = i->next;
-         else
-            allocated_fds = i->next;
-         if(i->next)
-            i->next->prev = i->prev;
-         if(i->pathname) 
-            VG_(arena_free) (VG_AR_CORE, i->pathname);
-         VG_(arena_free) (VG_AR_CORE, i);
-         fd_count--;
-         break;
-      }
-      i = i->next;
-   }
-}
-
-/* Note the fact that a file descriptor was just opened.  If the
-   tid is -1, this indicates an inherited fd.  If the pathname is NULL,
-   this either indicates a non-standard file (i.e. a pipe or socket or
-   some such thing) or that we don't know the filename.  If the fd is
-   already open, then we're probably doing a dup2() to an existing fd,
-   so just overwrite the existing one. */
-
-static
-void record_fd_open(Int tid, Int fd, char *pathname)
-{
-   OpenFd *i;
-
-   if (fd > VG_(max_fd))
-      return;			/* Valgrind internal */
-
-   /* Check to see if this fd is already open. */
-   i = allocated_fds;
-   while (i) {
-      if (i->fd == fd) {
-         if (i->pathname) VG_(arena_free)(VG_AR_CORE, i->pathname);
-         break;
-      }
-      i = i->next;
-   }
-
-   /* Not already one: allocate an OpenFd */
-   if (i == NULL) {
-      i = VG_(arena_malloc)(VG_AR_CORE, sizeof(OpenFd));
-
-      i->prev = NULL;
-      i->next = allocated_fds;
-      if(allocated_fds) allocated_fds->prev = i;
-      allocated_fds = i;
-      fd_count++;
-   }
-
-   i->fd = fd;
-   i->pathname = pathname;
-   i->where = (tid == -1) ? NULL : VG_(get_ExeContext)(tid);
-}
-
-static
-Char *unix2name(struct sockaddr_un *sa, UInt len, Char *name)
-{
-   if(sa == NULL || len == 0 || sa->sun_path[0] == '\0') {
-      VG_(sprintf)(name, "<unknown>");
-   } else {
-      VG_(sprintf)(name, "%s", sa->sun_path);
-   }
-
-   return name;
-}
-
-static
-Char *inet2name(struct sockaddr_in *sa, UInt len, Char *name)
-{
-   if(sa == NULL || len == 0) {
-      VG_(sprintf)(name, "<unknown>");
-   } else {
-      UInt addr = sa->sin_addr.s_addr;
-
-      if (addr == 0) {
-         VG_(sprintf)(name, "<unbound>");
-      } else {
-         VG_(sprintf)(name, "%u.%u.%u.%u:%u",
-                      addr & 0xFF, (addr>>8) & 0xFF,
-                      (addr>>16) & 0xFF, (addr>>24) & 0xFF,
-                      ntohs(sa->sin_port));
-      }
-   }
-
-   return name;
-}
-
-
-/*
- * Try get some details about a socket.
- */
-
-static void
-getsockdetails(int fd)
-{
-   union u {
-      struct sockaddr a;
-      struct sockaddr_in in;
-      struct sockaddr_un un;
-   } laddr;
-   socklen_t llen;
-
-   llen = sizeof(laddr);
-   VG_(memset)(&laddr, 0, llen);
-
-   if(VG_(getsockname)(fd, (struct vki_sockaddr *)&(laddr.a), &llen) != -1) {
-      switch(laddr.a.sa_family) {
-      case AF_INET: {
-         static char lname[32];
-         static char pname[32];
-         struct sockaddr_in paddr;
-         socklen_t plen = sizeof(struct sockaddr_in);
-
-         if(VG_(getpeername)(fd, (struct vki_sockaddr *)&paddr, &plen) != -1) {
-            VG_(message)(Vg_UserMsg, "Open AF_INET socket %d: %s <-> %s", fd,
-                         inet2name(&(laddr.in), llen, lname),
-                         inet2name(&paddr, plen, pname));
-         } else {
-            VG_(message)(Vg_UserMsg, "Open AF_INET socket %d: %s <-> unbound",
-                         fd, inet2name(&(laddr.in), llen, lname));
-         }
-         return;
-         }
-      case AF_UNIX: {
-         static char lname[256];
-         VG_(message)(Vg_UserMsg, "Open AF_UNIX socket %d: %s", fd,
-                      unix2name(&(laddr.un), llen, lname));
-         return;
-         }
-      default:
-         VG_(message)(Vg_UserMsg, "Open pf-%d socket %d:",
-                      laddr.a.sa_family, fd);
-         return;
-      }
-   }
-
-   VG_(message)(Vg_UserMsg, "Open socket %d:", fd);
-}
-
-
-/* Dump out a summary, and optionally a more detailed list, of open file
-   descriptors. */
-
-void VG_(fd_stats) ()
-{
-   OpenFd *i = allocated_fds;
-
-   VG_(message)(Vg_UserMsg,
-                "FILE DESCRIPTORS: %d open at exit.", fd_count);
-
-   while(i) {
-      if(i->pathname) {
-         VG_(message)(Vg_UserMsg, "Open file descriptor %d: %s", i->fd,
-                      i->pathname);
-      } else {
-         int val;
-         socklen_t len = sizeof(val);
-
-         if(VG_(getsockopt)(i->fd, SOL_SOCKET, SO_TYPE, &val, &len) == -1) {
-            VG_(message)(Vg_UserMsg, "Open file descriptor %d:", i->fd);
-         } else {
-            getsockdetails(i->fd);
-         }
-      }
-
-      if(i->where) {
-         VG_(pp_ExeContext)(i->where);
-         VG_(message)(Vg_UserMsg, "");
-      } else {
-         VG_(message)(Vg_UserMsg, "   <inherited from parent>");
-         VG_(message)(Vg_UserMsg, "");
-      }
-
-      i = i->next;
-   }
-
-   VG_(message)(Vg_UserMsg, "");
-}
-
-/* If /proc/self/fd doesn't exist for some weird reason (like you've
-   got a kernel that doesn't have /proc support compiled in), then we
-   need to find out what file descriptors we inherited from our parent
-   process the hard way - by checking each fd in turn. */
-
-static
-void do_hacky_preopened()
-{
-   struct vki_rlimit lim;
-   unsigned int count;
-   int i;
-
-   if(VG_(getrlimit) (VKI_RLIMIT_NOFILE, &lim) == -1) {
-      /* Hmm.  getrlimit() failed.  Now we're screwed, so just choose
-         an arbitrarily high number.  1024 happens to be the limit in
-         the 2.4 kernels. */
-      count = 1024;
-   } else {
-      count = lim.rlim_cur;
-   }
-
-   for (i = 0; i < count; i++)
-      if(VG_(fcntl)(i, VKI_F_GETFL, 0) != -1)
-         record_fd_open(-1, i, NULL);
-}
-
-/* Initialize the list of open file descriptors with the file descriptors
-   we inherited from out parent process. */
-
-void VG_(init_preopened_fds)()
-{
-   int f, ret;
-   struct vki_dirent d;
-
-   f = VG_(open)("/proc/self/fd", VKI_O_RDONLY, 0);
-   if(f == -1) {
-      do_hacky_preopened();
-      return;
-   }
-
-   while((ret = VG_(getdents)(f, &d, sizeof(d))) != 0) {
-      if(ret == -1)
-         goto out;
-
-      if(VG_(strcmp)(d.d_name, ".") && VG_(strcmp)(d.d_name, "..")) {
-         int fno = VG_(atoll)(d.d_name);
-
-         if(fno != f)
-            if(VG_(clo_track_fds))
-               record_fd_open(-1, fno, VG_(resolve_filename)(fno));
-      }
-
-      VG_(lseek)(f, d.d_off, VKI_SEEK_SET);
-   }
-
-out:
-   VG_(close)(f);
-}
-
-static
-UInt get_shm_size ( Int shmid )
-{
-   struct shmid_ds buf;
-   long __res = VG_(do_syscall)(__NR_ipc, 24 /* IPCOP_shmctl */, shmid, IPC_STAT, 0, &buf);
-    if ( VG_(is_kerror) ( __res ) )
-       return 0;
- 
-   return buf.shm_segsz;
-}
- 
-static
-Char *strdupcat ( const Char *s1, const Char *s2, ArenaId aid )
-{
-   UInt len = VG_(strlen) ( s1 ) + VG_(strlen) ( s2 ) + 1;
-   Char *result = VG_(arena_malloc) ( aid, len );
-   VG_(strcpy) ( result, s1 );
-   VG_(strcat) ( result, s2 );
-   return result;
-}
-
-static 
-void pre_mem_read_sendmsg ( ThreadId tid,
-                            Char *msg, UInt base, UInt size )
-{
-   Char *outmsg = strdupcat ( "socketcall.sendmsg", msg, VG_AR_TRANSIENT );
-   SYSCALL_TRACK( pre_mem_read, tid, outmsg, base, size );
-
-   VG_(arena_free) ( VG_AR_TRANSIENT, outmsg );
-}
-
-static 
-void pre_mem_write_recvmsg ( ThreadId tid,
-                             Char *msg, UInt base, UInt size )
-{
-   Char *outmsg = strdupcat ( "socketcall.recvmsg", msg, VG_AR_TRANSIENT );
-   SYSCALL_TRACK( pre_mem_write, tid, outmsg, base, size );
-   VG_(arena_free) ( VG_AR_TRANSIENT, outmsg );
-}
-
-static
-void post_mem_write_recvmsg ( ThreadId tid,
-                              Char *fieldName, UInt base, UInt size )
-{
-   VG_TRACK( post_mem_write, base, size );
-}
- 
-static
-void msghdr_foreachfield ( 
-        ThreadId tid, 
-        struct msghdr *msg, 
-        void (*foreach_func)( ThreadId, Char *, UInt, UInt ) 
-     )
-{
-   if ( !msg )
-      return;
-
-   foreach_func ( tid, "(msg)", (Addr)msg, sizeof( struct msghdr ) );
-
-   if ( msg->msg_name )
-      foreach_func ( tid, 
-                     "(msg.msg_name)", 
-                     (Addr)msg->msg_name, msg->msg_namelen );
-
-   if ( msg->msg_iov ) {
-      struct iovec *iov = msg->msg_iov;
-      UInt i;
-
-      foreach_func ( tid, 
-                     "(msg.msg_iov)", 
-                     (Addr)iov, msg->msg_iovlen * sizeof( struct iovec ) );
-
-      for ( i = 0; i < msg->msg_iovlen; ++i, ++iov )
-         foreach_func ( tid, 
-                        "(msg.msg_iov[i]", 
-                        (Addr)iov->iov_base, iov->iov_len );
-   }
-
-   if ( msg->msg_control )
-      foreach_func ( tid, 
-                     "(msg.msg_control)", 
-                     (Addr)msg->msg_control, msg->msg_controllen );
-}
-
-void check_cmsg_for_fds(Int tid, struct msghdr *msg)
-{
-   struct cmsghdr *cm = CMSG_FIRSTHDR(msg);
-
-   while (cm) {
-      if (cm->cmsg_level == SOL_SOCKET &&
-          cm->cmsg_type == SCM_RIGHTS ) {
-         int *fds = (int *) CMSG_DATA(cm);
-         int fdc = (cm->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr)))
-                         / sizeof(int);
-         int i;
-
-         for (i = 0; i < fdc; i++)
-            if(VG_(clo_track_fds))
-               record_fd_open (tid, fds[i], VG_(resolve_filename)(fds[i]));
-      }
-
-      cm = CMSG_NXTHDR(msg, cm);
-   }
-}
-
-static
-void pre_mem_read_sockaddr ( ThreadId tid,
-			     Char *description,
-			     struct sockaddr *sa, UInt salen )
-{
-   Char *outmsg;
-
-   /* NULL/zero-length sockaddrs are legal */
-   if ( sa == NULL || salen == 0 ) return;
-
-   outmsg = VG_(arena_malloc) ( VG_AR_TRANSIENT,
-                                strlen( description ) + 30 );
-
-   VG_(sprintf) ( outmsg, description, ".sa_family" );
-   SYSCALL_TRACK( pre_mem_read, tid, outmsg, 
-                  (UInt) &sa->sa_family, sizeof (sa_family_t));
-
-   switch (sa->sa_family) {
-                  
-      case AF_UNIX:
-         VG_(sprintf) ( outmsg, description, ".sun_path" );
-         SYSCALL_TRACK( pre_mem_read_asciiz, tid, outmsg,
-            (UInt) ((struct sockaddr_un *) sa)->sun_path);
-         break;
-                     
-      case AF_INET:
-         VG_(sprintf) ( outmsg, description, ".sin_port" );
-         SYSCALL_TRACK( pre_mem_read, tid, outmsg,
-            (UInt) &((struct sockaddr_in *) sa)->sin_port,
-            sizeof (((struct sockaddr_in *) sa)->sin_port));
-         VG_(sprintf) ( outmsg, description, ".sin_addr" );
-         SYSCALL_TRACK( pre_mem_read, tid, outmsg,
-            (UInt) &((struct sockaddr_in *) sa)->sin_addr,
-            sizeof (struct in_addr));
-         break;
-                           
-      case AF_INET6:
-         VG_(sprintf) ( outmsg, description, ".sin6_port" );
-         SYSCALL_TRACK( pre_mem_read, tid, outmsg,
-            (UInt) &((struct sockaddr_in6 *) sa)->sin6_port,
-            sizeof (((struct sockaddr_in6 *) sa)->sin6_port));
-         VG_(sprintf) ( outmsg, description, ".sin6_flowinfo" );
-         SYSCALL_TRACK( pre_mem_read, tid, outmsg,
-            (UInt) &((struct sockaddr_in6 *) sa)->sin6_flowinfo,
-            sizeof (uint32_t));
-         VG_(sprintf) ( outmsg, description, ".sin6_addr" );
-         SYSCALL_TRACK( pre_mem_read, tid, outmsg,
-            (UInt) &((struct sockaddr_in6 *) sa)->sin6_addr,
-            sizeof (struct in6_addr));
-#        ifndef GLIBC_2_1
-         VG_(sprintf) ( outmsg, description, ".sin6_scope_id" );
-         SYSCALL_TRACK( pre_mem_read, tid, outmsg,
-            (UInt) &((struct sockaddr_in6 *) sa)->sin6_scope_id,
-			sizeof (uint32_t));
-#        endif
-         break;
-               
-      default:
-         VG_(sprintf) ( outmsg, description, "" );
-         SYSCALL_TRACK( pre_mem_read, tid, outmsg, (UInt) sa, salen );
-         break;
-   }
-   
-   VG_(arena_free) ( VG_AR_TRANSIENT, outmsg );
-}
-
-/* Dereference a pointer to a UInt. */
-static UInt deref_UInt ( ThreadId tid, Addr a, Char* s )
-{
-   UInt* a_p = (UInt*)a;
-   SYSCALL_TRACK( pre_mem_read, tid, s, (Addr)a_p, sizeof(UInt) );
-   if (a_p == NULL)
-      return 0;
-   else
-      return *a_p;
-}
-
-/* Dereference a pointer to a pointer. */
-static Addr deref_Addr ( ThreadId tid, Addr a, Char* s )
-{
-   Addr* a_p = (Addr*)a;
-   SYSCALL_TRACK( pre_mem_read, tid, s, (Addr)a_p, sizeof(Addr) );
-   return *a_p;
-}
-
-static 
-void buf_and_len_pre_check( ThreadId tid, Addr buf_p, Addr buflen_p,
-                            Char* buf_s, Char* buflen_s )
-{
-   if (VG_(defined_pre_mem_write)()) {
-      UInt buflen_in = deref_UInt( tid, buflen_p, buflen_s);
-      if (buflen_in > 0) {
-         TL_(pre_mem_write) ( Vg_CoreSysCall,
-			      tid, buf_s, buf_p, buflen_in );
-      }
-   }
-}
-
-static 
-void buf_and_len_post_check( ThreadId tid, Int res,
-                             Addr buf_p, Addr buflen_p, Char* s )
-{
-   if (!VG_(is_kerror)(res) && VG_(defined_post_mem_write)()) {
-      UInt buflen_out = deref_UInt( tid, buflen_p, s);
-      if (buflen_out > 0 && buf_p != (Addr)NULL) {
-         TL_(post_mem_write) ( buf_p, buflen_out );
-      }
-   }
-}
-
-/* ---------------------------------------------------------------------
-   Data seg end, for brk()
-   ------------------------------------------------------------------ */
-
-static Addr do_brk(Addr newbrk)
-{
-   Addr ret = VG_(brk_limit);
-   static const Bool debug = False;
-   Segment *seg;
-
-   if (debug)
-      VG_(printf)("do_brk: brk_base=%p brk_limit=%p newbrk=%p\n",
-		  VG_(brk_base), VG_(brk_limit), newbrk);
-
-   if (newbrk < VG_(brk_base) || newbrk >= VG_(client_end))
-      return VG_(brk_limit);
-
-   /* brk isn't allowed to grow over anything else */
-   seg = VG_(find_segment)(VG_(brk_limit));
-
-   vg_assert(seg != NULL);
-
-   if (0)
-      VG_(printf)("brk_limit=%p seg->addr=%p seg->end=%p\n", 
-		  VG_(brk_limit), seg->addr, seg->addr+seg->len);
-   vg_assert(VG_(brk_limit) >= seg->addr && VG_(brk_limit) <= (seg->addr + seg->len));
-
-   seg = VG_(next_segment)(seg);
-   if (seg != NULL && newbrk > seg->addr)
-      return VG_(brk_limit);
-
-   if (PGROUNDDN(newbrk) != PGROUNDDN(VG_(brk_limit))) {
-      Addr current = PGROUNDUP(VG_(brk_limit));
-      Addr newaddr = PGROUNDUP(newbrk);
-
-      /* new brk in a new page - fix the mappings */
-      if (newbrk > VG_(brk_limit)) {
-	 
-	 if (debug)
-	    VG_(printf)("  extending brk: current=%p newaddr=%p delta=%d\n",
-			current, newaddr, newaddr-current);
-
-	 if (newaddr == current) {
-	    ret = newbrk;
-	 } else if (VG_(mmap)((void *)current , newaddr-current,
-			      VKI_PROT_READ | VKI_PROT_WRITE | VKI_PROT_EXEC,
-			      VKI_MAP_PRIVATE | VKI_MAP_ANONYMOUS | VKI_MAP_FIXED | VKI_MAP_CLIENT,
-			      -1, 0) >= 0) {
-	    VG_(map_segment)(current, newaddr-current, VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC,
-			     SF_FIXED|SF_BRK);
-	    ret = newbrk;
-	 }
-      } else {
-	 vg_assert(newbrk < VG_(brk_limit));
-
-	 if (debug)
-	    VG_(printf)("  shrinking brk: current=%p newaddr=%p delta=%d\n",
-			current, newaddr, current-newaddr);
-
-	 if (newaddr != current) {
-	    VG_(munmap)((void *)newaddr, current - newaddr);
-	    VG_(unmap_range)(newaddr, current-newaddr);
-	 }
-	 ret = newbrk;
-      }
-   } else
-      ret = newbrk;
-
-   VG_(brk_limit) = ret;
-
-   return ret;
-}
-
-
-/* ---------------------------------------------------------------------
-   Vet file descriptors for sanity
-   ------------------------------------------------------------------ */
-
-/* Return true if we're allowed to use or create this fd */
-static Bool fd_allowed(Int fd, const Char *syscall, ThreadId tid)
-{
-   if (fd < 0 || fd > VG_(max_fd) || fd == VG_(clo_logfile_fd)) {
-      VG_(message)(Vg_UserMsg, 
-         "Warning: invalid file descriptor %d in syscall %s()",
-         fd, syscall);
-      if (fd == VG_(clo_logfile_fd))
-	 VG_(message)(Vg_UserMsg, 
-            "   Use --logfile-fd=<number> to select an alternative "
-	    "logfile fd.");
-      if (VG_(clo_verbosity) > 1) {
-	 ExeContext *ec = VG_(get_ExeContext)(tid);
-	 VG_(pp_ExeContext)(ec);
-      }
-      return False;
-   }
-   return True;
-}
-
-
-/* ---------------------------------------------------------------------
-   The Main Entertainment ...
-   ------------------------------------------------------------------ */
-
-
-#define PRE(x)	\
-	static void before_##x(ThreadId tid, ThreadState *tst)
-#define POST(x)	\
-	static void after_##x(ThreadId tid, ThreadState *tst)
-
-#define PREALIAS(new, old)	\
-	PRE(new) __attribute__((alias(STR(before_##old))))
-#define POSTALIAS(new, old)	\
-	POST(new) __attribute__((alias(STR(after_##old))))
-
-#define SYSNO	(tst->m_eax)		/* in PRE(x)  */
-#define res	(tst->m_eax)	/* in POST(x) */
-#define arg1	(tst->m_ebx)
-#define arg2	(tst->m_ecx)
-#define arg3	(tst->m_edx)
-#define arg4	(tst->m_esi)
-#define arg5	(tst->m_edi)
-#define arg6	(tst->m_ebp)
-
-PRE(exit_group)
-{
-   VG_(core_panic)("syscall exit_group() not caught by the scheduler?!");
-}
-
-PRE(exit)
-{
-   VG_(core_panic)("syscall exit() not caught by the scheduler?!");
-}
-
-PRE(ptrace)
-{
-   /* long ptrace (enum __ptrace_request request, pid_t pid, 
-      void *addr, void *data); ... sort of. */
-   /* Sigh ... the /usr/include/sys/user.h on R H 6.2 doesn't 
-      define struct user_fpxregs_struct.  On the basis that it 
-      is defined as follows on my R H 7.2 (glibc-2.2.4) box, 
-      I kludge it.
-
-      struct user_fpxregs_struct
-      {
-      unsigned short int cwd;
-      unsigned short int swd;
-      unsigned short int twd;
-      unsigned short int fop;
-      long int fip;
-      long int fcs;
-      long int foo;
-      long int fos;
-      long int mxcsr;
-      long int reserved;
-      long int st_space[32];  8*16 bytes for each FP-reg = 128 bytes
-      long int xmm_space[32]; 8*16 bytes for each XMM-reg = 128 bytes
-      long int padding[56];
-      };
-   */
-   const Int sizeof_struct_user_fpxregs_struct
-      = sizeof(unsigned short) * (1 + 1 + 1 + 1) 
-      + sizeof(long int) * (1 + 1 + 1 + 1 + 1 + 1 + 32 + 32 + 56);
-
-   MAYBE_PRINTF("ptrace ( %d, %d, %p, %p )\n", arg1,arg2,arg3,arg4);
-   switch (arg1) {
-   case 12:   /* PTRACE_GETREGS */
-      SYSCALL_TRACK( pre_mem_write, tid, "ptrace(getregs)", arg4, 
-		     sizeof (struct user_regs_struct));
-      break;
-   case 14:   /* PTRACE_GETFPREGS */
-      SYSCALL_TRACK( pre_mem_write, tid, "ptrace(getfpregs)", arg4, 
-		     sizeof (struct user_fpregs_struct));
-      break;
-   case 18:   /* PTRACE_GETFPXREGS */
-      SYSCALL_TRACK( pre_mem_write, tid, "ptrace(getfpxregs)", arg4, 
-		     sizeof_struct_user_fpxregs_struct);
-      break;
-   case 1: case 2: case 3:    /* PTRACE_PEEK{TEXT,DATA,USER} */
-      SYSCALL_TRACK( pre_mem_write, tid, "ptrace(peek)", arg4, 
-		     sizeof (long));
-      break;
-   case 13:   /* PTRACE_SETREGS */
-      SYSCALL_TRACK( pre_mem_read, tid, "ptrace(setregs)", arg4, 
-		     sizeof (struct user_regs_struct));
-      break;
-   case 15:   /* PTRACE_SETFPREGS */
-      SYSCALL_TRACK( pre_mem_read, tid, "ptrace(setfpregs)", arg4, 
-		     sizeof (struct user_fpregs_struct));
-      break;
-   case 19:   /* PTRACE_SETFPXREGS */
-      SYSCALL_TRACK( pre_mem_read, tid, "ptrace(setfpxregs)", arg4, 
-		     sizeof_struct_user_fpxregs_struct);
-      break;
-   default:
-      break;
-   }
-}
-
-POST(ptrace)
-{
-   const Int sizeof_struct_user_fpxregs_struct
-      = sizeof(unsigned short) * (1 + 1 + 1 + 1) 
-      + sizeof(long int) * (1 + 1 + 1 + 1 + 1 + 1 + 32 + 32 + 56);
-
-   switch (arg1) {
-   case 12:  /* PTRACE_GETREGS */
-      VG_TRACK( post_mem_write, arg4, 
-		sizeof (struct user_regs_struct));
-      break;
-   case 14:  /* PTRACE_GETFPREGS */
-      VG_TRACK( post_mem_write, arg4, 
-		sizeof (struct user_fpregs_struct));
-      break;
-   case 18:  /* PTRACE_GETFPXREGS */
-      VG_TRACK( post_mem_write, arg4, 
-		sizeof_struct_user_fpxregs_struct);
-      break;
-   case 1: case 2: case 3:    /* PTRACE_PEEK{TEXT,DATA,USER} */
-      VG_TRACK( post_mem_write, arg4, sizeof (long));
-      break;
-   default:
-      break;
-   }
-}
-
-PRE(mount)
-{
-   MAYBE_PRINTF( "mount( %p, %p, %p )\n" ,arg1,arg2,arg3);
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid,"mount(specialfile)",arg1);
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid,"mount(dir)",arg2);
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid,"mount(filesystemtype)",arg3);
-}
-
-PRE(umount)
-{
-   /* int umount(const char *path) */
-   MAYBE_PRINTF("umount( %p )\n", arg1);
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid,"umount(path)",arg1);
-}
-
-PRE(modify_ldt)
-{
-   MAYBE_PRINTF("modify_ldt ( %d, %p, %d )\n", arg1,arg2,arg3);
-   if (arg1 == 0) {
-      /* read the LDT into ptr */
-      SYSCALL_TRACK( pre_mem_write, tid, 
-		     "modify_ldt(ptr)(func=0)", arg2, arg3 );
-   }
-   if (arg1 == 1 || arg1 == 0x11) {
-      /* write the LDT with the entry pointed at by ptr */
-      SYSCALL_TRACK( pre_mem_read, tid, 
-		     "modify_ldt(ptr)(func=1 or 0x11)", arg2, 
-		     sizeof(struct vki_modify_ldt_ldt_s) );
-   }
-   /* "do" the syscall ourselves; the kernel never sees it */
-   res = VG_(sys_modify_ldt)( tid, arg1, (void*)arg2, arg3 );
-
-   if (arg1 == 0 && !VG_(is_kerror)(res) && res > 0) {
-      VG_TRACK( post_mem_write, arg2, res );
-   }
-}
-
-PRE(set_thread_area)
-{
-   MAYBE_PRINTF("set_thread_area ( %p )\n", arg1);
-
-   SYSCALL_TRACK( pre_mem_read, tid, 
-		  "set_thread_area(ptr)", arg1, 
-		  sizeof(struct vki_modify_ldt_ldt_s) );
-
-   /* "do" the syscall ourselves; the kernel never sees it */
-   res = VG_(sys_set_thread_area)( tid, (void *)arg1 );
-}
-
-PRE(get_thread_area)
-{
-   MAYBE_PRINTF("get_thread_area ( %p )\n", arg1);
-   SYSCALL_TRACK( pre_mem_write, tid, 
-		  "get_thread_area(ptr)", arg1, 
-		  sizeof(struct vki_modify_ldt_ldt_s) );
-
-   /* "do" the syscall ourselves; the kernel never sees it */
-   res = VG_(sys_get_thread_area)( tid, (void *)arg1 );
-
-   if (!VG_(is_kerror)(res)) {
-      VG_TRACK( post_mem_write, arg1, sizeof(struct vki_modify_ldt_ldt_s) );
-   }
-}
-
-PRE(setresgid)
-{
-   /* int setresgid(gid_t rgid, gid_t egid, gid_t sgid); */
-   MAYBE_PRINTF("setresgid ( %d, %d, %d )\n", arg1, arg2, arg3);
-}
-
-PRE(vhangup)
-{
-   MAYBE_PRINTF("vhangup()\n");
-}
-
-PRE(iopl)
-{
-   MAYBE_PRINTF("iopl ( %d )\n", arg1);
-}
-
-PRE(setxattr)
-{
-   MAYBE_PRINTF("setxattr ( %p, %p, %p, %d, %d )\n",
-		arg1, arg2, arg3, arg4, arg5);
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "setxattr(path)", arg1 );
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "setxattr(name)", arg2 );
-   SYSCALL_TRACK( pre_mem_read, tid, "setxattr(value)", arg3, arg4 );
-}
-
-PREALIAS(lsetxattr, setxattr);
-
-PRE(fsetxattr)
-{
-   /* int fsetxattr (int filedes, const char *name,
-      const void *value, size_t size, int flags); */
-   MAYBE_PRINTF("fsetxattr ( %d, %p, %p, %d, %d )\n",
-		arg1, arg2, arg3, arg4, arg5);
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "fsetxattr(name)", arg2 );
-   SYSCALL_TRACK( pre_mem_read, tid, "fsetxattr(value)", arg3, arg4 );
-}
-
-PRE(getxattr)
-{
-   MAYBE_PRINTF("getxattr ( %p, %p, %p, %d )\n", 
-		arg1,arg2,arg3, arg4);
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "getxattr(path)", arg1 );
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "getxattr(name)", arg2 );
-   SYSCALL_TRACK( pre_mem_write, tid, "getxattr(value)", arg3, arg4 );
-}
-
-POST(getxattr)
-{
-   if (res > 0 && arg3 != (Addr)NULL) {
-      VG_TRACK( post_mem_write, arg3, res );
-   }
-}
-
-PREALIAS(lgetxattr, getxattr);
-POSTALIAS(lgetxattr, getxattr);
-
-PRE(fgetxattr)
-{
-   MAYBE_PRINTF("fgetxattr ( %d, %p, %p, %d )\n",
-		arg1, arg2, arg3, arg4);
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "fgetxattr(name)", arg2 );
-   SYSCALL_TRACK( pre_mem_write, tid, "fgetxattr(value)", arg3, arg4 );
-}
-
-POST(fgetxattr)
-{
-   if (res > 0 && arg3 != (Addr)NULL)
-      VG_TRACK( post_mem_write, arg3, res );
-}
-
-PRE(listxattr)
-{
-   MAYBE_PRINTF("listxattr ( %p, %p, %d )\n", arg1, arg2, arg3);
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "listxattr(path)", arg1 );
-   SYSCALL_TRACK( pre_mem_write, tid, "listxattr(list)", arg2, arg3 );
-}
-
-POST(listxattr)
-{
-   if (res > 0 && arg2 != (Addr)NULL)
-      VG_TRACK( post_mem_write, arg2, res );
-}
-
-PREALIAS(llistxattr, listxattr);
-POSTALIAS(llistxattr, listxattr);
-
-PRE(flistxattr)
-{
-   /* ssize_t flistxattr (int filedes, char *list, size_t size); */
-   MAYBE_PRINTF("flistxattr ( %d, %p, %d )\n", arg1, arg2, arg3);
-   SYSCALL_TRACK( pre_mem_write, tid, "listxattr(list)", arg2, arg3 );
-}
-
-POST(flistxattr)
-{
-   if (res > 0 && arg2 != (Addr)NULL)
-      VG_TRACK( post_mem_write, arg2, res );
-}
-
-PRE(removexattr)
-{
-   MAYBE_PRINTF("removexattr ( %p, %p )\n", arg1, arg2);
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "listxattr(path)", arg1 );
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "listxattr(name)", arg2 );
-}
-
-PREALIAS(lremovexattr, removexattr);
-
-PRE(fremovexattr)
-{
-   MAYBE_PRINTF("removexattr ( %d, %p )\n", arg1, arg2);
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "listxattr(name)", arg2 );
-}
-
-PRE(quotactl)
-{
-   MAYBE_PRINTF("quotactl (0x%x, %p, 0x%x, 0x%x )\n", 
-		arg1,arg2,arg3, arg4);
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "quotactl(special)", arg2 );
-}
-
-PRE(lookup_dcookie)
-{
-   MAYBE_PRINTF("lookup_dcookie (0x%llx, %p, %d)\n",
-		arg1 | ((long long) arg2 << 32), arg3, arg4);
-   SYSCALL_TRACK( pre_mem_write, tid, "lookup_dcookie(buf)", arg3, arg4);
-}
-
-POST(lookup_dcookie)
-{
-   if (arg3 != (Addr)NULL)
-      VG_TRACK( post_mem_write, arg3, res);
-}
-
-PRE(truncate64)
-{
-   MAYBE_PRINTF("truncate64 ( %p, %lld )\n",
-		arg1, ((ULong)arg2) | (((ULong) arg3) << 32));
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "truncate64(path)", arg1 );
-}
-
-PRE(fdatasync)
-{
-   /* int fdatasync(int fd); */
-   MAYBE_PRINTF("fdatasync ( %d )\n", arg1);
-}
-
-PRE(msync)
-{
-   /* int msync(const void *start, size_t length, int flags); */
-   MAYBE_PRINTF("msync ( %p, %d, %d )\n", arg1,arg2,arg3);
-   SYSCALL_TRACK( pre_mem_read, tid, "msync(start)", arg1, arg2 );
-}
-
-struct getpmsg_strbuf {
-   int     maxlen;         /* no. of bytes in buffer */
-   int     len;            /* no. of bytes returned */
-   caddr_t buf;            /* pointer to data */
-};
-
-PRE(getpmsg)
-{
-   /* LiS getpmsg from http://www.gcom.com/home/linux/lis/ */
-   /* int getpmsg(int fd, struct strbuf *ctrl, struct strbuf *data, 
-      int *bandp, int *flagsp); */
-   struct getpmsg_strbuf *ctrl;
-   struct getpmsg_strbuf *data;
-   MAYBE_PRINTF("getpmsg ( %d, %p, %p, %p, %p )\n",
-		arg1,arg2,arg3,arg4,arg5);
-   ctrl = (struct getpmsg_strbuf *)arg2;
-   data = (struct getpmsg_strbuf *)arg3;
-   if (ctrl && ctrl->maxlen > 0)
-      SYSCALL_TRACK( pre_mem_write,tid, "getpmsg(ctrl)", 
-		     (UInt)ctrl->buf, ctrl->maxlen);
-   if (data && data->maxlen > 0)
-      SYSCALL_TRACK( pre_mem_write,tid, "getpmsg(data)", 
-		     (UInt)data->buf, data->maxlen);
-   if (arg4)
-      SYSCALL_TRACK( pre_mem_write,tid, "getpmsg(bandp)", 
-		     (UInt)arg4, sizeof(int));
-   if (arg5)
-      SYSCALL_TRACK( pre_mem_write,tid, "getpmsg(flagsp)", 
-		     (UInt)arg5, sizeof(int));
-}
-
-POST(getpmsg)
-{
-   struct getpmsg_strbuf *ctrl;
-   struct getpmsg_strbuf *data;
-
-   ctrl = (struct getpmsg_strbuf *)arg2;
-   data = (struct getpmsg_strbuf *)arg3;
-   if (res == 0 && ctrl && ctrl->len > 0) {
-      VG_TRACK( post_mem_write, (UInt)ctrl->buf, ctrl->len);
-   }
-   if (res == 0 && data && data->len > 0) {
-      VG_TRACK( post_mem_write, (UInt)data->buf, data->len);
-   }
-}
-
-PRE(putpmsg)
-{
-   /* LiS putpmsg from http://www.gcom.com/home/linux/lis/ */
-   /* int putpmsg(int fd, struct strbuf *ctrl, struct strbuf *data, 
-      int band, int flags); */
-   struct strbuf {
-      int     maxlen;         /* no. of bytes in buffer */
-      int     len;            /* no. of bytes returned */
-      caddr_t buf;            /* pointer to data */
-   };
-   struct strbuf *ctrl;
-   struct strbuf *data;
-   MAYBE_PRINTF("putpmsg ( %d, %p, %p, %d, %d )\n",
-		arg1,arg2,arg3,arg4,arg5);
-   ctrl = (struct strbuf *)arg2;
-   data = (struct strbuf *)arg3;
-   if (ctrl && ctrl->len > 0)
-      SYSCALL_TRACK( pre_mem_read,tid, "putpmsg(ctrl)",
-		     (UInt)ctrl->buf, ctrl->len);
-   if (data && data->len > 0)
-      SYSCALL_TRACK( pre_mem_read,tid, "putpmsg(data)",
-		     (UInt)data->buf, data->len);
-}
-
-PRE(getitimer)
-{
-   /* int getitimer(int which, struct itimerval *value); */
-   MAYBE_PRINTF("getitimer ( %d, %p )\n", arg1, arg2);
-   SYSCALL_TRACK( pre_mem_write, tid, "getitimer(timer)", arg2, 
-		  sizeof(struct itimerval) );
-}
-
-POST(getitimer)
-{
-   if (arg2 != (Addr)NULL) {
-      VG_TRACK( post_mem_write,arg2, sizeof(struct itimerval));
-   }
-}
-
-PRE(syslog)
-{
-   /* int syslog(int type, char *bufp, int len); */
-   MAYBE_PRINTF("syslog (%d, %p, %d)\n",arg1,arg2,arg3);
-   switch(arg1) {
-   case 2: case 3: case 4:
-      SYSCALL_TRACK( pre_mem_write, tid, "syslog(buf)", arg2, arg3);
-      break;
-   default: 
-      break;
-   }
-}
-
-POST(syslog)
-{
-   switch (arg1) {
-   case 2: case 3: case 4:
-      VG_TRACK( post_mem_write, arg2, arg3 );
-      break;
-   default:
-      break;
-   }
-}
-
-PRE(personality)
-{
-   /* int personality(unsigned long persona); */
-   MAYBE_PRINTF("personality ( %d )\n", arg1);
-}
-
-PRE(chroot)
-{
-   /* int chroot(const char *path); */
-   MAYBE_PRINTF("chroot ( %p )\n", arg1);
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "chroot(path)", arg1 );
-}
-
-PRE(madvise)
-{
-   /* int madvise(void *start, size_t length, int advice ); */
-   MAYBE_PRINTF("madvise ( %p, %d, %d )\n", arg1,arg2,arg3);
-}
-
-PRE(mremap)
-{
-   /* void* mremap(void * old_address, size_t old_size, 
-      size_t new_size, unsigned long flags, void * new_address); */
-   MAYBE_PRINTF("mremap ( %p, %d, %d, 0x%x, %p )\n", 
-		arg1, arg2, arg3, arg4, arg5);
-   
-   res = mremap_segment((Addr)arg1, arg2, (Addr)arg5, arg3, arg4, tid);
-}
-
-PRE(nice)
-{
-   /* int nice(int inc); */
-   MAYBE_PRINTF("nice ( %d )\n", arg1);
-}
-
-PRE(setresgid32)
-{
-   /* int setresgid(gid_t rgid, gid_t egid, gid_t sgid); */
-   MAYBE_PRINTF("setresgid32 ( %d, %d, %d )\n", arg1, arg2, arg3);
-}
-
-PRE(setfsuid32)
-{
-   /* int setfsuid(uid_t fsuid); */
-   MAYBE_PRINTF("setfsuid ( %d )\n", arg1);
-}
-
-PRE(_sysctl)
-{
-   /* int _sysctl(struct __sysctl_args *args); */
-   MAYBE_PRINTF("_sysctl ( %p )\n", arg1 );
-   SYSCALL_TRACK( pre_mem_write, tid, "_sysctl(args)", arg1, 
-		  sizeof(struct __sysctl_args) );
-}
-
-POST(_sysctl)
-{
-   VG_TRACK( post_mem_write, arg1, sizeof(struct __sysctl_args) );
-
-}
-
-PRE(sched_getscheduler)
-{
-   /* int sched_getscheduler(pid_t pid); */
-   MAYBE_PRINTF("sched_getscheduler ( %d )\n", arg1);
-}
-
-PRE(sched_setscheduler)
-{
-   /* int sched_setscheduler(pid_t pid, int policy, 
-      const struct sched_param *p); */
-   MAYBE_PRINTF("sched_setscheduler ( %d, %d, %p )\n",arg1,arg2,arg3);
-   if (arg3 != (UInt)NULL)
-      SYSCALL_TRACK( pre_mem_read, tid,
-		     "sched_setscheduler(struct sched_param *p)", 
-		     arg3, sizeof(struct sched_param));
-}
-
-PRE(mlock)
-{
-   /* int mlock(const void * addr, size_t len) */
-   MAYBE_PRINTF("mlock ( %p, %d )\n", arg1, arg2);
-}
-
-PRE(munlock)
-{
-   /* int munlock(const void * addr, size_t len) */
-   MAYBE_PRINTF("munlock ( %p, %d )\n", arg1, arg2);
-}
-
-PRE(mlockall)
-{
-   /* int mlockall(int flags); */
-   MAYBE_PRINTF("mlockall ( %x )\n", arg1);
-}
-
-PRE(munlockall)
-{
-   /* int munlock(const void * addr, size_t len) */
-   MAYBE_PRINTF("munlock ( %p, %d )\n", arg1, arg2);
-}
-
-PRE(sched_get_priority_max)
-{
-   /* int sched_get_priority_max(int policy); */
-   MAYBE_PRINTF("sched_get_priority_max ( %d )\n", arg1);
-}
-
-PRE(sched_get_priority_min)
-{
-   /* int sched_get_priority_min(int policy); */
-   MAYBE_PRINTF("sched_get_priority_min ( %d )\n", arg1);
-}
-
-PRE(setpriority)
-{
-   /* int setpriority(int which, int who, int prio); */
-   MAYBE_PRINTF("setpriority ( %d, %d, %d )\n", arg1, arg2, arg3);
-}
-
-PRE(getpriority)
-{
-   /* int getpriority(int which, int who); */
-   MAYBE_PRINTF("getpriority ( %d, %d )\n", arg1, arg2);
-}
-
-PRE(setfsgid)
-{
-   /* int setfsgid(gid_t gid); */
-   MAYBE_PRINTF("setfsgid ( %d )\n", arg1);
-}
-
-PRE(setregid)
-{
-   /* int setregid(gid_t rgid, gid_t egid); */
-   MAYBE_PRINTF("setregid ( %d, %d )\n", arg1, arg2);
-}
-
-PRE(setresuid)
-{
-   /* int setresuid(uid_t ruid, uid_t euid, uid_t suid); */
-   MAYBE_PRINTF("setresuid ( %d, %d, %d )\n", arg1, arg2, arg3);
-}
-
-PRE(setfsuid)
-{
-   /* int setfsuid(uid_t uid); */
-   MAYBE_PRINTF("setfsuid ( %d )\n", arg1);
-}
-
-PRE(sendfile)
-{
-   /* ssize_t sendfile(int out_fd, int in_fd, off_t *offset, 
-      size_t count) */
-   MAYBE_PRINTF("sendfile ( %d, %d, %p, %d )\n",arg1,arg2,arg3,arg4);
-   if (arg3 != (UInt)NULL)
-      SYSCALL_TRACK( pre_mem_write, tid, "sendfile(offset)",
-		     arg3, sizeof(off_t) );
-}
-
-POST(sendfile)
-{
-   VG_TRACK( post_mem_write, arg3, sizeof( off_t ) );
-}
-
-PRE(sendfile64)
-{
-   /* ssize_t sendfile64(int out_df, int in_fd, loff_t *offset,
-      size_t count); */
-   MAYBE_PRINTF("sendfile64 ( %d, %d, %p, %d )\n",arg1,arg2,arg3,arg4);
-   if (arg3 != (UInt)NULL)
-      SYSCALL_TRACK( pre_mem_write, tid, "sendfile64(offset)",
-		     arg3, sizeof(loff_t) );
-}
-
-POST(sendfile64)
-{
-   if (arg3 != (UInt)NULL ) {
-      VG_TRACK( post_mem_write, arg3, sizeof(loff_t) );
-   }
-}
-
-PRE(pwrite64)
-{
-   /* ssize_t pwrite (int fd, const void *buf, size_t nbytes,
-      off_t offset); */
-   MAYBE_PRINTF("pwrite64 ( %d, %p, %d, %d )\n", arg1, arg2, arg3, arg4);
-   SYSCALL_TRACK( pre_mem_read, tid, "pwrite(buf)", arg2, arg3 );
-}
-
-PRE(sync)
-{
-   /* int sync(); */
-   MAYBE_PRINTF("sync ( )\n");
-}
-
-PRE(fstatfs)
-{
-   /* int fstatfs(int fd, struct statfs *buf); */
-   MAYBE_PRINTF("fstatfs ( %d, %p )\n",arg1,arg2);
-   SYSCALL_TRACK( pre_mem_write, tid, "stat(buf)", 
-		  arg2, sizeof(struct statfs) );
-}
-
-POST(fstatfs)
-{
-   VG_TRACK( post_mem_write, arg2, sizeof(struct statfs) );
-}
-
-PRE(getsid)
-{
-   /* pid_t getsid(pid_t pid); */
-   MAYBE_PRINTF("getsid ( %d )\n", arg1);
-}
-
-PRE(pread64)
-{
-   /* ssize_t pread64(int fd, void *buf, size_t count, off_t offset); */
-   MAYBE_PRINTF("pread ( %d, %p, %d, %d ) ...\n",arg1,arg2,arg3,arg4);
-   SYSCALL_TRACK( pre_mem_write, tid, "pread(buf)", arg2, arg3 );
-}
-
-POST(pread64)
-{
-   MAYBE_PRINTF("SYSCALL[%d]       pread ( %d, %p, %d, %d ) --> %d\n",
-		VG_(getpid)(),
-		arg1, arg2, arg3, arg4, res);
-   if (res > 0) {
-      VG_TRACK( post_mem_write, arg2, res );
-   }
-}
-
-PRE(mknod)
-{
-   /* int mknod(const char *pathname, mode_t mode, dev_t dev); */
-   MAYBE_PRINTF("mknod ( %p, 0x%x, 0x%x )\n", arg1, arg2, arg3 );
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "mknod(pathname)", arg1 );
-}
-
-PRE(flock)
-{
-   /* int flock(int fd, int operation); */
-   MAYBE_PRINTF("flock ( %d, %d )\n", arg1, arg2 );
-}
-
-PRE(init_module)
-{
-   /* int init_module(const char *name, struct module *image); */
-   MAYBE_PRINTF("init_module ( %p, %p )\n", arg1, arg2 );
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "init_module(name)", arg1 );
-   SYSCALL_TRACK( pre_mem_read, tid, "init_module(image)", arg2, 
-		  VKI_SIZEOF_STRUCT_MODULE );
-}
-
-PRE(ioperm)
-{
-   /* int ioperm(unsigned long from, unsigned long num, int turn_on); */
-   MAYBE_PRINTF("ioperm ( %d, %d, %d )\n", arg1, arg2, arg3 );
-}
-
-PRE(capget)
-{
-   /* int capget(cap_user_header_t header, cap_user_data_t data); */
-   MAYBE_PRINTF("capget ( %p, %p )\n", arg1, arg2 );
-   SYSCALL_TRACK( pre_mem_read, tid, "capget(header)", arg1, 
-		  sizeof(vki_cap_user_header_t) );
-   SYSCALL_TRACK( pre_mem_write, tid, "capget(data)", arg2, 
-		  sizeof( vki_cap_user_data_t) );
-}
-
-POST(capget)
-{
-   if (arg2 != (Addr)NULL)
-      VG_TRACK( post_mem_write, arg2, sizeof( vki_cap_user_data_t) );
-}
-
-PRE(capset)
-{
-   SYSCALL_TRACK( pre_mem_read, tid, "capset(header)", 
-		  arg1, sizeof(vki_cap_user_header_t) );
-   SYSCALL_TRACK( pre_mem_read, tid, "capset(data)", 
-		  arg2, sizeof( vki_cap_user_data_t) );
-}
-
-PRE(execve)
-{
-   /* int execve (const char *filename, 
-      char *const argv [], 
-      char *const envp[]); */
-   MAYBE_PRINTF("execve ( %p(%s), %p, %p ) --- NOT CHECKED\n", 
-		arg1, arg1, arg2, arg3);
-
-   /* Erk.  If the exec fails, then the following will have made a
-      mess of things which makes it hard for us to continue.  The
-      right thing to do is piece everything together again in
-      POST(execve), but that's hard work.  Instead, we make an effort
-      to check that the execve will work before actually calling
-      exec. */
-   {
-      struct vki_stat st;
-      Int ret = VG_(stat)((Char *)arg1, &st);
-
-      if (ret < 0) {
-	 res = ret;
-	 return;
-      }
-      /* just look for any X bit set
-	 XXX do proper permissions check?
-       */
-      if ((st.st_mode & 0111) == 0) {
-	 res = -VKI_EACCES;
-	 return;
-      }
-   }
-
-   /* Resistance is futile.  Nuke all other threads.  POSIX mandates
-      this. (Really, nuke them all, since the new process will make
-      its own new thread.) */
-   VG_(nuke_all_threads_except)( VG_INVALID_THREADID );
-
-   {
-      /* Make the LD_LIBRARY_PATH/LD_PRELOAD disappear so that the
-	 child doesn't get our libpthread and other stuff.  This is
-	 done unconditionally, since if we are tracing the child,
-	 stage1/2 will set up the appropriate client environment. */
-      Int i;
-      Char** envp = (Char**)arg3;
-      Char*  ld_preload_str = NULL;
-      Char*  ld_library_path_str = NULL;
-
-      if (envp != NULL) {
-	 Char *buf;
-
-	 for (i = 0; envp[i] != NULL; i++) {
-	    if (VG_(strncmp)(envp[i], "LD_PRELOAD=", 11) == 0)
-	       ld_preload_str = &envp[i][11];
-	    if (VG_(strncmp)(envp[i], "LD_LIBRARY_PATH=", 16) == 0)
-	       ld_library_path_str = &envp[i][16];
-	 }
-
-	 buf = VG_(arena_malloc)(VG_AR_CORE, VG_(strlen)(VG_(libdir)) + 20);
-
-         VG_(sprintf)(buf, "%s*/vg_inject.so", VG_(libdir));
-         VG_(mash_colon_env)(ld_preload_str, buf);
-
-         VG_(sprintf)(buf, "%s*/vgpreload_*.so", VG_(libdir));
-         VG_(mash_colon_env)(ld_preload_str, buf);
-
-         VG_(sprintf)(buf, "%s*", VG_(libdir));
-         VG_(mash_colon_env)(ld_library_path_str, buf);
-
-         VG_(env_unsetenv)(envp, VALGRINDCLO);
-
-	 /* XXX if variable becomes empty, remove it completely? */
-      }
-   }
-
-   if (VG_(clo_trace_children)) {
-      /* If we're tracing the children, then we need to start it
-	 with our starter+arguments.
-      */
-      Int i;
-      Char *exec = (Char *)arg1;
-      Char **env = (Char **)arg3;
-      Char *cp;
-      Char *exename;
-      Bool sawexec = False;
-      Char *optvar;
-      Int  optlen;
-
-      optlen = 1;
-      for(i = 0; i < VG_(vg_argc); i++)
-	 optlen += VG_(strlen)(VG_(vg_argv)[i]) + 1;
-
-      /* All these are leaked - we're either going to exec, or panic
-	 when we fail. */
-      exename  = VG_(arena_malloc)(VG_AR_CORE, 64);
-      exec = VG_(arena_malloc)(VG_AR_CORE, VG_(strlen)(exec) + 7 /* --exec= */ + 1 /* \0 */);
-
-      VG_(sprintf)(exec, "--exec=%s", (Char *)arg1);
-      VG_(sprintf)(exename, "/proc/self/fd/%d", VG_(vgexecfd));
-
-      optlen += VG_(strlen)(exec)+1;
-
-      optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
-
-      /* valgrind arguments */
-      cp = optvar;
-      
-      for(i = 1; i < VG_(vg_argc); i++) {
-	 Char *arg = VG_(vg_argv)[i];
-	 Int len;
-	 
-	 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
-	    /* replace existing --exec= arg */
-	    sawexec = True;
-	    arg = exec;
-	 } else if (VG_(strcmp)(VG_(vg_argv)[i], "--") == 0)
-	    break;
-
-	 len = VG_(strlen)(arg);
-	 VG_(memcpy)(cp, arg, len);
-	 cp += len;
-	 *cp++ = '\01';
-      }
-
-      if (!sawexec) {
-	 Int execlen = VG_(strlen)(exec);
-	 VG_(memcpy)(cp, exec, execlen);
-	 cp += execlen;
-	 *cp++ = '\01';
-      }
-      *cp = '\0';
-
-      VG_(env_setenv)(&env, VALGRINDCLO, optvar);
-
-      arg1 = (UInt)exename;
-      arg3 = (UInt)env;
-   }
-
-   if (0) {
-      Char **cpp;
-
-      VG_(printf)("exec: %s\n", (Char *)arg1);
-      for(cpp = (Char **)arg2; cpp && *cpp; cpp++)
-	 VG_(printf)("argv: %s\n", *cpp);
-      for(cpp = (Char **)arg3; cpp && *cpp; cpp++)
-	 VG_(printf)("env: %s\n", *cpp);
-   }
-
-   /* Set our real sigmask to match the client's sigmask so that the
-      exec'd child will get the right mask.  First we need to clear
-      out any pending signals so they they don't get delivered, which
-      would confuse things.
-
-      XXX This is a bug - the signals should remain pending, and be
-      delivered to the new process after exec.  There's also a
-      race-condition, since if someone delivers us a signal between
-      the sigprocmask and the execve, we'll still get the signal. Oh
-      well.
-   */
-   {
-      vki_ksigset_t allsigs;
-      vki_ksiginfo_t info;
-      static const struct vki_timespec zero = { 0, 0 };
-    
-      VG_(ksigfillset)(&allsigs);
-      while(VG_(ksigtimedwait)(&allsigs, &info, &zero) > 0)
-	 ;
-
-      VG_(ksigprocmask)(VKI_SIG_SETMASK, &tst->sig_mask, NULL);
-   }
-
-   res = VG_(do_syscall)(__NR_execve, arg1, arg2, arg3);
-
-   /* If we got here, then the execve failed.  We've already made too much of a mess
-      of ourselves to continue, so we have to abort. */
-   VG_(message)(Vg_UserMsg, "execve(%p \"%s\", %p, %p) failed, errno %d",
-		arg1, arg1, arg2, arg3, -res);
-   VG_(core_panic)("EXEC FAILED: I can't recover from execve() failing, so I'm dying.\n"
-		   "Add more stringent tests in PRE(execve), or work out how to recover.");   
-}
-
-PRE(access)
-{
-   /* int access(const char *pathname, int mode); */
-   MAYBE_PRINTF("access ( %p, %d )\n", arg1,arg2);
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "access(pathname)", arg1 );
-}
-
-PRE(alarm)
-{
-   /* unsigned int alarm(unsigned int seconds); */
-   MAYBE_PRINTF("alarm ( %d )\n", arg1);
-}
-
-PRE(brk)
-{
-   Addr brk_limit = VG_(brk_limit);
-
-   /* libc   says: int   brk(void *end_data_segment);
-      kernel says: void* brk(void* end_data_segment);  (more or less)
-
-      libc returns 0 on success, and -1 (and sets errno) on failure.
-      Nb: if you ask to shrink the dataseg end below what it
-      currently is, that always succeeds, even if the dataseg end
-      doesn't actually change (eg. brk(0)).  Unless it seg faults.
-
-      Kernel returns the new dataseg end.  If the brk() failed, this
-      will be unchanged from the old one.  That's why calling (kernel)
-      brk(0) gives the current dataseg end (libc brk() just returns
-      zero in that case).
-
-      Both will seg fault if you shrink it back into a text segment.
-   */
-   MAYBE_PRINTF("brk ( %p ) --> ",arg1);
-
-   res = do_brk(arg1);
-
-   MAYBE_PRINTF("0x%x\n", res);
-
-   if (res == arg1) {
-      /* brk() succeeded */
-      if (res < brk_limit) {
-         /* successfully shrunk the data segment. */
-         VG_TRACK( die_mem_brk, (Addr)arg1,
-		   brk_limit-arg1 );
-      } else
-      if (res > brk_limit) {
-         /* successfully grew the data segment */
-         VG_TRACK( new_mem_brk, brk_limit,
-                                arg1-brk_limit );
-      }
-   } else {
-      /* brk() failed */
-      vg_assert(brk_limit == res);
-   }
-}
-
-PRE(chdir)
-{
-   /* int chdir(const char *path); */
-   MAYBE_PRINTF("chdir ( %p )\n", arg1);
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "chdir(path)", arg1 );
-}
-
-PRE(chmod)
-{
-   /* int chmod(const char *path, mode_t mode); */
-   MAYBE_PRINTF("chmod ( %p, %d )\n", arg1,arg2);
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "chmod(path)", arg1 );
-}
-
-PRE(chown)
-{
-   /* int chown(const char *path, uid_t owner, gid_t group); */
-   MAYBE_PRINTF("chown ( %p, 0x%x, 0x%x )\n", arg1,arg2,arg3);
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "chown(path)", arg1 );
-}
-
-PREALIAS(chown32, chown);
-PREALIAS(lchown32, chown);
-
-PRE(close)
-{
-   /* int close(int fd); */
-   MAYBE_PRINTF("close ( %d )\n",arg1);
-   /* Detect and negate attempts by the client to close Valgrind's
-      logfile fd ... */
-   if (!fd_allowed(arg1, "close", tid))
-      res = -VKI_EBADF;
-}
-
-POST(close)
-{
-   if(VG_(clo_track_fds)) record_fd_close(tid, arg1);
-}
-
-PRE(dup)
-{
-   /* int dup(int oldfd); */
-   MAYBE_PRINTF("dup ( %d ) --> ", arg1);
-}
-
-POST(dup)
-{
-   MAYBE_PRINTF("%d\n", res);
-   if (!fd_allowed(res, "dup", tid)) {
-      VG_(close)(res);
-      res = -VKI_EMFILE;
-   } else {
-      if(VG_(clo_track_fds))
-         record_fd_open(tid, res, VG_(resolve_filename)(res));
-   }
-}
-
-PRE(dup2)
-{
-   /* int dup2(int oldfd, int newfd); */
-   MAYBE_PRINTF("dup2 ( %d, %d ) ...\n", arg1,arg2);
-   if (!fd_allowed(arg2, "dup2", tid))
-      res = -VKI_EBADF;
-}
-
-POST(dup2)
-{
-   MAYBE_PRINTF("SYSCALL[%d]       dup2 ( %d, %d ) = %d\n", 
-		VG_(getpid)(), 
-		arg1, arg2, res);
-   if(VG_(clo_track_fds))
-      record_fd_open(tid, res, VG_(resolve_filename)(res));
-}
-
-PRE(fcntl)
-{
-   /* int fcntl(int fd, int cmd, int arg); */
-   MAYBE_PRINTF("fcntl ( %d, %d, %d )\n",arg1,arg2,arg3);
-}
-
-POST(fcntl)
-{
-   if (arg2 == VKI_F_DUPFD)
-      if(VG_(clo_track_fds))
-         record_fd_open(tid, res, VG_(resolve_filename)(res));
-}
-
-PRE(fchdir)
-{
-   /* int fchdir(int fd); */
-   MAYBE_PRINTF("fchdir ( %d )\n", arg1);
-}
-
-PRE(fchown)
-{
-   /* int fchown(int filedes, uid_t owner, gid_t group); */
-   MAYBE_PRINTF("fchown ( %d, %d, %d )\n", arg1,arg2,arg3);
-}
-
-PREALIAS(fchown32, fchown);
-
-PRE(fchmod)
-{
-   /* int fchmod(int fildes, mode_t mode); */
-   MAYBE_PRINTF("fchmod ( %d, %d )\n", arg1,arg2);
-}
-
-PRE(fcntl64)
-{
-   /* int fcntl64(int fd, int cmd, int arg); */
-   MAYBE_PRINTF("fcntl64 ( %d, %d, %d )\n", arg1,arg2,arg3);
-}
-
-POST(fcntl64)
-{
-   if (arg2 == VKI_F_DUPFD)
-      if(VG_(clo_track_fds))
-         record_fd_open(tid, res, VG_(resolve_filename)(res));
-}
-
-PRE(fstat)
-{
-   /* int fstat(int filedes, struct stat *buf); */
-   MAYBE_PRINTF("fstat ( %d, %p )\n",arg1,arg2);
-   SYSCALL_TRACK( pre_mem_write, tid, "fstat", arg2, sizeof(struct stat) );
-}
-
-POST(fstat)
-{
-   VG_TRACK( post_mem_write, arg2, sizeof(struct stat) );
-}
-
-static vki_ksigset_t fork_saved_mask;
-
-PRE(fork)
-{
-   vki_ksigset_t mask;
-
-   vg_assert(VG_(gettid)() == VG_(main_pid));
-
-   /* Block all signals during fork, so that we can fix things up in
-      the child without being interrupted. */
-   VG_(ksigfillset)(&mask);
-   VG_(ksigprocmask)(VKI_SIG_SETMASK, &mask, &fork_saved_mask);
-
-   /* pid_t fork(void); */
-   MAYBE_PRINTF("fork ()\n");
-
-   do_atfork_pre(tid);
-}
-
-POST(fork)
-{
-   if (res == 0) {
-      do_atfork_child(tid);
-
-      /* I am the child.  Nuke all other threads which I might
-	 have inherited from my parent.  POSIX mandates this. */
-      VG_(nuke_all_threads_except)( tid );
-
-      /* XXX TODO: tid 1 is special, and is presumed to be present.
-	 We should move this TID to 1 in the child. */
-
-      /* restore signal mask */
-      VG_(ksigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
-   } else {
-      MAYBE_PRINTF("   fork: process %d created child %d\n", VG_(main_pid), res);
-
-      do_atfork_parent(tid);
-
-      /* restore signal mask */
-      VG_(ksigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
-   }
-}
-
-PRE(clone)
-{
-   MAYBE_PRINTF("clone ( %d, %p, %p, %p, %p )\n",arg1,arg2,arg3,arg4,arg5);
-
-   if (arg2 == 0 &&
-       arg1 == (VKI_CLONE_CHILD_CLEARTID|VKI_CLONE_CHILD_SETTID|VKI_SIGCHLD)) {
-      before_fork(tid, tst);
-      res = VG_(do_syscall)(SYSNO, arg1, arg2, arg3, arg4, arg5);
-      after_fork(tid, tst);
-   } else {
-      VG_(unimplemented)
-         ("clone(): not supported by Valgrind.\n   "
-          "We do now support programs linked against\n   "
-          "libpthread.so, though.  Re-run with -v and ensure that\n   "
-          "you are picking up Valgrind's implementation of libpthread.so.");
-   }
-}
-
-PRE(fsync)
-{
-   /* int fsync(int fd); */
-   MAYBE_PRINTF("fsync ( %d )\n", arg1);
-}
-
-PRE(ftruncate)
-{
-   /* int ftruncate(int fd, size_t length); */
-   MAYBE_PRINTF("ftruncate ( %d, %d )\n", arg1,arg2);
-}
-
-PRE(ftruncate64)
-{
-   /* int ftruncate64(int fd, off64_t length); */
-   MAYBE_PRINTF("ftruncate64 ( %d, %lld )\n", 
-		arg1,arg2|((long long) arg3 << 32));
-}
-
-PRE(getdents)
-{
-   /* int getdents(unsigned int fd, struct dirent *dirp, 
-      unsigned int count); */
-   MAYBE_PRINTF("getdents ( %d, %p, %d )\n",arg1,arg2,arg3);
-   SYSCALL_TRACK( pre_mem_write, tid, "getdents(dirp)", arg2, arg3 );
-}
-
-POST(getdents)
-{
-   if (res > 0)
-      VG_TRACK( post_mem_write, arg2, res );
-}
-
-PRE(getdents64)
-{
-   /* int getdents(unsigned int fd, struct dirent64 *dirp, 
-      unsigned int count); */
-   MAYBE_PRINTF("getdents64 ( %d, %p, %d )\n",arg1,arg2,arg3);
-   SYSCALL_TRACK( pre_mem_write, tid, "getdents64(dirp)", arg2, arg3 );
-}
-
-POST(getdents64)
-{
-   if (res > 0)
-      VG_TRACK( post_mem_write, arg2, res );
-}
-
-PRE(getgroups)
-{
-   /* int getgroups(int size, gid_t list[]); */
-   MAYBE_PRINTF("getgroups ( %d, %p )\n", arg1, arg2);
-   if (arg1 > 0)
-      SYSCALL_TRACK( pre_mem_write, tid, "getgroups(list)", arg2, 
-		     arg1 * sizeof(gid_t) );
-}
-
-POST(getgroups)
-{
-   if (arg1 > 0 && res > 0)
-      VG_TRACK( post_mem_write, arg2, res * sizeof(gid_t) );
-}
-
-PREALIAS(getgroups32, getgroups);
-POSTALIAS(getgroups32, getgroups);
-
-PRE(getcwd)
-{
-   /* char *getcwd(char *buf, size_t size);  (but see comment below) */
-   MAYBE_PRINTF("getcwd ( %p, %d )\n",arg1,arg2);
-   SYSCALL_TRACK( pre_mem_write, tid, "getcwd(buf)", arg1, arg2 );
-}
-
-POST(getcwd)
-{
-   if (res != (Addr)NULL)
-      VG_TRACK( post_mem_write, arg1, res );
-}
-
-PRE(geteuid)
-{
-   /* uid_t geteuid(void); */
-   MAYBE_PRINTF("geteuid ( )\n");
-}
-
-PRE(geteuid32)
-{
-   /* ?? uid_t geteuid32(void); */
-   MAYBE_PRINTF("geteuid32(?) ( )\n");
-}
-
-PRE(getegid)
-{
-   /* gid_t getegid(void); */
-   MAYBE_PRINTF("getegid ()\n");
-}
-
-PRE(getegid32)
-{
-   /* gid_t getegid32(void); */
-   MAYBE_PRINTF("getegid32 ()\n");
-}
-
-PRE(getgid)
-{
-   /* gid_t getgid(void); */
-   MAYBE_PRINTF("getgid ()\n");
-}
-
-PRE(getgid32)
-{
-   /* gid_t getgid32(void); */
-   MAYBE_PRINTF("getgid32 ()\n");
-}
-
-PRE(getpid)
-{
-   /* pid_t getpid(void); */
-   MAYBE_PRINTF("getpid ()\n");
-}
-
-PRE(getpgid)
-{
-   /* pid_t getpgid(pid_t pid); */
-   MAYBE_PRINTF("getpgid ( %d )\n", arg1);
-}
-
-PRE(getpgrp)
-{
-   /* pid_t getpgrp(void); */
-   MAYBE_PRINTF("getpgrp ()\n");
-}
-
-PRE(getppid)
-{
-   /* pid_t getppid(void); */
-   MAYBE_PRINTF("getppid ()\n");
-}
-
-PRE(getresgid)
-{
-   /* int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); */
-   MAYBE_PRINTF("getresgid ( %p, %p, %p )\n", arg1,arg2,arg3);
-   SYSCALL_TRACK( pre_mem_write, tid, "getresgid(rgid)", 
-		  arg1, sizeof(gid_t) );
-   SYSCALL_TRACK( pre_mem_write, tid, "getresgid(egid)", 
-		  arg2, sizeof(gid_t) );
-   SYSCALL_TRACK( pre_mem_write, tid, "getresgid(sgid)", 
-		  arg3, sizeof(gid_t) );
-}
-
-POST(getresgid)
-{
-   if (res == 0) {
-      VG_TRACK( post_mem_write, arg1, sizeof(gid_t) );
-      VG_TRACK( post_mem_write, arg2, sizeof(gid_t) );
-      VG_TRACK( post_mem_write, arg3, sizeof(gid_t) );
-   }
-}
-
-PRE(getresgid32)
-{
-   /* int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); */
-   MAYBE_PRINTF("getresgid32 ( %p, %p, %p )\n", arg1,arg2,arg3);
-   SYSCALL_TRACK( pre_mem_write, tid, "getresgid32(rgid)", 
-		  arg1, sizeof(gid_t) );
-   SYSCALL_TRACK( pre_mem_write, tid, "getresgid32(egid)", 
-		  arg2, sizeof(gid_t) );
-   SYSCALL_TRACK( pre_mem_write, tid, "getresgid32(sgid)", 
-		  arg3, sizeof(gid_t) );
-}
-
-POST(getresgid32)
-{
-   if (res == 0) {
-      VG_TRACK( post_mem_write, arg1, sizeof(gid_t) );
-      VG_TRACK( post_mem_write, arg2, sizeof(gid_t) );
-      VG_TRACK( post_mem_write, arg3, sizeof(gid_t) );
-   }
-}
-
-PRE(getresuid)
-{
-   /* int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); */
-   MAYBE_PRINTF("getresuid ( %p, %p, %p )\n", arg1,arg2,arg3);
-   SYSCALL_TRACK( pre_mem_write, tid, "getresuid(ruid)", 
-		  arg1, sizeof(uid_t) );
-   SYSCALL_TRACK( pre_mem_write, tid, "getresuid(euid)", 
-		  arg2, sizeof(uid_t) );
-   SYSCALL_TRACK( pre_mem_write, tid, "getresuid(suid)", 
-		  arg3, sizeof(uid_t) );
-}
-
-POST(getresuid)
-{
-   if (res == 0) {
-      VG_TRACK( post_mem_write, arg1, sizeof(uid_t) );
-      VG_TRACK( post_mem_write, arg2, sizeof(uid_t) );
-      VG_TRACK( post_mem_write, arg3, sizeof(uid_t) );
-   }
-}
-
-PRE(getresuid32)
-{
-   /* int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); */
-   MAYBE_PRINTF("getresuid32 ( %p, %p, %p )\n", arg1,arg2,arg3);
-   SYSCALL_TRACK( pre_mem_write, tid, "getresuid32(ruid)", 
-		  arg1, sizeof(uid_t) );
-   SYSCALL_TRACK( pre_mem_write, tid, "getresuid32(euid)", 
-		  arg2, sizeof(uid_t) );
-   SYSCALL_TRACK( pre_mem_write, tid, "getresuid32(suid)", 
-		  arg3, sizeof(uid_t) );
-}
-
-POST(getresuid32)
-{
-   if (res == 0) {
-      VG_TRACK( post_mem_write, arg1, sizeof(uid_t) );
-      VG_TRACK( post_mem_write, arg2, sizeof(uid_t) );
-      VG_TRACK( post_mem_write, arg3, sizeof(uid_t) );
-   }
-}
-
-PRE(getrlimit)
-{
-   /* int getrlimit (int resource, struct rlimit *rlim); */
-   MAYBE_PRINTF("getrlimit ( %d, %p )\n", arg1,arg2);
-   SYSCALL_TRACK( pre_mem_write, tid, "getrlimit(rlim)", arg2, 
-		  sizeof(struct rlimit) );
-}
-
-POST(getrlimit)
-{
-   if (res == 0)
-      VG_TRACK( post_mem_write, arg2, sizeof(struct rlimit) );
-}
-
-PREALIAS(ugetrlimit, getrlimit);
-POSTALIAS(ugetrlimit, getrlimit);
-
-PRE(getrusage)
-{
-   /* int getrusage (int who, struct rusage *usage); */
-   MAYBE_PRINTF("getrusage ( %d, %p )\n", arg1,arg2);
-   SYSCALL_TRACK( pre_mem_write, tid, "getrusage(usage)", arg2, 
-		  sizeof(struct rusage) );
-}
-
-POST(getrusage)
-{
-   if (res == 0)
-      VG_TRACK( post_mem_write,arg2, sizeof(struct rusage) );
-}
-
-PRE(gettimeofday)
-{
-   /* int gettimeofday(struct timeval *tv, struct timezone *tz); */
-   MAYBE_PRINTF("gettimeofday ( %p, %p )\n",arg1,arg2);
-   SYSCALL_TRACK( pre_mem_write, tid, "gettimeofday(tv)", arg1, 
-		  sizeof(struct timeval) );
-   if (arg2 != 0)
-      SYSCALL_TRACK( pre_mem_write, tid, "gettimeofday(tz)", arg2, 
-		     sizeof(struct timezone) );
-}
-
-POST(gettimeofday)
-{
-   if (res == 0) {
-      VG_TRACK( post_mem_write, arg1, sizeof(struct timeval) );
-      if (arg2 != 0)
-	 VG_TRACK( post_mem_write, arg2, sizeof(struct timezone) );
-   }
-}
-
-PRE(getuid)
-{
-   /* uid_t getuid(void); */
-   MAYBE_PRINTF("getuid ( )\n");
-}
-
-PRE(getuid32)
-{
-   /* ???uid_t getuid32(void); */
-   MAYBE_PRINTF("getuid32 ( )\n");
-}
-
-PRE(ipc)
-{
-   MAYBE_PRINTF("ipc ( %d, %d, %d, %d, %p, %d )\n",
-		arg1,arg2,arg3,arg4,arg5,arg6);
-   switch (arg1 /* call */) {
-   case 1: /* IPCOP_semop */
-      SYSCALL_TRACK( pre_mem_read, tid, "semop(sops)", arg5, 
-		     arg3 * sizeof(struct sembuf) );
-      break;
-   case 2: /* IPCOP_semget */
-   case 3: /* IPCOP_semctl */
-      break;
-   case 11: /* IPCOP_msgsnd */
-   {
-      struct msgbuf *msgp = (struct msgbuf *)arg5;
-      Int msgsz = arg3;
-
-      SYSCALL_TRACK( pre_mem_read, tid, "msgsnd(msgp->mtype)", 
-		     (UInt)&msgp->mtype, sizeof(msgp->mtype) );
-      SYSCALL_TRACK( pre_mem_read, tid, "msgsnd(msgp->mtext)", 
-		     (UInt)msgp->mtext, msgsz );
-      break;
-   }
-   case 12: /* IPCOP_msgrcv */
-   {
-      struct msgbuf *msgp;
-      Int msgsz = arg3;
- 
-      msgp = (struct msgbuf *)deref_Addr( tid,
-					  (Addr) (&((struct ipc_kludge *)arg5)->msgp),
-					  "msgrcv(msgp)" );
-
-      SYSCALL_TRACK( pre_mem_write, tid, "msgrcv(msgp->mtype)", 
-		     (UInt)&msgp->mtype, sizeof(msgp->mtype) );
-      SYSCALL_TRACK( pre_mem_write, tid, "msgrcv(msgp->mtext)", 
-		     (UInt)msgp->mtext, msgsz );
-      break;
-   }
-   case 13: /* IPCOP_msgget */
-      break;
-   case 14: /* IPCOP_msgctl */
-   {
-      switch (arg3 /* cmd */) {
-      case IPC_STAT:
-	 SYSCALL_TRACK( pre_mem_write, tid, "msgctl(buf)", arg5, 
-			sizeof(struct msqid_ds) );
-	 break;
-      case IPC_SET:
-	 SYSCALL_TRACK( pre_mem_read, tid, "msgctl(buf)", arg5, 
-			sizeof(struct msqid_ds) );
-	 break;
-#                    if defined(IPC_64)
-      case IPC_STAT|IPC_64:
-	 SYSCALL_TRACK( pre_mem_write, tid, "msgctl(buf)", arg5, 
-			sizeof(struct msqid64_ds) );
-	 break;
-#                    endif
-#                    if defined(IPC_64)
-      case IPC_SET|IPC_64:
-	 SYSCALL_TRACK( pre_mem_read, tid, "msgctl(buf)", arg5, 
-			sizeof(struct msqid64_ds) );
-	 break;
-#                    endif
-      default:
-	 break;
-      }
-      break;
-   }
-   case 21: /* IPCOP_shmat */
-   {
-      UInt shmid = arg2;
-      UInt segmentSize = get_shm_size ( shmid );
-      
-      /* If they didn't ask for a particular address, then place it
-	 like an mmap. */
-      if (arg5 == 0)
-	 arg5 = VG_(find_map_space)(0, segmentSize, True);
-      else if (!valid_client_addr(arg5, segmentSize, tid, "shmat"))
-	 res = -VKI_EINVAL;
-      break;
-   }
-   case 22: /* IPCOP_shmdt */
-      if (!valid_client_addr(arg1, 1, tid, "shmdt"))
-	 res = -VKI_EINVAL;
-      break;
-   case 23: /* IPCOP_shmget */
-      break;
-   case 24: /* IPCOP_shmctl */
-      /* Subject: shmctl: The True Story
-	 Date: Thu, 9 May 2002 18:07:23 +0100 (BST)
-	 From: Reuben Thomas <rrt@mupsych.org>
-	 To: Julian Seward <jseward@acm.org>
-
-	 1. As you suggested, the syscall subop is in arg1.
-
-	 2. There are a couple more twists, so the arg order
-	 is actually:
-
-	 arg1 syscall subop
-	 arg2 file desc
-	 arg3 shm operation code (can have IPC_64 set)
-	 arg4 0 ??? is arg3-arg4 a 64-bit quantity when IPC_64
-	 is defined?
-	 arg5 pointer to buffer
-
-	 3. With this in mind, I've amended the case as below:
-      */
-   {
-      UInt cmd = arg3;
-      Bool out_arg = False;
-      if ( arg5 ) {
-#                    if defined(IPC_64)
-	 cmd = cmd & (~IPC_64);
-#                    endif
-	 out_arg = cmd == SHM_STAT || cmd == IPC_STAT;
-	 if ( out_arg )
-	    SYSCALL_TRACK( pre_mem_write, tid, 
-                           "shmctl(SHM_STAT or IPC_STAT,buf)", 
-                           arg5, sizeof(struct shmid_ds) );
-	 else
-	    SYSCALL_TRACK( pre_mem_read, tid, 
-                           "shmctl(SHM_XXXX,buf)", 
-                           arg5, sizeof(struct shmid_ds) );
-      }
-   }
-   break;
-   default:
-      VG_(message)(Vg_DebugMsg,
-		   "FATAL: unhandled syscall(ipc) %d",
-		   arg1 );
-      VG_(core_panic)("... bye!\n");
-      break; /*NOTREACHED*/
-   }   
-}
-
-POST(ipc)
-{
-   switch (arg1 /* call */) {
-   case 1: /* IPCOP_semop */
-      break;
-   case 2: /* IPCOP_semget */
-   case 3: /* IPCOP_semctl */
-      break;
-   case 11: /* IPCOP_msgsnd */
-      break;
-   case 12: /* IPCOP_msgrcv */
-   {
-      struct msgbuf *msgp;
- 
-      msgp = (struct msgbuf *)deref_Addr( tid,
-					  (Addr) (&((struct ipc_kludge *)arg5)->msgp),
-					  "msgrcv(msgp)" );
-      if ( res > 0 ) {
-	 VG_TRACK( post_mem_write, (UInt)&msgp->mtype, 
-		   sizeof(msgp->mtype) );
-	 VG_TRACK( post_mem_write, (UInt)msgp->mtext, res );
-      }
-      break;
-   }
-   case 13: /* IPCOP_msgget */
-      break;
-   case 14: /* IPCOP_msgctl */
-   {
-      switch (arg3 /* cmd */) {
-      case IPC_STAT:
-	 if ( res > 0 ) {
-	    VG_TRACK( post_mem_write, arg5, 
-		      sizeof(struct msqid_ds) );
-	 }
-	 break;
-      case IPC_SET:
-	 break;
-#                    if defined(IPC_64)
-      case IPC_STAT|IPC_64:
-	 if ( res > 0 ) {
-	    VG_TRACK( post_mem_write, arg5, 
-		      sizeof(struct msqid64_ds) );
-	 }
-	 break;
-#                    endif
-#                    if defined(IPC_64)
-      case IPC_SET|IPC_64:
-	 break;
-#                    endif
-      default:
-	 break;
-      }
-      break;
-   }
-   case 21: /* IPCOP_shmat */
-   {
-      Int shmid = arg2;
-      Int shmflag = arg3;
-      Addr addr;
-
-      /* force readability. before the syscall it is
-       * indeed uninitialized, as can be seen in
-       * glibc/sysdeps/unix/sysv/linux/shmat.c */
-      VG_TRACK( post_mem_write, arg4, sizeof( ULong ) );
-
-      addr = deref_Addr ( tid, arg4, "shmat(addr)" );
-      if ( addr > 0 ) { 
-	 UInt segmentSize = get_shm_size ( shmid );
-	 if ( segmentSize > 0 ) {
-	    UInt prot;
-	    /* we don't distinguish whether it's read-only or
-	     * read-write -- it doesn't matter really. */
-	    VG_TRACK( new_mem_mmap, addr, segmentSize, 
-		      True, True, False );
-
-	    prot = VKI_PROT_READ|VKI_PROT_WRITE;
-	    if (!(shmflag & 010000)) /* = SHM_RDONLY */
-	       prot &= ~VKI_PROT_WRITE;
-	    VG_(map_segment)(addr, segmentSize, prot,
-			     SF_SHARED | SF_SHM);
-	 }
-      }
-      break;
-   }
-   case 22: /* IPCOP_shmdt */
-   {
-      Segment *s = VG_(find_segment)(arg1);
-
-      if (s != NULL && (s->flags & SF_SHM) && VG_(seg_contains)(s, arg1, 1)) {
-	 VG_TRACK( die_mem_munmap, s->addr, s->len );
-	 VG_(unmap_range)(s->addr, s->len);
-      }
-      break;
-   }
-   case 23: /* IPCOP_shmget */
-      break;
-   case 24: /* IPCOP_shmctl */
-      /* Subject: shmctl: The True Story
-	 Date: Thu, 9 May 2002 18:07:23 +0100 (BST)
-	 From: Reuben Thomas <rrt@mupsych.org>
-	 To: Julian Seward <jseward@acm.org>
-
-	 1. As you suggested, the syscall subop is in arg1.
-
-	 2. There are a couple more twists, so the arg order
-	 is actually:
-
-	 arg1 syscall subop
-	 arg2 file desc
-	 arg3 shm operation code (can have IPC_64 set)
-	 arg4 0 ??? is arg3-arg4 a 64-bit quantity when IPC_64
-	 is defined?
-	 arg5 pointer to buffer
-
-	 3. With this in mind, I've amended the case as below:
-      */
-   {
-      UInt cmd = arg3;
-      Bool out_arg = False;
-      if ( arg5 ) {
-#                    if defined(IPC_64)
-	 cmd = cmd & (~IPC_64);
-#                    endif
-	 out_arg = cmd == SHM_STAT || cmd == IPC_STAT;
-      }
-      if ( arg5 && res == 0 && out_arg )
-	 VG_TRACK( post_mem_write, arg5, 
-		   sizeof(struct shmid_ds) );
-   }
-   break;
-   default:
-      VG_(message)(Vg_DebugMsg,
-		   "FATAL: unhandled syscall(ipc) %d",
-		   arg1 );
-      VG_(core_panic)("... bye!\n");
-      break; /*NOTREACHED*/
-   }
-}
-
-PRE(ioctl)
-{
-   /* int ioctl(int d, int request, ...)
-      [The  "third"  argument  is traditionally char *argp, 
-      and will be so named for this discussion.]
-   */
-   /*
-     VG_(message)(
-     Vg_DebugMsg, 
-     "is an IOCTL,  request = 0x%x,   d = %d,   argp = 0x%x", 
-     arg2,arg1,arg3);
-   */
-   MAYBE_PRINTF("ioctl ( %d, 0x%x, %p )\n",arg1,arg2,arg3);
-   switch (arg2 /* request */) {
-   case TCSETS:
-   case TCSETSW:
-   case TCSETSF:
-      SYSCALL_TRACK( pre_mem_read, tid, "ioctl(TCSET{S,SW,SF})", arg3, 
-		     VKI_SIZEOF_STRUCT_TERMIOS );
-      break; 
-   case TCGETS:
-      SYSCALL_TRACK( pre_mem_write, tid, "ioctl(TCGETS)", arg3, 
-		     VKI_SIZEOF_STRUCT_TERMIOS );
-      break;
-   case TCSETA:
-   case TCSETAW:
-   case TCSETAF:
-      SYSCALL_TRACK( pre_mem_read, tid, "ioctl(TCSET{A,AW,AF})", arg3,
-		     VKI_SIZEOF_STRUCT_TERMIO );
-      break;
-   case TCGETA:
-      SYSCALL_TRACK( pre_mem_write, tid, "ioctl(TCGETA)", arg3,
-		     VKI_SIZEOF_STRUCT_TERMIO );
-      break;
-   case TCSBRK:
-   case TCXONC:
-   case TCSBRKP:
-   case TCFLSH:
-      /* These just take an int by value */
-      break;
-   case TIOCGWINSZ:
-      SYSCALL_TRACK( pre_mem_write, tid, "ioctl(TIOCGWINSZ)", arg3, 
-		     sizeof(struct winsize) );
-      break;
-   case TIOCSWINSZ:
-      SYSCALL_TRACK( pre_mem_read, tid, "ioctl(TIOCSWINSZ)", arg3, 
-		     sizeof(struct winsize) );
-      break;
-   case TIOCLINUX:
-      SYSCALL_TRACK( pre_mem_read, tid, "ioctl(TIOCLINUX)", arg3, 
-		     sizeof(char *) );
-      if (*(char *)arg3 == 11) {
-	 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(TIOCLINUX, 11)", 
-			arg3, 2 * sizeof(char *) );
-      }
-      break;
-   case TIOCGPGRP:
-      /* Get process group ID for foreground processing group. */
-      SYSCALL_TRACK( pre_mem_write, tid, "ioctl(TIOCGPGRP)", arg3,
-		     sizeof(pid_t) );
-      break;
-   case TIOCSPGRP:
-      /* Set a process group ID? */
-      SYSCALL_TRACK( pre_mem_write, tid, "ioctl(TIOCGPGRP)", arg3,
-		     sizeof(pid_t) );
-      break;
-   case TIOCGPTN: /* Get Pty Number (of pty-mux device) */
-      SYSCALL_TRACK( pre_mem_write, tid, "ioctl(TIOCGPTN)", 
-		     arg3, sizeof(int) );
-      break;
-   case TIOCSCTTY:
-      /* Just takes an int value.  */
-      break;
-   case TIOCSPTLCK: /* Lock/unlock Pty */
-      SYSCALL_TRACK( pre_mem_read, tid, "ioctl(TIOCSPTLCK)", 
-		     arg3, sizeof(int) );
-      break;
-   case FIONBIO:
-      SYSCALL_TRACK( pre_mem_read, tid, "ioctl(FIONBIO)", 
-		     arg3, sizeof(int) );
-      break;
-   case FIOASYNC:
-      SYSCALL_TRACK( pre_mem_read, tid, "ioctl(FIOASYNC)", 
-		     arg3, sizeof(int) );
-      break;
-   case FIONREAD:                /* identical to SIOCINQ */
-      SYSCALL_TRACK( pre_mem_write, tid, "ioctl(FIONREAD)", 
-		     arg3, sizeof(int) );
-      break;
-
-      /* If you get compilation problems here, change the #if
-	 1 to #if 0 and get rid of <scsi/sg.h> in
-	 vg_unsafe.h. */
-#       if 1
-   case SG_SET_COMMAND_Q:
-      SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SG_SET_COMMAND_Q)", 
-		     arg3, sizeof(int) );
-      break;
-#           if defined(SG_IO)
-   case SG_IO:
-      SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SG_IO)", arg3, 
-		     sizeof(struct sg_io_hdr) );
-      break;
-#           endif /* SG_IO */
-   case SG_GET_SCSI_ID:
-      /* Note: sometimes sg_scsi_id is called sg_scsi_id_t */
-      SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SG_GET_SCSI_ID)", arg3, 
-		     sizeof(struct sg_scsi_id) );
-      break;
-   case SG_SET_RESERVED_SIZE:
-      SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SG_SET_RESERVED_SIZE)", 
-		     arg3, sizeof(int) );
-      break;
-   case SG_SET_TIMEOUT:
-      SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SG_SET_TIMEOUT)", arg3, 
-		     sizeof(int) );
-      break;
-   case SG_GET_RESERVED_SIZE:
-      SYSCALL_TRACK( pre_mem_write, tid, 
-		     "ioctl(SG_GET_RESERVED_SIZE)", arg3, 
-		     sizeof(int) );
-      break;
-   case SG_GET_TIMEOUT:
-      SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SG_GET_TIMEOUT)", arg3, 
-		     sizeof(int) );
-      break;
-   case SG_GET_VERSION_NUM:
-      SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SG_GET_VERSION_NUM)", 
-		     arg3, sizeof(int) );
-      break;
-#       endif
-
-   case VKI_IIOCGETCPS:
-      /* In early 2.4 kernels, ISDN_MAX_CHANNELS was only defined
-       * when KERNEL was. I never saw a larger value than 64 though */
-#              ifndef ISDN_MAX_CHANNELS
-#              define ISDN_MAX_CHANNELS 64
-#              endif
-      SYSCALL_TRACK( pre_mem_write, tid, "ioctl(IIOCGETCPS)", arg3,
-		     ISDN_MAX_CHANNELS 
-		     * 2 * sizeof(unsigned long) );
-      break;
-   case VKI_IIOCNETGPN:
-      SYSCALL_TRACK( pre_mem_read, tid, "ioctl(IIOCNETGPN)",
-		     (UInt)&((isdn_net_ioctl_phone *)arg3)->name,
-		     sizeof(((isdn_net_ioctl_phone *)arg3)->name) );
-      SYSCALL_TRACK( pre_mem_write, tid, "ioctl(IIOCNETGPN)", arg3,
-		     sizeof(isdn_net_ioctl_phone) );
-      break;
-
-      /* These all use struct ifreq AFAIK */
-   case SIOCGIFINDEX:
-   case SIOCGIFFLAGS:        /* get flags                    */
-   case SIOCGIFHWADDR:       /* Get hardware address         */
-   case SIOCGIFMTU:          /* get MTU size                 */
-   case SIOCGIFADDR:         /* get PA address               */
-   case SIOCGIFNETMASK:      /* get network PA mask          */
-   case SIOCGIFMETRIC:       /* get metric                   */
-   case SIOCGIFMAP:          /* Get device parameters        */
-   case SIOCGIFTXQLEN:       /* Get the tx queue length      */
-   case SIOCGIFDSTADDR:      /* get remote PA address        */
-   case SIOCGIFBRDADDR:      /* get broadcast PA address     */
-   case SIOCGIFNAME:         /* get iface name               */
-      SYSCALL_TRACK( pre_mem_write,tid, "ioctl(SIOCGIFINDEX)", arg3, 
-		     sizeof(struct ifreq));
-      break;
-   case SIOCGIFCONF:         /* get iface list               */
-      /* WAS:
-	 SYSCALL_TRACK( pre_mem_write,"ioctl(SIOCGIFCONF)", arg3, 
-	 sizeof(struct ifconf));
-	 KERNEL_DO_SYSCALL(tid,res);
-	 if (!VG_(is_kerror)(res) && res == 0)
-	 VG_TRACK( post_mem_write,arg3, sizeof(struct ifconf));
-      */
-      SYSCALL_TRACK( pre_mem_read,tid, "ioctl(SIOCGIFCONF)", arg3, 
-		     sizeof(struct ifconf));
-      if ( arg3 ) {
-	 // TODO len must be readable and writable
-	 // buf pointer only needs to be readable
-	 struct ifconf *ifc = (struct ifconf *) arg3;
-	 SYSCALL_TRACK( pre_mem_write,tid, "ioctl(SIOCGIFCONF).ifc_buf",
-			(Addr)(ifc->ifc_buf), (UInt)(ifc->ifc_len) );
-      }
-      break;
-   case SIOCGSTAMP:
-      SYSCALL_TRACK( pre_mem_write,tid, "ioctl(SIOCGSTAMP)", arg3, 
-		     sizeof(struct timeval));
-      break;
-      /* SIOCOUTQ is an ioctl that, when called on a socket, returns
-	 the number of bytes currently in that socket's send buffer.
-	 It writes this value as an int to the memory location
-	 indicated by the third argument of ioctl(2). */
-   case SIOCOUTQ:
-      SYSCALL_TRACK( pre_mem_write,tid, "ioctl(SIOCOUTQ)", arg3, 
-		     sizeof(int));
-      break;
-   case SIOCGRARP:           /* get RARP table entry         */
-   case SIOCGARP:            /* get ARP table entry          */
-      SYSCALL_TRACK( pre_mem_write,tid, "ioctl(SIOCGARP)", arg3, 
-		     sizeof(struct arpreq));
-      break;
-                    
-   case SIOCSIFFLAGS:        /* set flags                    */
-   case SIOCSIFMAP:          /* Set device parameters        */
-   case SIOCSIFTXQLEN:       /* Set the tx queue length      */
-   case SIOCSIFDSTADDR:      /* set remote PA address        */
-   case SIOCSIFBRDADDR:      /* set broadcast PA address     */
-   case SIOCSIFNETMASK:      /* set network PA mask          */
-   case SIOCSIFMETRIC:       /* set metric                   */
-   case SIOCSIFADDR:         /* set PA address               */
-   case SIOCSIFMTU:          /* set MTU size                 */
-   case SIOCSIFHWADDR:       /* set hardware address         */
-      SYSCALL_TRACK( pre_mem_read,tid,"ioctl(SIOCSIFFLAGS)", arg3, 
-		     sizeof(struct ifreq));
-      break;
-      /* Routing table calls.  */
-   case SIOCADDRT:           /* add routing table entry      */
-   case SIOCDELRT:           /* delete routing table entry   */
-      SYSCALL_TRACK( pre_mem_read,tid,"ioctl(SIOCADDRT/DELRT)", arg3, 
-		     sizeof(struct rtentry));
-      break;
-
-      /* RARP cache control calls. */
-   case SIOCDRARP:           /* delete RARP table entry      */
-   case SIOCSRARP:           /* set RARP table entry         */
-      /* ARP cache control calls. */
-   case SIOCSARP:            /* set ARP table entry          */
-   case SIOCDARP:            /* delete ARP table entry       */
-      SYSCALL_TRACK( pre_mem_read,tid, "ioctl(SIOCSIFFLAGS)", arg3, 
-		     sizeof(struct ifreq));
-      break;
-
-   case SIOCSPGRP:
-      SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SIOCSPGRP)", arg3, 
-		     sizeof(int) );
-      break;
-
-      /* linux/soundcard interface (OSS) */
-   case SNDCTL_SEQ_GETOUTCOUNT:
-   case SNDCTL_SEQ_GETINCOUNT:
-   case SNDCTL_SEQ_PERCMODE:
-   case SNDCTL_SEQ_TESTMIDI:
-   case SNDCTL_SEQ_RESETSAMPLES:
-   case SNDCTL_SEQ_NRSYNTHS:
-   case SNDCTL_SEQ_NRMIDIS:
-   case SNDCTL_SEQ_GETTIME:
-   case SNDCTL_DSP_GETFMTS:
-   case SNDCTL_DSP_GETTRIGGER:
-   case SNDCTL_DSP_GETODELAY:
-#           if defined(SNDCTL_DSP_GETSPDIF)
-   case SNDCTL_DSP_GETSPDIF:
-#           endif
-   case SNDCTL_DSP_GETCAPS:
-   case SOUND_PCM_READ_RATE:
-   case SOUND_PCM_READ_CHANNELS:
-   case SOUND_PCM_READ_BITS:
-   case (SOUND_PCM_READ_BITS|0x40000000): /* what the fuck ? */
-   case SOUND_PCM_READ_FILTER:
-      SYSCALL_TRACK( pre_mem_write,tid,
-		     "ioctl(SNDCTL_XXX|SOUND_XXX (SIOR, int))", 
-		     arg3,
-		     sizeof(int));
-      break;
-   case SNDCTL_SEQ_CTRLRATE:
-   case SNDCTL_DSP_SPEED:
-   case SNDCTL_DSP_STEREO:
-   case SNDCTL_DSP_GETBLKSIZE: 
-   case SNDCTL_DSP_CHANNELS:
-   case SOUND_PCM_WRITE_FILTER:
-   case SNDCTL_DSP_SUBDIVIDE:
-   case SNDCTL_DSP_SETFRAGMENT:
-#           if defined(SNDCTL_DSP_GETCHANNELMASK)
-   case SNDCTL_DSP_GETCHANNELMASK:
-#           endif
-#           if defined(SNDCTL_DSP_BIND_CHANNEL)
-   case SNDCTL_DSP_BIND_CHANNEL:
-#           endif
-   case SNDCTL_TMR_TIMEBASE:
-   case SNDCTL_TMR_TEMPO:
-   case SNDCTL_TMR_SOURCE:
-   case SNDCTL_MIDI_PRETIME:
-   case SNDCTL_MIDI_MPUMODE:
-      SYSCALL_TRACK( pre_mem_read,tid, "ioctl(SNDCTL_XXX|SOUND_XXX "
-		     "(SIOWR, int))", 
-		     arg3, sizeof(int));
-      SYSCALL_TRACK( pre_mem_write,tid, "ioctl(SNDCTL_XXX|SOUND_XXX "
-		     "(SIOWR, int))", 
-		     arg3, sizeof(int));
-      break;
-   case SNDCTL_DSP_GETOSPACE:
-   case SNDCTL_DSP_GETISPACE:
-      SYSCALL_TRACK( pre_mem_write,tid, 
-		     "ioctl(SNDCTL_XXX|SOUND_XXX "
-		     "(SIOR, audio_buf_info))", arg3,
-		     sizeof(audio_buf_info));
-      break;
-   case SNDCTL_DSP_SETTRIGGER:
-      SYSCALL_TRACK( pre_mem_read,tid, 
-		     "ioctl(SNDCTL_XXX|SOUND_XXX (SIOW, int))", 
-		     arg3, sizeof(int));
-      break;
-
-   case SNDCTL_DSP_POST:
-   case SNDCTL_DSP_RESET:
-   case SNDCTL_DSP_SYNC:
-   case SNDCTL_DSP_SETSYNCRO:
-   case SNDCTL_DSP_SETDUPLEX:
-      break;
-
-      /* Real Time Clock (/dev/rtc) ioctls */
-#           ifndef GLIBC_2_1
-   case RTC_UIE_ON:
-   case RTC_UIE_OFF:
-   case RTC_AIE_ON:
-   case RTC_AIE_OFF:
-   case RTC_PIE_ON:
-   case RTC_PIE_OFF:
-   case RTC_IRQP_SET:
-      break;
-   case RTC_RD_TIME:
-   case RTC_ALM_READ:
-      SYSCALL_TRACK( pre_mem_write,tid, "ioctl(RTC_RD_TIME/ALM_READ)", 
-		     arg3, sizeof(struct rtc_time));
-      break;
-   case RTC_ALM_SET:
-      SYSCALL_TRACK( pre_mem_read,tid, "ioctl(RTC_ALM_SET)", arg3,
-		     sizeof(struct rtc_time));
-      break;
-   case RTC_IRQP_READ:
-      SYSCALL_TRACK( pre_mem_write,tid, "ioctl(RTC_IRQP_READ)", arg3,
-		     sizeof(unsigned long));
-      break;
-#           endif /* GLIBC_2_1 */
-
-#           ifdef BLKGETSIZE
-   case BLKGETSIZE:
-      SYSCALL_TRACK( pre_mem_write,tid, "ioctl(BLKGETSIZE)", arg3,
-		     sizeof(unsigned long));
-      break;
-#           endif /* BLKGETSIZE */
-
-      /* CD ROM stuff (??)  */
-   case CDROMSUBCHNL:
-      SYSCALL_TRACK( pre_mem_read,tid, 
-		     "ioctl(CDROMSUBCHNL (cdsc_format, char))",
-		     (int) &(((struct cdrom_subchnl *) arg3)->cdsc_format), 
-		     sizeof(((struct cdrom_subchnl *) arg3)->cdsc_format));
-      SYSCALL_TRACK( pre_mem_write,tid, 
-		     "ioctl(CDROMSUBCHNL)", arg3, 
-		     sizeof(struct cdrom_subchnl));
-      break;
-   case CDROMREADTOCHDR:
-      SYSCALL_TRACK( pre_mem_write,tid, 
-		     "ioctl(CDROMREADTOCHDR)", arg3, 
-		     sizeof(struct cdrom_tochdr));
-      break;
-   case CDROMREADTOCENTRY:
-      SYSCALL_TRACK( pre_mem_read,tid, 
-		     "ioctl(CDROMREADTOCENTRY (cdte_format, char))",
-		     (int) &(((struct cdrom_tocentry *) arg3)->cdte_format), 
-		     sizeof(((struct cdrom_tocentry *) arg3)->cdte_format));
-      SYSCALL_TRACK( pre_mem_read,tid, 
-		     "ioctl(CDROMREADTOCENTRY (cdte_track, char))",
-		     (int) &(((struct cdrom_tocentry *) arg3)->cdte_track), 
-		     sizeof(((struct cdrom_tocentry *) arg3)->cdte_track));
-      SYSCALL_TRACK( pre_mem_write,tid, 
-		     "ioctl(CDROMREADTOCENTRY)", arg3, 
-		     sizeof(struct cdrom_tocentry));
-      break;
-   case CDROMPLAYMSF:
-      SYSCALL_TRACK( pre_mem_read,tid, "ioctl(CDROMPLAYMSF)", arg3, 
-		     sizeof(struct cdrom_msf));
-      break;
-      /* The following two are probably bogus (should check args
-	 for readability).  JRS 20021117 */
-   case CDROM_DRIVE_STATUS: /* 0x5326 */
-   case CDROM_CLEAR_OPTIONS: /* 0x5321 */
-      break;
-
-      /* We don't have any specific information on it, so
-	 try to do something reasonable based on direction and
-	 size bits.  The encoding scheme is described in
-	 /usr/include/asm/ioctl.h.  
-
-	 According to Simon Hausmann, _IOC_READ means the kernel
-	 writes a value to the ioctl value passed from the user
-	 space and the other way around with _IOC_WRITE. */
-   default: {
-      UInt dir  = _IOC_DIR(arg2);
-      UInt size = _IOC_SIZE(arg2);
-      if (VG_(strstr)(VG_(clo_weird_hacks), "lax-ioctls") != NULL) {
-	 /* 
-	  * Be very lax about ioctl handling; the only
-	  * assumption is that the size is correct. Doesn't
-	  * require the full buffer to be initialized when
-	  * writing.  Without this, using some device
-	  * drivers with a large number of strange ioctl
-	  * commands becomes very tiresome.
-	  */
-      } else if (/* size == 0 || */ dir == _IOC_NONE) {
-	 static Int moans = 3;
-	 if (moans > 0) {
-	    moans--;
-	    VG_(message)(Vg_UserMsg, 
-			 "Warning: noted but unhandled ioctl 0x%x"
-			 " with no size/direction hints",
-			 arg2); 
-	    VG_(message)(Vg_UserMsg, 
-			 "   This could cause spurious value errors"
-			 " to appear.");
-	    VG_(message)(Vg_UserMsg, 
-			 "   See README_MISSING_SYSCALL_OR_IOCTL for "
-			 "guidance on writing a proper wrapper." );
-	 }
-      } else {
-	 if ((dir & _IOC_WRITE) && size > 0)
-	    SYSCALL_TRACK( pre_mem_read,tid, "ioctl(generic)", 
-			   arg3, size);
-	 if ((dir & _IOC_READ) && size > 0)
-	    SYSCALL_TRACK( pre_mem_write,tid, "ioctl(generic)", 
-			   arg3, size);
-      }
-      break;
-   }
-   }   
-}
-
-POST(ioctl)
-{
-   /* int ioctl(int d, int request, ...)
-      [The  "third"  argument  is traditionally char *argp, 
-      and will be so named for this discussion.]
-   */
-   /*
-     VG_(message)(
-     Vg_DebugMsg, 
-     "is an IOCTL,  request = 0x%x,   d = %d,   argp = 0x%x", 
-     arg2,arg1,arg3);
-   */
-   MAYBE_PRINTF("ioctl ( %d, 0x%x, %p )\n",arg1,arg2,arg3);
-   switch (arg2 /* request */) {
-   case TCSETS:
-   case TCSETSW:
-   case TCSETSF:
-      break; 
-   case TCGETS:
-      if (res == 0)
-	 VG_TRACK( post_mem_write, arg3, VKI_SIZEOF_STRUCT_TERMIOS );
-      break;
-   case TCSETA:
-   case TCSETAW:
-   case TCSETAF:
-      break;
-   case TCGETA:
-      if (res == 0)
-	 VG_TRACK( post_mem_write, arg3, VKI_SIZEOF_STRUCT_TERMIO );
-      break;
-   case TCSBRK:
-   case TCXONC:
-   case TCSBRKP:
-   case TCFLSH:
-      break;
-   case TIOCGWINSZ:
-      if (res == 0)
-	 VG_TRACK( post_mem_write, arg3, sizeof(struct winsize) );
-      break;
-   case TIOCSWINSZ:
-      break;
-   case TIOCLINUX:
-      if (res == 0)
-	 VG_TRACK( post_mem_write, arg3, sizeof(char *) );
-      break;
-   case TIOCGPGRP:
-      /* Get process group ID for foreground processing group. */
-      if (res == 0)
-	 VG_TRACK( post_mem_write, arg3, sizeof(pid_t) );
-      break;
-   case TIOCSPGRP:
-      /* Set a process group ID? */
-      if (res == 0)
-	 VG_TRACK( post_mem_write, arg3, sizeof(pid_t) );
-      break;
-   case TIOCGPTN: /* Get Pty Number (of pty-mux device) */
-      if (res == 0)
-	 VG_TRACK( post_mem_write, arg3, sizeof(int));
-      break;
-   case TIOCSCTTY:
-      break;
-   case TIOCSPTLCK: /* Lock/unlock Pty */
-      break;
-   case FIONBIO:
-      break;
-   case FIOASYNC:
-      break;
-   case FIONREAD:                /* identical to SIOCINQ */
-      if (res == 0)
-	 VG_TRACK( post_mem_write, arg3, sizeof(int) );
-      break;
-
-      /* If you get compilation problems here, change the #if
-	 1 to #if 0 and get rid of <scsi/sg.h> in
-	 vg_unsafe.h. */
-#       if 1
-   case SG_SET_COMMAND_Q:
-      break;
-#           if defined(SG_IO)
-   case SG_IO:
-      if (res == 0)
-	 VG_TRACK( post_mem_write,arg3, sizeof(struct sg_io_hdr));
-      break;
-#           endif /* SG_IO */
-   case SG_GET_SCSI_ID:
-      if (res == 0)
-	 VG_TRACK( post_mem_write,arg3, sizeof(struct sg_scsi_id));
-      break;
-   case SG_SET_RESERVED_SIZE:
-      break;
-   case SG_SET_TIMEOUT:
-      break;
-   case SG_GET_RESERVED_SIZE:
-      if (res == 0)
-	 VG_TRACK( post_mem_write,arg3, sizeof(int));
-      break;
-   case SG_GET_TIMEOUT:
-      if (res == 0)
-	 VG_TRACK( post_mem_write,arg3, sizeof(int));
-      break;
-   case SG_GET_VERSION_NUM:
-      break;
-#       endif
-
-   case VKI_IIOCGETCPS:
-      /* In early 2.4 kernels, ISDN_MAX_CHANNELS was only defined
-       * when KERNEL was. I never saw a larger value than 64 though */
-#              ifndef ISDN_MAX_CHANNELS
-#              define ISDN_MAX_CHANNELS 64
-#              endif
-      if (res == 0)
-	 VG_TRACK( post_mem_write, arg3, ISDN_MAX_CHANNELS 
-		   * 2 * sizeof(unsigned long) );
-      break;
-   case VKI_IIOCNETGPN:
-      if (res == 0)
-	 VG_TRACK( post_mem_write, arg3, sizeof(isdn_net_ioctl_phone) );
-      break;
-
-      /* These all use struct ifreq AFAIK */
-   case SIOCGIFINDEX:
-   case SIOCGIFFLAGS:        /* get flags                    */
-   case SIOCGIFHWADDR:       /* Get hardware address         */
-   case SIOCGIFMTU:          /* get MTU size                 */
-   case SIOCGIFADDR:         /* get PA address               */
-   case SIOCGIFNETMASK:      /* get network PA mask          */
-   case SIOCGIFMETRIC:       /* get metric                   */
-   case SIOCGIFMAP:          /* Get device parameters        */
-   case SIOCGIFTXQLEN:       /* Get the tx queue length      */
-   case SIOCGIFDSTADDR:      /* get remote PA address        */
-   case SIOCGIFBRDADDR:      /* get broadcast PA address     */
-   case SIOCGIFNAME:         /* get iface name               */
-      if (res == 0)
-	 VG_TRACK( post_mem_write,arg3, sizeof(struct ifreq));
-      break;
-   case SIOCGIFCONF:         /* get iface list               */
-      /* WAS:
-	 SYSCALL_TRACK( pre_mem_write,"ioctl(SIOCGIFCONF)", arg3, 
-	 sizeof(struct ifconf));
-	 KERNEL_DO_SYSCALL(tid,res);
-	 if (!VG_(is_kerror)(res) && res == 0)
-	 VG_TRACK( post_mem_write,arg3, sizeof(struct ifconf));
-      */
-      if (res == 0 && arg3 ) {
-	 struct ifconf *ifc = (struct ifconf *) arg3;
-	 if (ifc->ifc_buf != NULL)
-	    VG_TRACK( post_mem_write, (Addr)(ifc->ifc_buf), 
-		      (UInt)(ifc->ifc_len) );
-      }
-      break;
-   case SIOCGSTAMP:
-      if (res == 0)
-	 VG_TRACK( post_mem_write,arg3, sizeof(struct timeval));
-      break;
-      /* SIOCOUTQ is an ioctl that, when called on a socket, returns
-	 the number of bytes currently in that socket's send buffer.
-	 It writes this value as an int to the memory location
-	 indicated by the third argument of ioctl(2). */
-   case SIOCOUTQ:
-      if (res == 0)
-	 VG_TRACK( post_mem_write,arg3, sizeof(int));
-      break;
-   case SIOCGRARP:           /* get RARP table entry         */
-   case SIOCGARP:            /* get ARP table entry          */
-      if (res == 0)
-	 VG_TRACK( post_mem_write,arg3, sizeof(struct arpreq));
-      break;
-                    
-   case SIOCSIFFLAGS:        /* set flags                    */
-   case SIOCSIFMAP:          /* Set device parameters        */
-   case SIOCSIFTXQLEN:       /* Set the tx queue length      */
-   case SIOCSIFDSTADDR:      /* set remote PA address        */
-   case SIOCSIFBRDADDR:      /* set broadcast PA address     */
-   case SIOCSIFNETMASK:      /* set network PA mask          */
-   case SIOCSIFMETRIC:       /* set metric                   */
-   case SIOCSIFADDR:         /* set PA address               */
-   case SIOCSIFMTU:          /* set MTU size                 */
-   case SIOCSIFHWADDR:       /* set hardware address         */
-      break;
-      /* Routing table calls.  */
-   case SIOCADDRT:           /* add routing table entry      */
-   case SIOCDELRT:           /* delete routing table entry   */
-      break;
-
-      /* RARP cache control calls. */
-   case SIOCDRARP:           /* delete RARP table entry      */
-   case SIOCSRARP:           /* set RARP table entry         */
-      /* ARP cache control calls. */
-   case SIOCSARP:            /* set ARP table entry          */
-   case SIOCDARP:            /* delete ARP table entry       */
-      break;
-
-   case SIOCSPGRP:
-      break;
-
-      /* linux/soundcard interface (OSS) */
-   case SNDCTL_SEQ_GETOUTCOUNT:
-   case SNDCTL_SEQ_GETINCOUNT:
-   case SNDCTL_SEQ_PERCMODE:
-   case SNDCTL_SEQ_TESTMIDI:
-   case SNDCTL_SEQ_RESETSAMPLES:
-   case SNDCTL_SEQ_NRSYNTHS:
-   case SNDCTL_SEQ_NRMIDIS:
-   case SNDCTL_SEQ_GETTIME:
-   case SNDCTL_DSP_GETFMTS:
-   case SNDCTL_DSP_GETTRIGGER:
-   case SNDCTL_DSP_GETODELAY:
-#           if defined(SNDCTL_DSP_GETSPDIF)
-   case SNDCTL_DSP_GETSPDIF:
-#           endif
-   case SNDCTL_DSP_GETCAPS:
-   case SOUND_PCM_READ_RATE:
-   case SOUND_PCM_READ_CHANNELS:
-   case SOUND_PCM_READ_BITS:
-   case (SOUND_PCM_READ_BITS|0x40000000): /* what the fuck ? */
-   case SOUND_PCM_READ_FILTER:
-      if (res == 0)
-	 VG_TRACK( post_mem_write,arg3, sizeof(int));
-      break;
-   case SNDCTL_SEQ_CTRLRATE:
-   case SNDCTL_DSP_SPEED:
-   case SNDCTL_DSP_STEREO:
-   case SNDCTL_DSP_GETBLKSIZE: 
-   case SNDCTL_DSP_CHANNELS:
-   case SOUND_PCM_WRITE_FILTER:
-   case SNDCTL_DSP_SUBDIVIDE:
-   case SNDCTL_DSP_SETFRAGMENT:
-#           if defined(SNDCTL_DSP_GETCHANNELMASK)
-   case SNDCTL_DSP_GETCHANNELMASK:
-#           endif
-#           if defined(SNDCTL_DSP_BIND_CHANNEL)
-   case SNDCTL_DSP_BIND_CHANNEL:
-#           endif
-   case SNDCTL_TMR_TIMEBASE:
-   case SNDCTL_TMR_TEMPO:
-   case SNDCTL_TMR_SOURCE:
-   case SNDCTL_MIDI_PRETIME:
-   case SNDCTL_MIDI_MPUMODE:
-      break;
-   case SNDCTL_DSP_GETOSPACE:
-   case SNDCTL_DSP_GETISPACE:
-      if (res == 0)
-	 VG_TRACK( post_mem_write,arg3, sizeof(audio_buf_info));
-      break;
-   case SNDCTL_DSP_SETTRIGGER:
-      break;
-
-   case SNDCTL_DSP_POST:
-   case SNDCTL_DSP_RESET:
-   case SNDCTL_DSP_SYNC:
-   case SNDCTL_DSP_SETSYNCRO:
-   case SNDCTL_DSP_SETDUPLEX:
-      break;
-
-      /* Real Time Clock (/dev/rtc) ioctls */
-#           ifndef GLIBC_2_1
-   case RTC_UIE_ON:
-   case RTC_UIE_OFF:
-   case RTC_AIE_ON:
-   case RTC_AIE_OFF:
-   case RTC_PIE_ON:
-   case RTC_PIE_OFF:
-   case RTC_IRQP_SET:
-      break;
-   case RTC_RD_TIME:
-   case RTC_ALM_READ:
-      if (res == 0)
-	 VG_TRACK( post_mem_write,arg3, sizeof(struct rtc_time));
-      break;
-   case RTC_ALM_SET:
-      break;
-   case RTC_IRQP_READ:
-      if(res == 0)
-	 VG_TRACK( post_mem_write,arg3, sizeof(unsigned long));
-      break;
-#           endif /* GLIBC_2_1 */
-
-#           ifdef BLKGETSIZE
-   case BLKGETSIZE:
-      if (res == 0)
-	 VG_TRACK( post_mem_write,arg3, sizeof(unsigned long));
-      break;
-#           endif /* BLKGETSIZE */
-
-      /* CD ROM stuff (??)  */
-   case CDROMSUBCHNL:
-      if (res == 0)
-	 VG_TRACK( post_mem_write,arg3, sizeof(struct cdrom_subchnl));
-      break;
-   case CDROMREADTOCHDR:
-      if (res == 0)
-	 VG_TRACK( post_mem_write,arg3, sizeof(struct cdrom_tochdr));
-      break;
-   case CDROMREADTOCENTRY:
-      if (res == 0)
-	 VG_TRACK( post_mem_write,arg3, sizeof(struct cdrom_tochdr));
-      break;
-   case CDROMPLAYMSF:
-      break;
-      /* The following two are probably bogus (should check args
-	 for readability).  JRS 20021117 */
-   case CDROM_DRIVE_STATUS: /* 0x5326 */
-   case CDROM_CLEAR_OPTIONS: /* 0x5321 */
-      break;
-
-      /* We don't have any specific information on it, so
-	 try to do something reasonable based on direction and
-	 size bits.  The encoding scheme is described in
-	 /usr/include/asm/ioctl.h.  
-
-	 According to Simon Hausmann, _IOC_READ means the kernel
-	 writes a value to the ioctl value passed from the user
-	 space and the other way around with _IOC_WRITE. */
-   default: {
-      UInt dir  = _IOC_DIR(arg2);
-      UInt size = _IOC_SIZE(arg2);
-      if (size > 0 && (dir & _IOC_READ)
-	  && res == 0
-	  && arg3 != (Addr)NULL)
-	 VG_TRACK( post_mem_write,arg3, size);
-      break;
-   }
-   }
-}
-
-PRE(kill)
-{
-   /* int kill(pid_t pid, int sig); */
-   MAYBE_PRINTF("kill ( %d, %d )\n", arg1,arg2);
-   if (arg2 == VKI_SIGVGINT || arg2 == VKI_SIGVGKILL)
-      res = -VKI_EINVAL;
-}
-
-POST(kill)
-{
-   /* If this was a self-kill then wait for a signal to be
-      delivered to any thread before claiming the kill is done. */
-   if (res >= 0 &&					/* if it was successful */
-       arg2 != 0 &&					/* if a real signal */
-       !VG_(is_sig_ign)(arg2) &&			/* that isn't ignored and */
-       !VG_(ksigismember)(&tst->eff_sig_mask, arg2) &&	/*      we're not blocking it */
-       (arg1 == VG_(getpid)() ||			/* directed at us or */
-	arg1 == -1	      ||			/* directed at everyone or */
-	arg1 == 0	      ||			/* directed at whole group or */
-	-arg1 == VG_(getpgrp)())) {			/* directed at our group... */
-      /* ...then wait for that signal to be delivered to someone
-	 (might be us, might be someone else who doesn't have it
-	 blocked) */
-      VG_(proxy_waitsig)();
-   }
-}
-
-PRE(link)
-{
-   /* int link(const char *oldpath, const char *newpath); */
-   MAYBE_PRINTF("link ( %p, %p)\n", arg1, arg2);
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "link(oldpath)", arg1);
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "link(newpath)", arg2);
-}
-
-PRE(lseek)
-{
-   /* off_t lseek(int fildes, off_t offset, int whence); */
-   MAYBE_PRINTF("lseek ( %d, %d, %d )\n",arg1,arg2,arg3);
-}
-
-PRE(_llseek)
-{
-   /* int _llseek(unsigned int fd, unsigned long offset_high,       
-      unsigned long  offset_low, 
-      loff_t * result, unsigned int whence); */
-   MAYBE_PRINTF("llseek ( %d, 0x%x, 0x%x, %p, %d )\n",
-		arg1,arg2,arg3,arg4,arg5);
-   SYSCALL_TRACK( pre_mem_write, tid, "llseek(result)", arg4, 
-		  sizeof(loff_t));
-}
-
-POST(_llseek)
-{
-   if (res == 0)
-      VG_TRACK( post_mem_write, arg4, sizeof(loff_t) );
-}
-
-PRE(lstat)
-{
-   /* int lstat(const char *file_name, struct stat *buf); */
-   MAYBE_PRINTF("lstat ( %p \"%s\", %p )\n",arg1,arg1,arg2);
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "lstat(file_name)", arg1 );
-   SYSCALL_TRACK( pre_mem_write, tid, "lstat(buf)", arg2, 
-		  sizeof(struct stat) );
-}
-
-POST(lstat)
-{
-   if (res == 0) {
-      VG_TRACK( post_mem_write, arg2, sizeof(struct stat) );
-   }
-}
-
-PRE(lstat64)
-{
-   /* int lstat64(const char *file_name, struct stat64 *buf); */
-   MAYBE_PRINTF("lstat64 ( %p \"%s\", %p )\n",arg1,arg1,arg2);
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "lstat64(file_name)", arg1 );
-   SYSCALL_TRACK( pre_mem_write, tid, "lstat64(buf)", arg2, 
-		  sizeof(struct stat64) );
-}
-
-POST(lstat64)
-{
-   if (res == 0) {
-      VG_TRACK( post_mem_write, arg2, sizeof(struct stat64) );
-   }
-}
-
-PRE(mkdir)
-{
-   /* int mkdir(const char *pathname, mode_t mode); */
-   MAYBE_PRINTF("mkdir ( %p, %d )\n", arg1,arg2);
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "mkdir(pathname)", arg1 );
-}
-
-PRE(mmap2)
-{
-   /* My impression is that this is exactly like __NR_mmap 
-      except that all 6 args are passed in regs, rather than in 
-      a memory-block.
-      
-      Almost.  The big difference is that the file offset is specified
-      in pagesize units rather than bytes, so that it can be used for
-      files bigger than 2^32 bytes. - JSGF
-   */
-   /* void* mmap(void *start, size_t length, int prot, 
-      int flags, int fd, off_t offset); 
-   */
-   MAYBE_PRINTF("mmap2 ( %p, %d, %d, %d, %d, %d )\n",
-		arg1, arg2, arg3, arg4, arg5, arg6 );
-
-   if (arg4 & VKI_MAP_FIXED) {
-      if (!valid_client_addr(arg1, arg2, tid, "mmap2"))
-	 res = -VKI_ENOMEM;
-   } else {
-      arg1 = VG_(find_map_space)(arg1, arg2, True);
-      arg4 |= VKI_MAP_FIXED;
-      if (arg1 == 0)
-	 res = -VKI_ENOMEM;
-   }
-}
-
-POST(mmap2)
-{
-   if (!VG_(is_kerror)(res)) {
-      if (!valid_client_addr(res, arg2, tid, "mmap2")) {
-         VG_(munmap)((void *)res, arg2);
-         res = -VKI_ENOMEM;
-      } else
-         mmap_segment( (Addr)res, arg2, arg3, arg4, arg5, arg6 * (ULong)VKI_BYTES_PER_PAGE );
-   }
-}
-
-PRE(mmap)
-{
-   /* void* mmap(void *start, size_t length, int prot, 
-      int flags, int fd, off_t offset); 
-   */
-
-   UInt* arg_block = (UInt*)arg1;
-   UInt a1, a2, a3, a4, a5, a6;
-
-   SYSCALL_TRACK( pre_mem_read, tid, "mmap(args)", arg1, 6*sizeof(UInt) );
-
-   a1 = arg_block[0];
-   a2 = arg_block[1];
-   a3 = arg_block[2];
-   a4 = arg_block[3];
-   a5 = arg_block[4];
-   a6 = arg_block[5];
-   MAYBE_PRINTF("mmap ( %p, %d, %d, %d, %d, %d )\n",
-		a1, a2, a3, a4, a5, a6 );
-
-   if (a4 & VKI_MAP_FIXED) {
-      if (!valid_client_addr(a1, a2, tid, "mmap")) {
-	 MAYBE_PRINTF("mmap failing: %p-%p\n", a1, a1+a2);
-	 res = -VKI_ENOMEM;
-      }
-   } else {
-      a1 = VG_(find_map_space)(arg_block[0], arg_block[1], True);
-      if (a1 == 0)
-	 res = -VKI_ENOMEM;
-      else
-	 a4 |= VKI_MAP_FIXED;
-   }
-
-   if (res != -VKI_ENOMEM) {
-      UInt new_arg_block[6];
-
-      new_arg_block[0] = a1;
-      new_arg_block[1] = a2;
-      new_arg_block[2] = a3;
-      new_arg_block[3] = a4;
-      new_arg_block[4] = a5;
-      new_arg_block[5] = a6;
-      
-      res = VG_(do_syscall)(__NR_mmap, new_arg_block);
-
-      if (!VG_(is_kerror)(res)) {
-         if (!valid_client_addr(res, a2, tid, "mmap")) {
-	    VG_(munmap)((void *)res, a2);
-	    res = -VKI_ENOMEM;
-         } else
-	    mmap_segment( (Addr)res, a2, a3, a4, a5, a6 );
-      }
-   }
-}
-
-PRE(mprotect)
-{
-   /* int mprotect(const void *addr, size_t len, int prot); */
-   /* should addr .. addr+len-1 be checked before the call? */
-   MAYBE_PRINTF("mprotect ( %p, %d, %d )\n", arg1,arg2,arg3);
-
-   if (!valid_client_addr(arg1, arg2, tid, "mprotect"))
-      res = -VKI_ENOMEM;
-}
-
-POST(mprotect)
-{
-   mprotect_segment( arg1, arg2, arg3 );
-}
-
-PRE(munmap)
-{
-   /* int munmap(void *start, size_t length); */
-   /* should start .. start+length-1 be checked before the call? */
-   MAYBE_PRINTF("munmap ( %p, %d )\n", arg1,arg2);
-
-   if (!valid_client_addr(arg1, arg2, tid, "munmap"))
-      res = -VKI_EINVAL;
-}
-
-POST(munmap)
-{
-   munmap_segment( arg1, arg2 );
-}
-
-PRE(mincore)
-{
-   /* int mincore(void *start, size_t length, unsigned char *vec); */
-   MAYBE_PRINTF("mincore ( %p, %d, %p )\n", arg1,arg2,arg3);
-   SYSCALL_TRACK(pre_mem_write, tid, "mincore(vec)",
-                 arg3, (arg2 + 4096 - 1) / 4096);
-}
-
-POST(mincore)
-{
-   if (!VG_(is_kerror)(res))
-      VG_TRACK( post_mem_write, arg3, (arg2 + 4096 - 1) / 4096 );  
-}
-
-PRE(nanosleep)
-{
-         /* int nanosleep(const struct timespec *req, struct timespec *rem); */
-         MAYBE_PRINTF("nanosleep ( %p, %p )\n", arg1,arg2);
-         SYSCALL_TRACK( pre_mem_read, tid, "nanosleep(req)", arg1, 
-                                              sizeof(struct timespec) );
-         if (arg2 != (UInt)NULL)
-            SYSCALL_TRACK( pre_mem_write, tid, "nanosleep(rem)", arg2, 
-			   sizeof(struct timespec) );
-}
-
-POST(nanosleep)
-{
-   /* Somewhat bogus ... is only written by the kernel if
-      res == -1 && errno == EINTR. */
-   if (arg2 != (UInt)NULL)
-      VG_TRACK( post_mem_write, arg2, sizeof(struct timespec) );
-}
-
-PRE(_newselect)
-{
-   /* int select(int n,  
-		 fd_set *readfds, fd_set *writefds, fd_set *exceptfds, 
-		 struct timeval *timeout);
-   */
-   MAYBE_PRINTF("newselect ( %d, %p, %p, %p, %p )\n",
-		arg1,arg2,arg3,arg4,arg5);
-   if (arg2 != 0)
-      SYSCALL_TRACK( pre_mem_read, tid, "newselect(readfds)",   
-		     arg2, arg1/8 /* __FD_SETSIZE/8 */ );
-   if (arg3 != 0)
-      SYSCALL_TRACK( pre_mem_read, tid, "newselect(writefds)",  
-		     arg3, arg1/8 /* __FD_SETSIZE/8 */ );
-   if (arg4 != 0)
-      SYSCALL_TRACK( pre_mem_read, tid, "newselect(exceptfds)", 
-		     arg4, arg1/8 /* __FD_SETSIZE/8 */ );
-   if (arg5 != 0)
-      SYSCALL_TRACK( pre_mem_read, tid, "newselect(timeout)", arg5, 
-		     sizeof(struct timeval) );
-}
-
-PRE(open)
-{
-   /* int open(const char *pathname, int flags); */
-   MAYBE_PRINTF("open ( %p(%s), %d ) --> ",arg1,arg1,arg2);
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "open(pathname)", arg1 );
-}
-
-POST(open)
-{
-   if (!fd_allowed(res, "open", tid)) {
-      VG_(close)(res);
-      res = -VKI_EMFILE;
-   } else {
-      if(VG_(clo_track_fds))
-         record_fd_open(tid, res, VG_(arena_strdup)(VG_AR_CORE, (Char*)arg1));
-   }
-   MAYBE_PRINTF("%d\n",res);
-}
-
-PRE(read)
-{
-   /* size_t read(int fd, void *buf, size_t count); */
-   MAYBE_PRINTF("read ( %d, %p, %d )\n", arg1, arg2, arg3);
-
-   if (!fd_allowed(arg1, "read", tid))
-      res = -VKI_EBADF;   
-}
-
-POST(read)
-{
-   if (res > 0)
-      VG_TRACK(post_mem_write, arg2, res);
-}
-
-PRE(write)
-{
-   /* size_t write(int fd, const void *buf, size_t count); */
-   MAYBE_PRINTF("write ( %d, %p, %d )\n", arg1, arg2, arg3);
-   if (!fd_allowed(arg1, "write", tid))
-      res = -VKI_EBADF;
-   else
-      SYSCALL_TRACK( pre_mem_read, tid, "write(buf)", arg2, arg3 );
-}
-
-PRE(creat)
-{
-   /* int creat(const char *pathname, mode_t mode); */
-   MAYBE_PRINTF("creat ( %p(%s), %d ) --> ",arg1,arg1,arg2);
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "creat(pathname)", arg1 );
-}
-
-POST(creat)
-{
-   if (!fd_allowed(res, "creat", tid)) {
-      VG_(close)(res);
-      res = -VKI_EMFILE;
-   } else {
-      if(VG_(clo_track_fds))
-         record_fd_open(tid, res, VG_(arena_strdup)(VG_AR_CORE, (Char*)arg1));
-   }
-   MAYBE_PRINTF("%d\n",res);
-}
-
-PRE(pipe)
-{
-   /* int pipe(int filedes[2]); */
-   MAYBE_PRINTF("pipe ( %p ) ...\n", arg1);
-   SYSCALL_TRACK( pre_mem_write, tid, "pipe(filedes)", 
-		  arg1, 2*sizeof(int) );
-}
-
-POST(pipe)
-{
-   Int *p = (Int *)arg1;
-
-   if (!fd_allowed(p[0], "pipe", tid) ||
-       !fd_allowed(p[1], "pipe", tid)) {
-      VG_(close)(p[0]);
-      VG_(close)(p[1]);
-      res = -VKI_EMFILE;
-   } else {
-      VG_TRACK( post_mem_write, arg1, 2*sizeof(int) );
-      if(VG_(clo_track_fds)) {
-         record_fd_open(tid, p[0], NULL);
-         record_fd_open(tid, p[1], NULL);
-      }
-   }
-
-   MAYBE_PRINTF("SYSCALL[%d]       pipe --> %d (rd %d, wr %d)\n", 
-		VG_(getpid)(), res,
-		((UInt*)arg1)[0], ((UInt*)arg1)[1] );
-}
-
-PRE(poll)
-{
-   /* struct pollfd {
-	int fd;           -- file descriptor
-	short events;     -- requested events
-	short revents;    -- returned events
-      };
-      int poll(struct pollfd *ufds, unsigned int nfds, 
-      int timeout) 
-   */
-   MAYBE_PRINTF("poll ( %p, %d, %d )\n",arg1,arg2,arg3);
-   /* In fact some parts of this struct should be readable too.
-      This should be fixed properly. */
-   SYSCALL_TRACK( pre_mem_write, tid, "poll(ufds)", 
-		  arg1, arg2 * sizeof(struct pollfd) );
-}
-
-POST(poll)
-{
-   if (res > 0) {
-      UInt i;
-      struct pollfd * arr = (struct pollfd *)arg1;
-      for (i = 0; i < arg2; i++)
-	 VG_TRACK( post_mem_write, (Addr)(&arr[i].revents), 
-		   sizeof(Short) );
-   }
-}
-
-PRE(readlink)
-{
-   /* int readlink(const char *path, char *buf, size_t bufsiz); */
-   MAYBE_PRINTF("readlink ( %p, %p, %d )\n", arg1,arg2,arg3);
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "readlink(path)", arg1 );
-   SYSCALL_TRACK( pre_mem_write, tid, "readlink(buf)", arg2,arg3 );
-}
-
-POST(readlink)
-{
-   VG_TRACK( post_mem_write, arg2, res );
-}
-
-PRE(readv)
-{
-   /* int readv(int fd, const struct iovec * vector, size_t count); */
-   Int i;
-   struct iovec * vec;
-   MAYBE_PRINTF("readv ( %d, %p, %d )\n",arg1,arg2,arg3);
-   if (!fd_allowed(arg1, "readv", tid)) {
-      res = -VKI_EBADF;
-   } else {
-      SYSCALL_TRACK( pre_mem_read, tid, "readv(vector)", 
-		     arg2, arg3 * sizeof(struct iovec) );
-      /* ToDo: don't do any of the following if the vector is invalid */
-      vec = (struct iovec *)arg2;
-      for (i = 0; i < (Int)arg3; i++)
-	 SYSCALL_TRACK( pre_mem_write, tid, "readv(vector[...])",
-			(UInt)vec[i].iov_base,vec[i].iov_len );
-   }
-}
-
-POST(readv)
-{
-   if (res > 0) {
-      Int i;
-      struct iovec * vec = (struct iovec *)arg2;
-      Int remains = res;
-
-      /* res holds the number of bytes read. */
-      for (i = 0; i < (Int)arg3; i++) {
-	 Int nReadThisBuf = vec[i].iov_len;
-	 if (nReadThisBuf > remains) nReadThisBuf = remains;
-	 VG_TRACK( post_mem_write, (UInt)vec[i].iov_base, nReadThisBuf );
-	 remains -= nReadThisBuf;
-	 if (remains < 0) VG_(core_panic)("readv: remains < 0");
-      }
-   }
-}
-
-PRE(rename)
-{
-   /* int rename(const char *oldpath, const char *newpath); */
-   MAYBE_PRINTF("rename ( %p, %p )\n", arg1, arg2 );
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "rename(oldpath)", arg1 );
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "rename(newpath)", arg2 );
-}
-
-PRE(rmdir)
-{
-   /* int rmdir(const char *pathname); */
-   MAYBE_PRINTF("rmdir ( %p )\n", arg1);
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "rmdir(pathname)", arg1 );
-}
-
-PRE(sched_setparam)
-{
-   /* int sched_setparam(pid_t pid, const struct sched_param *p); */
-   MAYBE_PRINTF("sched_setparam ( %d, %p )\n", arg1, arg2 );
-   SYSCALL_TRACK( pre_mem_read, tid, "sched_setparam(ptr)",
-		  arg2, sizeof(struct sched_param) );
-}
-
-POST(sched_setparam)
-{
-   VG_TRACK( post_mem_write, arg2, sizeof(struct sched_param) );
-}
-
-PRE(sched_getparam)
-{
-   /* int sched_getparam(pid_t pid, struct sched_param *p); */
-   MAYBE_PRINTF("sched_getparam ( %d, %p )\n", arg1, arg2 );
-   SYSCALL_TRACK( pre_mem_write, tid, "sched_getparam(ptr)",
-		  arg2, sizeof(struct sched_param) );
-}
-
-POST(sched_getparam)
-{
-   VG_TRACK( post_mem_write, arg2, sizeof(struct sched_param) );
-}
-
-PRE(sched_yield)
-{
-   /* int sched_yield(void); */
-   MAYBE_PRINTF("sched_yield ()\n" );
-}
-
-PRE(select)
-{
-   /* struct sel_arg_struct {
-      unsigned long n;
-      fd_set *inp, *outp, *exp;
-      struct timeval *tvp;
-      };
-      int old_select(struct sel_arg_struct *arg);
-   */
-   SYSCALL_TRACK( pre_mem_read, tid, "select(args)", arg1, 5*sizeof(UInt) );
-
-   {
-      UInt* arg_struct = (UInt*)arg1;
-      UInt a1, a2, a3, a4, a5;
-
-      a1 = arg_struct[0];
-      a2 = arg_struct[1];
-      a3 = arg_struct[2];
-      a4 = arg_struct[3];
-      a5 = arg_struct[4];
-
-      MAYBE_PRINTF("select ( %d, %p, %p, %p, %p )\n", 
-		   a1,a2,a3,a4,a5);
-      if (a2 != (Addr)NULL)
-	 SYSCALL_TRACK( pre_mem_read, tid, "select(readfds)", a2, 
-			a1/8 /* __FD_SETSIZE/8 */ );
-      if (a3 != (Addr)NULL)
-	 SYSCALL_TRACK( pre_mem_read, tid, "select(writefds)", a3, 
-			arg1/8 /* __FD_SETSIZE/8 */ );
-      if (a4 != (Addr)NULL)
-	 SYSCALL_TRACK( pre_mem_read, tid, "select(exceptfds)", a4, 
-			a1/8 /* __FD_SETSIZE/8 */ );
-      if (a5 != (Addr)NULL)
-	 SYSCALL_TRACK( pre_mem_read, tid, "select(timeout)", a5, 
-			sizeof(struct timeval) );
-   }
-}
-
-PRE(setitimer)
-{
-         /* setitimer(int which, const struct itimerval *value,
-                                 struct itimerval *ovalue); */
-         MAYBE_PRINTF("setitimer ( %d, %p, %p )\n", arg1,arg2,arg3);
-         if (arg2 != (Addr)NULL)
-            SYSCALL_TRACK( pre_mem_read,tid, "setitimer(value)", 
-                             arg2, sizeof(struct itimerval) );
-         if (arg3 != (Addr)NULL)
-            SYSCALL_TRACK( pre_mem_write,tid, "setitimer(ovalue)", 
-                             arg3, sizeof(struct itimerval));
-}
-
-POST(setitimer)
-{
-   if (arg3 != (Addr)NULL) {
-      VG_TRACK( post_mem_write,arg3, sizeof(struct itimerval));
-   }
-}
-
-PRE(setfsgid32)
-{
-   /* int setfsgid(uid_t fsgid); */
-   MAYBE_PRINTF("setfsgid ( %d )\n", arg1);
-}
-
-PRE(setgid)
-{
-   /* int setgid(gid_t gid); */
-   MAYBE_PRINTF("setgid ( %d )\n", arg1);
-}
-
-PREALIAS(setgid32, setgid);
-
-PRE(setsid)
-{
-   /* pid_t setsid(void); */
-   MAYBE_PRINTF("setsid ()\n");
-}
-
-PRE(setgroups)
-{
-   /* int setgroups(size_t size, const gid_t *list); */
-   MAYBE_PRINTF("setgroups ( %d, %p )\n", arg1, arg2);
-   if (arg1 > 0)
-      SYSCALL_TRACK( pre_mem_read, tid, "setgroups(list)", arg2, 
-		     arg1 * sizeof(gid_t) );
-}
-
-PREALIAS(setgroups32, setgroups);
-
-PRE(setpgid)
-{
-   /* int setpgid(pid_t pid, pid_t pgid); */
-   MAYBE_PRINTF("setpgid ( %d, %d )\n", arg1, arg2);
-}
-
-POST(setpgid)
-{
-   VG_(main_pgrp) = VG_(getpgrp)();
-}
-
-PRE(setregid32)
-{
-   /* int setregid(gid_t rgid, gid_t egid); */
-   MAYBE_PRINTF("setregid32(?) ( %d, %d )\n", arg1, arg2);
-}
-
-PRE(setresuid32)
-{
-   /* int setresuid(uid_t ruid, uid_t euid, uid_t suid); */
-   MAYBE_PRINTF("setresuid32(?) ( %d, %d, %d )\n", arg1, arg2, arg3);
-}
-
-PRE(setreuid)
-{
-   /* int setreuid(uid_t ruid, uid_t euid); */
-   MAYBE_PRINTF("setreuid ( 0x%x, 0x%x )\n", arg1, arg2);
-}
-
-PREALIAS(setreuid32, setreuid);
-
-PRE(setrlimit)
-{
-   /* int setrlimit (int resource, const struct rlimit *rlim); */
-   MAYBE_PRINTF("setrlimit ( %d, %p )\n", arg1,arg2);
-   SYSCALL_TRACK( pre_mem_read, tid, "setrlimit(rlim)", 
-		  arg2, sizeof(struct rlimit) );
-}
-
-PRE(setuid)
-{
-   /* int setuid(uid_t uid); */
-   MAYBE_PRINTF("setuid ( %d )\n", arg1);
-}
-
-PREALIAS(setuid32, setuid);
-
-PRE(socketcall)
-{
-   /* int socketcall(int call, unsigned long *args); */
-   MAYBE_PRINTF("socketcall ( %d, %p )\n",arg1,arg2);
-   switch (arg1 /* request */) {
-
-   case SYS_SOCKETPAIR:
-      /* int socketpair(int d, int type, int protocol, int sv[2]); */
-      SYSCALL_TRACK( pre_mem_read, tid, "socketcall.socketpair(args)", 
-		     arg2, 4*sizeof(Addr) );
-      SYSCALL_TRACK( pre_mem_write, tid, "socketcall.socketpair(sv)", 
-		     ((UInt*)arg2)[3], 2*sizeof(int) );
-      break;
-
-   case SYS_SOCKET:
-      /* int socket(int domain, int type, int protocol); */
-      SYSCALL_TRACK( pre_mem_read, tid, "socketcall.socket(args)", 
-		     arg2, 3*sizeof(Addr) );
-      break;
-
-   case SYS_BIND:
-      /* int bind(int sockfd, struct sockaddr *my_addr, 
-	 int addrlen); */
-      SYSCALL_TRACK( pre_mem_read, tid, "socketcall.bind(args)", 
-		     arg2, 3*sizeof(Addr) );
-      pre_mem_read_sockaddr( tid, "socketcall.bind(my_addr.%s)",
-			     (struct sockaddr *) (((UInt*)arg2)[1]), ((UInt*)arg2)[2]);
-      break;
-               
-   case SYS_LISTEN:
-      /* int listen(int s, int backlog); */
-      SYSCALL_TRACK( pre_mem_read, tid, "socketcall.listen(args)", 
-		     arg2, 2*sizeof(Addr) );
-      break;
-
-   case SYS_ACCEPT: {
-      /* int accept(int s, struct sockaddr *addr, int *addrlen); */
-      SYSCALL_TRACK( pre_mem_read, tid, "socketcall.accept(args)", 
-		     arg2, 3*sizeof(Addr) );
-      {
-	 Addr addr_p     = ((UInt*)arg2)[1];
-	 Addr addrlen_p  = ((UInt*)arg2)[2];
-	 if (addr_p != (Addr)NULL) 
-	    buf_and_len_pre_check ( tid, addr_p, addrlen_p,
-				    "socketcall.accept(addr)",
-				    "socketcall.accept(addrlen_in)" );
-      }
-      break;
-   }
-
-   case SYS_SENDTO:
-      /* int sendto(int s, const void *msg, int len, 
-	 unsigned int flags, 
-	 const struct sockaddr *to, int tolen); */
-      SYSCALL_TRACK( pre_mem_read, tid, "socketcall.sendto(args)", arg2, 
-		     6*sizeof(Addr) );
-      SYSCALL_TRACK( pre_mem_read, tid, "socketcall.sendto(msg)",
-		     ((UInt*)arg2)[1], /* msg */
-		     ((UInt*)arg2)[2]  /* len */ );
-      pre_mem_read_sockaddr( tid, "socketcall.sendto(to.%s)",
-			     (struct sockaddr *) (((UInt*)arg2)[4]), ((UInt*)arg2)[5]);
-      break;
-
-   case SYS_SEND:
-      /* int send(int s, const void *msg, size_t len, int flags); */
-      SYSCALL_TRACK( pre_mem_read, tid, "socketcall.send(args)", arg2,
-		     4*sizeof(Addr) );
-      SYSCALL_TRACK( pre_mem_read, tid, "socketcall.send(msg)",
-		     ((UInt*)arg2)[1], /* msg */
-		     ((UInt*)arg2)[2]  /* len */ );
-      break;
-
-   case SYS_RECVFROM:
-      /* int recvfrom(int s, void *buf, int len, unsigned int flags,
-	 struct sockaddr *from, int *fromlen); */
-      SYSCALL_TRACK( pre_mem_read, tid, "socketcall.recvfrom(args)", 
-		     arg2, 6*sizeof(Addr) );
-      {
-	 Addr buf_p      = ((UInt*)arg2)[1];
-	 Int  len        = ((UInt*)arg2)[2];
-	 Addr from_p     = ((UInt*)arg2)[4];
-	 Addr fromlen_p  = ((UInt*)arg2)[5];
-
-	 SYSCALL_TRACK( pre_mem_write, tid, "socketcall.recvfrom(buf)", 
-			buf_p, len );
-	 if (from_p != (Addr)NULL) 
-	    buf_and_len_pre_check ( tid, from_p, fromlen_p, 
-				    "socketcall.recvfrom(from)",
-				    "socketcall.recvfrom(fromlen_in)" );
-      }
-      break;
-   
-   case SYS_RECV:
-      /* int recv(int s, void *buf, int len, unsigned int flags); */
-      /* man 2 recv says:
-	 The  recv call is normally used only on a connected socket
-	 (see connect(2)) and is identical to recvfrom with a  NULL
-	 from parameter.
-      */
-      SYSCALL_TRACK( pre_mem_read, tid, "socketcall.recv(args)", 
-		     arg2, 4*sizeof(Addr) );
-      SYSCALL_TRACK( pre_mem_write, tid, "socketcall.recv(buf)", 
-		     ((UInt*)arg2)[1], /* buf */
-		     ((UInt*)arg2)[2]  /* len */ );
-      break;
-
-   case SYS_CONNECT:
-      /* int connect(int sockfd, 
-	 struct sockaddr *serv_addr, int addrlen ); */
-      SYSCALL_TRACK( pre_mem_read, tid, "socketcall.connect(args)", 
-		     arg2, 3*sizeof(Addr) );
-      SYSCALL_TRACK( pre_mem_read, tid, 
-		     "socketcall.connect(serv_addr.sa_family)",
-		     ((UInt*)arg2)[1], /* serv_addr */
-		     sizeof (sa_family_t));
-      pre_mem_read_sockaddr( tid,
-			     "socketcall.connect(serv_addr.%s)",
-			     (struct sockaddr *) (((UInt*)arg2)[1]), ((UInt*)arg2)[2]);
-      break;
-
-   case SYS_SETSOCKOPT:
-      /* int setsockopt(int s, int level, int optname, 
-	 const void *optval, int optlen); */
-      SYSCALL_TRACK( pre_mem_read, tid, "socketcall.setsockopt(args)", 
-		     arg2, 5*sizeof(Addr) );
-      SYSCALL_TRACK( pre_mem_read, tid, "socketcall.setsockopt(optval)",
-		     ((UInt*)arg2)[3], /* optval */
-		     ((UInt*)arg2)[4]  /* optlen */ );
-      break;
-
-   case SYS_GETSOCKOPT:
-      /* int setsockopt(int s, int level, int optname, 
-	 void *optval, socklen_t *optlen); */
-      SYSCALL_TRACK( pre_mem_read, tid, "socketcall.getsockopt(args)", 
-		     arg2, 5*sizeof(Addr) );
-      {
-	 Addr optval_p  = ((UInt*)arg2)[3];
-	 Addr optlen_p  = ((UInt*)arg2)[4];
-	 /* vg_assert(sizeof(socklen_t) == sizeof(UInt)); */
-	 if (optval_p != (Addr)NULL) 
-	    buf_and_len_pre_check ( tid, optval_p, optlen_p,
-				    "socketcall.getsockopt(optval)",
-				    "socketcall.getsockopt(optlen)" );
-      }
-      break;
-
-   case SYS_GETSOCKNAME:
-      /* int getsockname(int s, struct sockaddr* name, int* namelen) */
-      SYSCALL_TRACK( pre_mem_read, tid, "socketcall.getsockname(args)",
-		     arg2, 3*sizeof(Addr) );
-      {
-	 Addr name_p     = ((UInt*)arg2)[1];
-	 Addr namelen_p  = ((UInt*)arg2)[2];
-
-	 /* Nb: name_p cannot be NULL */
-	 buf_and_len_pre_check ( tid, name_p, namelen_p,
-				 "socketcall.getsockname(name)",
-				 "socketcall.getsockname(namelen_in)" );
-      }
-      break;
-
-   case SYS_GETPEERNAME:
-      /* int getpeername(int s, struct sockaddr* name, int* namelen) */
-      SYSCALL_TRACK( pre_mem_read, tid, "socketcall.getpeername(args)",
-		     arg2, 3*sizeof(Addr) );
-      {
-	 Addr name_p     = ((UInt*)arg2)[1];
-	 Addr namelen_p  = ((UInt*)arg2)[2];
-
-	 /* Nb: name_p cannot be NULL */
-	 buf_and_len_pre_check ( tid, name_p, namelen_p,
-				 "socketcall.getpeername(name)",
-				 "socketcall.getpeername(namelen_in)" );
-      }
-      break;
-
-   case SYS_SHUTDOWN:
-      /* int shutdown(int s, int how); */
-      SYSCALL_TRACK( pre_mem_read, tid, "socketcall.shutdown(args)", 
-		     arg2, 2*sizeof(Addr) );
-      break;
-
-   case SYS_SENDMSG: {
-      /* int sendmsg(int s, const struct msghdr *msg, int flags); */
-
-      /* this causes warnings, and I don't get why. glibc bug?
-       * (after all it's glibc providing the arguments array)
-       SYSCALL_TRACK( pre_mem_read, "socketcall.sendmsg(args)", 
-       arg2, 3*sizeof(Addr) );
-      */
-
-      struct msghdr *msg = (struct msghdr *)((UInt *)arg2)[ 1 ];
-      msghdr_foreachfield ( tid, msg, pre_mem_read_sendmsg );
-
-      break;
-   }
-      
-   case SYS_RECVMSG: {
-      /* int recvmsg(int s, struct msghdr *msg, int flags); */
-
-      /* this causes warnings, and I don't get why. glibc bug?
-       * (after all it's glibc providing the arguments array)
-       SYSCALL_TRACK( pre_mem_read, "socketcall.recvmsg(args)", 
-       arg2, 3*sizeof(Addr) );
-      */
-
-      struct msghdr *msg = (struct msghdr *)((UInt *)arg2)[ 1 ];
-      msghdr_foreachfield ( tid, msg, pre_mem_write_recvmsg );
-
-      break;
-   }
-
-   default:
-      VG_(message)(Vg_DebugMsg,"Warning: unhandled socketcall 0x%x",arg1);
-      res = -VKI_EINVAL;
-      break;
-   }
-}
-
-POST(socketcall)
-{
-   /* int socketcall(int call, unsigned long *args); */
-   MAYBE_PRINTF("socketcall ( %d, %p )\n",arg1,arg2);
-
-   switch (arg1 /* request */) {
-
-   case SYS_SOCKETPAIR:
-      /* XXX TODO: check return fd against VG_(max_fd) */
-      VG_TRACK( post_mem_write, ((UInt*)arg2)[3], 2*sizeof(int) );
-      if(VG_(clo_track_fds)) {
-         record_fd_open(tid, ((UInt*)((UInt*)arg2)[3])[0], NULL);
-         record_fd_open(tid, ((UInt*)((UInt*)arg2)[3])[1], NULL);
-      }
-      break;
-
-   case SYS_SOCKET:
-      if (!fd_allowed(res, "socket", tid)) {
-	 VG_(close)(res);
-	 res = -VKI_EMFILE;
-      } else {
-         if(VG_(clo_track_fds))
-            record_fd_open(tid, res, NULL);
-      }
-      break;
-
-   case SYS_BIND:
-      /* int bind(int sockfd, struct sockaddr *my_addr, 
-			int addrlen); */
-      break;
-               
-   case SYS_LISTEN:
-      /* int listen(int s, int backlog); */
-      break;
-
-   case SYS_ACCEPT: {
-      /* int accept(int s, struct sockaddr *addr, int *addrlen); */
-      if (!fd_allowed(res, "accept", tid)) {
-	 VG_(close)(res);
-	 res = -VKI_EMFILE;
-      } else {
-	 Addr addr_p     = ((UInt*)arg2)[1];
-	 Addr addrlen_p  = ((UInt*)arg2)[2];
-
-	 if (addr_p != (Addr)NULL) 
-	    buf_and_len_post_check ( tid, res, addr_p, addrlen_p,
-				     "socketcall.accept(addrlen_out)" );
-         if(VG_(clo_track_fds))
-            record_fd_open(tid, res, NULL);
-      }
-      break;
-   }
-
-   case SYS_SENDTO:
-      break;
-
-   case SYS_SEND:
-      break;
-
-   case SYS_RECVFROM:
-      {
-	 Addr buf_p      = ((UInt*)arg2)[1];
-	 Int  len        = ((UInt*)arg2)[2];
-	 Addr from_p     = ((UInt*)arg2)[4];
-	 Addr fromlen_p  = ((UInt*)arg2)[5];
-
-	 if (from_p != (Addr)NULL) 
-	    buf_and_len_post_check ( tid, res, from_p, fromlen_p,
-				     "socketcall.recvfrom(fromlen_out)" );
-	 VG_TRACK( post_mem_write, buf_p, len );
-      }
-      break;
-
-   case SYS_RECV:
-      if (res >= 0 
-	  && ((UInt*)arg2)[1] != (UInt)NULL) {
-	 VG_TRACK( post_mem_write, ((UInt*)arg2)[1], /* buf */
-		   ((UInt*)arg2)[2]  /* len */ );
-      }
-      break;
-
-   case SYS_CONNECT:
-      break;
-
-   case SYS_SETSOCKOPT:
-      break;
-
-   case SYS_GETSOCKOPT:
-      {
-	 Addr optval_p  = ((UInt*)arg2)[3];
-	 Addr optlen_p  = ((UInt*)arg2)[4];
-
-	 if (optval_p != (Addr)NULL) 
-	    buf_and_len_post_check ( tid, res, optval_p, optlen_p,
-				     "socketcall.getsockopt(optlen_out)" );
-      }
-      break;
-
-   case SYS_GETSOCKNAME:
-      {
-	 Addr name_p     = ((UInt*)arg2)[1];
-	 Addr namelen_p  = ((UInt*)arg2)[2];
-
-	 buf_and_len_post_check ( tid, res, name_p, namelen_p,
-				  "socketcall.getsockname(namelen_out)" );
-      }
-      break;
-
-   case SYS_GETPEERNAME:
-      {
-	 Addr name_p     = ((UInt*)arg2)[1];
-	 Addr namelen_p  = ((UInt*)arg2)[2];
-
-	 buf_and_len_post_check ( tid, res, name_p, namelen_p,
-				  "socketcall.getpeername(namelen_out)" );
-      }
-      break;
-
-   case SYS_SHUTDOWN:
-      break;
-
-   case SYS_SENDMSG:
-      break;
-
-   case SYS_RECVMSG:
-   {
-      struct msghdr *msg = (struct msghdr *)((UInt *)arg2)[ 1 ];
-
-      msghdr_foreachfield( tid, msg, post_mem_write_recvmsg );
-      check_cmsg_for_fds( tid, msg );
-
-      break;
-   }
-
-   default:
-      VG_(message)(Vg_DebugMsg,"FATAL: unhandled socketcall 0x%x",arg1);
-      VG_(core_panic)("... bye!\n");
-      break; /*NOTREACHED*/
-   }
-}
-
-PRE(stat)
-{
-   /* int stat(const char *file_name, struct stat *buf); */
-   MAYBE_PRINTF("stat ( %p, %p )\n",arg1,arg2);
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "stat(file_name)", arg1 );
-   SYSCALL_TRACK( pre_mem_write, tid, "stat(buf)", 
-		  arg2, sizeof(struct stat) );
-}
-
-POST(stat)
-{
-   VG_TRACK( post_mem_write, arg2, sizeof(struct stat) );
-}
-
-PRE(statfs)
-{
-   /* int statfs(const char *path, struct statfs *buf); */
-   MAYBE_PRINTF("statfs ( %p, %p )\n",arg1,arg2);
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "statfs(path)", arg1 );
-   SYSCALL_TRACK( pre_mem_write, tid, "statfs(buf)", 
-		  arg2, sizeof(struct statfs) );
-}
-
-POST(statfs)
-{
-   VG_TRACK( post_mem_write, arg2, sizeof(struct statfs) );
-}
-
-PRE(statfs64)
-{
-   /* int statfs64(const char *path, struct statfs *buf); */
-   MAYBE_PRINTF("statfs64 ( %p, %p )\n",arg1,arg2);
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "statfs64(path)", arg1 );
-   SYSCALL_TRACK( pre_mem_write, tid, "statfs64(buf)", 
-		  arg2, sizeof(struct statfs64) );
-}
-
-POST(statfs64)
-{
-   VG_TRACK( post_mem_write, arg2, sizeof(struct statfs64) );
-}
-
-PRE(symlink)
-{
-   /* int symlink(const char *oldpath, const char *newpath); */
-   MAYBE_PRINTF("symlink ( %p, %p )\n",arg1,arg2);
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "symlink(oldpath)", arg1 );
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "symlink(newpath)", arg2 );
-}
-
-PRE(stat64)
-{
-   /* int stat64(const char *file_name, struct stat64 *buf); */
-   MAYBE_PRINTF("stat64 ( %p, %p )\n",arg1,arg2);
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "stat64(file_name)", arg1 );
-   SYSCALL_TRACK( pre_mem_write, tid, "stat64(buf)", 
-		  arg2, sizeof(struct stat64) );
-}
-
-POST(stat64)
-{
-   VG_TRACK( post_mem_write, arg2, sizeof(struct stat64) );
-}
-
-PRE(fstat64)
-{
-   /* int fstat64(int filedes, struct stat64 *buf); */
-   MAYBE_PRINTF("fstat64 ( %d, %p )\n",arg1,arg2);
-   SYSCALL_TRACK( pre_mem_write, tid, "fstat64(buf)", 
-		  arg2, sizeof(struct stat64) );
-}
-
-POST(fstat64)
-{
-   VG_TRACK( post_mem_write, arg2, sizeof(struct stat64) );
-}
-
-PRE(sysinfo)
-{
-   /* int sysinfo(struct sysinfo *info); */
-   MAYBE_PRINTF("sysinfo ( %p )\n",arg1);
-   SYSCALL_TRACK( pre_mem_write, tid, "sysinfo(info)", 
-		  arg1, sizeof(struct sysinfo) );
-}
-
-POST(sysinfo)
-{
-   VG_TRACK( post_mem_write, arg1, sizeof(struct sysinfo) );
-}
-
-PRE(time)
-{
-   /* time_t time(time_t *t); */
-   MAYBE_PRINTF("time ( %p )\n",arg1);
-   if (arg1 != (UInt)NULL) {
-      SYSCALL_TRACK( pre_mem_write, tid, "time", arg1, sizeof(time_t) );
-   }
-}
-
-POST(time)
-{
-   if (arg1 != (UInt)NULL) {
-      VG_TRACK( post_mem_write, arg1, sizeof(time_t) );
-   }
-}
-
-PRE(times)
-{
-   /* clock_t times(struct tms *buf); */
-   MAYBE_PRINTF("times ( %p )\n",arg1);
-   SYSCALL_TRACK( pre_mem_write, tid, "times(buf)", 
-		  arg1, sizeof(struct tms) );
-}
-
-POST(times)
-{
-   if (arg1 != (UInt)NULL) {
-      VG_TRACK( post_mem_write, arg1, sizeof(struct tms) );
-   }
-}
-
-PRE(truncate)
-{
-   /* int truncate(const char *path, size_t length); */
-   MAYBE_PRINTF("truncate ( %p \"%s\", %d )\n", arg1,arg1,arg2);
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "truncate(path)", arg1 );
-}
-
-PRE(umask)
-{
-   /* mode_t umask(mode_t mask); */
-   MAYBE_PRINTF("umask ( %d )\n", arg1);
-}
-
-PRE(unlink)
-{
-   /* int unlink(const char *pathname) */
-   MAYBE_PRINTF("unlink ( %p \"%s\" )\n",arg1, arg1);
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "unlink(pathname)", arg1 );
-}
-
-PRE(uname)
-{
-   /* int uname(struct utsname *buf); */
-   MAYBE_PRINTF("uname ( %p )\n",arg1);
-   SYSCALL_TRACK( pre_mem_write, tid, "uname(buf)", 
-		  arg1, sizeof(struct utsname) );
-}
-
-POST(uname)
-{
-   if (arg1 != (UInt)NULL) {
-      VG_TRACK( post_mem_write, arg1, sizeof(struct utsname) );
-   }
-}
-
-PRE(utime)
-{
-   /* int utime(const char *filename, struct utimbuf *buf); */
-   MAYBE_PRINTF("utime ( %p, %p )\n", arg1,arg2);
-   SYSCALL_TRACK( pre_mem_read_asciiz, tid, "utime(filename)", arg1 );
-   if (arg2 != (UInt)NULL)
-      SYSCALL_TRACK( pre_mem_read, tid, "utime(buf)", arg2, 
-		     sizeof(struct utimbuf) );
-}
-
-PRE(waitpid)
-{
-   /* pid_t waitpid(pid_t pid, int *status, int options); */
-
-   MAYBE_PRINTF("waitpid ( %d, %p, %d )\n",
-                arg1,arg2,arg3);
-   if (arg2 != (Addr)NULL)
-      SYSCALL_TRACK( pre_mem_write, tid, "waitpid(status)",
-                     arg2, sizeof(int) );
-}
-
-POST(waitpid)
-{
-   if (arg2 != (Addr)NULL)
-      VG_TRACK( post_mem_write, arg2, sizeof(int) );
-}
-
-PRE(wait4)
-{
-   /* pid_t wait4(pid_t pid, int *status, int options,
-      struct rusage *rusage) */
-   MAYBE_PRINTF("wait4 ( %d, %p, %d, %p )\n",
-		arg1,arg2,arg3,arg4);
-   arg3 &= ~(VKI__WCLONE | VKI__WALL);
-
-   if (arg2 != (Addr)NULL)
-      SYSCALL_TRACK( pre_mem_write, tid, "wait4(status)", 
-		     arg2, sizeof(int) );
-   if (arg4 != (Addr)NULL)
-      SYSCALL_TRACK( pre_mem_write, tid, "wait4(rusage)", arg4, 
-		     sizeof(struct rusage) );
-}
-
-POST(wait4)
-{
-   if (arg2 != (Addr)NULL)
-      VG_TRACK( post_mem_write, arg2, sizeof(int) );
-   if (arg4 != (Addr)NULL)
-      VG_TRACK( post_mem_write, arg4, sizeof(struct rusage) );
-}
-
-PRE(writev)
-{
-   /* int writev(int fd, const struct iovec * vector, size_t count); */
-   Int i;
-   struct iovec * vec;
-   MAYBE_PRINTF("writev ( %d, %p, %d )\n",arg1,arg2,arg3);
-   if (!fd_allowed(arg1, "writev", tid)) {
-      res = -VKI_EBADF;
-   } else {
-      SYSCALL_TRACK( pre_mem_read, tid, "writev(vector)", 
-		     arg2, arg3 * sizeof(struct iovec) );
-      /* ToDo: don't do any of the following if the vector is invalid */
-      vec = (struct iovec *)arg2;
-      for (i = 0; i < (Int)arg3; i++)
-	 SYSCALL_TRACK( pre_mem_read, tid, "writev(vector[...])",
-			(UInt)vec[i].iov_base,vec[i].iov_len );
-   }
-}
-
-PRE(prctl)
-{
-   /* int prctl(int option, unsigned long arg2, unsigned long arg3,
-      unsigned long arg4, unsigned long arg5); */
-   MAYBE_PRINTF( "prctl ( %d, %d, %d, %d, %d )\n", arg1, arg2, arg3,
-		 arg4, arg5 );
-}
-
-PRE(adjtimex)
-{
-   struct timex *tx = (struct timex *)arg1;
-   MAYBE_PRINTF("adjtimex ( %p )\n", arg1);
-
-   SYSCALL_TRACK(pre_mem_read, tid, "adjtimex(timex->modes)", arg1, sizeof(tx->modes));
-
-#define ADJX(bit,field) 				\
-   if (tx->modes & bit)					\
-      SYSCALL_TRACK(pre_mem_read, tid,			\
-		    "adjtimex(timex->"#field")",	\
-		    (UInt)&tx->field, sizeof(tx->field))
-   ADJX(ADJ_FREQUENCY, freq);
-   ADJX(ADJ_MAXERROR, maxerror);
-   ADJX(ADJ_ESTERROR, esterror);
-   ADJX(ADJ_STATUS, status);
-   ADJX(ADJ_TIMECONST, constant);
-   ADJX(ADJ_TICK, tick);
-#undef ADJX
-   
-   SYSCALL_TRACK(pre_mem_write, tid, "adjtimex(timex)", arg1, sizeof(struct timex));
-}
-
-POST(adjtimex)
-{
-   VG_TRACK(post_mem_write, arg1, sizeof(struct timex));
-}
-
-PRE(clock_gettime)
-{
-    /* int clock_gettime(clockid_t clk_id, struct timespec *tp); */
-    MAYBE_PRINTF("clock_gettime(%d, %p)\n" ,arg1,arg2);
-    SYSCALL_TRACK(pre_mem_write, tid, "clock_gettime(tp)",
-                   arg2, sizeof(struct timespec));
-}
-
-POST(clock_gettime)
-{
-    if (!VG_(is_kerror)(res) && res == 0)
-       VG_TRACK( post_mem_write, arg2, sizeof(struct timespec) );
-}
-
-PRE(utimes)
-{
-    /* int utimes(const char *filename, struct timeval *tvp); */
-    MAYBE_PRINTF("utimes ( %p, %p )\n", arg1,arg2);
-    SYSCALL_TRACK( pre_mem_read_asciiz, tid, "utimes(filename)", arg1 );
-    if (arg2 != (UInt)NULL)
-         SYSCALL_TRACK( pre_mem_read, tid, "utimes(tvp)", arg2,
-                       sizeof(struct timeval) );
-}
-
-PRE(futex)
-{
-    /* int futex(void *futex, int op, int val, const struct timespec *timeout); */
-    MAYBE_PRINTF("futex ( %p, %d, %d, %p, %p )\n", arg1,arg2,arg3,arg4,arg5);
-    SYSCALL_TRACK( pre_mem_read, tid, "futex(futex)", arg1, sizeof(int) );
-    if (arg2 == VKI_FUTEX_WAIT && arg4 != (UInt)NULL)
-       SYSCALL_TRACK( pre_mem_read, tid, "futex(timeout)", arg4,
-                      sizeof(struct timespec) );
-    if (arg2 == VKI_FUTEX_REQUEUE)
-       SYSCALL_TRACK( pre_mem_read, tid, "futex(futex2)", arg4, sizeof(int) );
-}
-
-POST(futex)
-{
-   if (!VG_(is_kerror)(res)) {
-      VG_TRACK( post_mem_write, arg1, sizeof(int) );
-      if (arg2 == VKI_FUTEX_FD && VG_(clo_track_fds))
-         record_fd_open(tid, res, NULL);
-   }
-}
-
-#define SIGNAL_SIMULATION	1
-
-PRE(pause)
-{
-   /* int pause(void); */
-   MAYBE_PRINTF("pause ( )\n");
-}
-
-PRE(rt_sigsuspend)
-{
-   /* int sigsuspend(const sigset_t *mask); */
-   MAYBE_PRINTF("sigsuspend ( %p )\n", arg1 );
-   if (arg1 != (Addr)NULL) {
-      /* above NULL test is paranoia */
-      SYSCALL_TRACK( pre_mem_read, tid, "sigsuspend(mask)", arg1, 
-		     sizeof(vki_ksigset_t) );
-   }
-}
-
-PREALIAS(sigsuspend, rt_sigsuspend);
-
-PRE(rt_sigtimedwait)
-{
-   /* int sigtimedwait(const  sigset_t  *set,  siginfo_t  *info,
-      const struct timespec timeout); */
-   MAYBE_PRINTF("sigtimedwait ( %p, %p, timeout )\n", arg1, arg2);
-   if (arg1 != (UInt)NULL) 
-      SYSCALL_TRACK( pre_mem_read,  tid, "sigtimedwait(set)",  arg1,
-                     sizeof(vki_ksigset_t));
-   if (arg2 != (UInt)NULL)
-      SYSCALL_TRACK( pre_mem_write, tid, "sigtimedwait(info)", arg2,
-		     sizeof(siginfo_t) );
-}
-
-POST(rt_sigtimedwait)
-{
-   if (arg2 != (UInt)NULL)
-      VG_TRACK( post_mem_write, arg2, sizeof(siginfo_t) );
-}
-
-PRE(rt_sigqueueinfo)
-{
-   /*  long sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo) */
-   MAYBE_PRINTF("rt_sigqueueinfo(%d, %d, %p)\n", arg1, arg2, arg3);
-   if (arg2 != (UInt)NULL)
-      SYSCALL_TRACK( pre_mem_read, tid, "sigqueueinfo(uinfo)", arg3, 
-		     sizeof(siginfo_t) );
-}
-
-POST(rt_sigqueueinfo)
-{
-   if (res >= 0 && 
-       arg2 != 0 &&
-       !VG_(is_sig_ign)(arg2) &&
-       !VG_(ksigismember)(&tst->eff_sig_mask, arg2) &&
-       arg1 == VG_(getpid)()) {
-      VG_(proxy_waitsig)();
-   }
-}
-
-PRE(sigaltstack)
-{
-   /* int sigaltstack(const stack_t *ss, stack_t *oss); */
-   MAYBE_PRINTF("sigaltstack ( %p, %p )\n",arg1,arg2);
-   if (arg1 != (UInt)NULL) {
-      SYSCALL_TRACK( pre_mem_read, tid, "sigaltstack(ss)", 
-		     arg1, sizeof(vki_kstack_t) );
-   }
-   if (arg2 != (UInt)NULL) {
-      SYSCALL_TRACK( pre_mem_write, tid, "sigaltstack(oss)", 
-		     arg2, sizeof(vki_kstack_t) );
-   }
-
-   if (SIGNAL_SIMULATION)
-      VG_(do__NR_sigaltstack) (tid);
-}
-
-POST(sigaltstack)
-{
-   if (res == 0 && arg2 != (UInt)NULL)
-      VG_TRACK( post_mem_write, arg2, sizeof(vki_kstack_t));
-}
-
-PRE(sigaction)
-{
-   /* int sigaction(int signum, struct k_sigaction *act, 
-      struct k_sigaction *oldact); */
-   MAYBE_PRINTF("sigaction ( %d, %p, %p )\n",arg1,arg2,arg3);
-   if (arg2 != (UInt)NULL)
-      SYSCALL_TRACK( pre_mem_read, tid, "sigaction(act)", 
-		     arg2, sizeof(vki_ksigaction));
-   if (arg3 != (UInt)NULL)
-      SYSCALL_TRACK( pre_mem_write, tid, "sigaction(oldact)", 
-		     arg3, sizeof(vki_ksigaction));
-
-   if (SIGNAL_SIMULATION)
-      VG_(do__NR_sigaction)(tid);
-}
-
-POST(sigaction)
-{
-   if (res == 0 && arg3 != (UInt)NULL)
-      VG_TRACK( post_mem_write, arg3, sizeof(vki_ksigaction));
-}
-
-PREALIAS(rt_sigaction, sigaction);
-POSTALIAS(rt_sigaction, sigaction);
-
-PRE(sigprocmask)
-{
-   /* int sigprocmask(int how, k_sigset_t *set, 
-      k_sigset_t *oldset); */
-   MAYBE_PRINTF("sigprocmask ( %d, %p, %p )\n",arg1,arg2,arg3);
-   if (arg2 != (UInt)NULL)
-      SYSCALL_TRACK( pre_mem_read, tid, "sigprocmask(set)", 
-		     arg2, sizeof(vki_ksigset_t));
-   if (arg3 != (UInt)NULL)
-      SYSCALL_TRACK( pre_mem_write, tid, "sigprocmask(oldset)", 
-		     arg3, sizeof(vki_ksigset_t));
-
-   if (SIGNAL_SIMULATION)
-      VG_(do__NR_sigprocmask) ( tid, 
-				arg1 /*how*/, 
-				(vki_ksigset_t*) arg2,
-				(vki_ksigset_t*) arg3 );
-}
-
-POST(sigprocmask)
-{
-   if (res == 0 && arg3 != (UInt)NULL)
-      VG_TRACK( post_mem_write, arg3, sizeof(vki_ksigset_t));
-}
-
-PREALIAS(rt_sigprocmask, sigprocmask);
-POSTALIAS(rt_sigprocmask, sigprocmask);
-
-PRE(sigpending)
-{
-   /* int sigpending( sigset_t *set ) ; */
-   MAYBE_PRINTF( "sigpending ( %p )\n", arg1 );
-   SYSCALL_TRACK( pre_mem_write, tid, "sigpending(set)", 
-		  arg1, sizeof(vki_ksigset_t));
-}
-
-POST(sigpending)
-{
-   if ( !VG_( is_kerror )( res ) && res == 0 )
-      VG_TRACK( post_mem_write, arg1, sizeof( vki_ksigset_t ) ) ;
-}
-
-PREALIAS(rt_sigpending, sigpending);
-POSTALIAS(rt_sigpending, sigpending);
-
-
-#undef SYSNO
-#undef res
-#undef arg1
-#undef arg2
-#undef arg3
-#undef arg4
-#undef arg5
-#undef arg6
-
-struct sys_info {
-   Bool	may_block;		/* is a potentially blocking syscall */
-   void	(*before)(ThreadId tid, ThreadState *tst);
-   void	(*after)(ThreadId tid, ThreadState *tst);
-};
-#define SYSB_(name, blk)	[__NR_##name] = { blk, before_##name, NULL }
-#define SYSBA(name, blk)	[__NR_##name] = { blk, before_##name, after_##name }
-
-static void bad_before(ThreadId tid, ThreadState *tst)
-{
-   VG_(message)
-      (Vg_DebugMsg,"WARNING: unhandled syscall: %d", tst->m_eax);
-   if (VG_(clo_verbosity) > 1) {
-      ExeContext *ec = VG_(get_ExeContext)(tid);
-      VG_(pp_ExeContext)(ec);
-   }
-   VG_(message)
-      (Vg_DebugMsg,"Do not panic.  You may be able to fix this easily.");
-   VG_(message)
-      (Vg_DebugMsg,"Read the file README_MISSING_SYSCALL_OR_IOCTL.");
-
-   tst->m_eax = -VKI_ENOSYS;
-}
-
-static void bad_after(ThreadId tid, ThreadState *tst)
-{
-}
-
-static const struct sys_info bad_sys = { False, bad_before, bad_after };
-
-static const struct sys_info special_sys[] = {
-   /* special */
-   SYSB_(exit_group,		False),
-   SYSB_(exit,			False),
-   SYSB_(clone,			False),
-
-   SYSB_(modify_ldt,		False),
-   SYSB_(set_thread_area,	False),
-   SYSB_(get_thread_area,	False),
-
-   SYSB_(execve,		False),
-   SYSB_(brk,			False),
-   SYSB_(mmap,			False),
-   SYSB_(mremap,		False),
-
-#if SIGNAL_SIMULATION
-   SYSBA(sigaltstack,		False),
-   SYSBA(rt_sigaction,		False),
-   SYSBA(sigaction,		False),
-   SYSBA(rt_sigprocmask,	False),
-   SYSBA(sigprocmask,		False),
-#endif /* SIGNAL_SIMULATION */
-};
-#define MAX_SPECIAL_SYS		(sizeof(special_sys)/sizeof(special_sys[0]))
-
-static const struct sys_info sys_info[] = {
-   SYSBA(ptrace,		False),
-   SYSB_(mount,			True),
-   SYSB_(umount,		False),
-
-   SYSB_(setresgid,		False),
-   SYSB_(vhangup,		False),
-   SYSB_(iopl,			False),
-
-   SYSB_(setxattr,		True),
-   SYSB_(lsetxattr,		True),
-   SYSB_(fsetxattr,		True),
-   SYSBA(getxattr,		True),
-   SYSBA(lgetxattr,		True),
-   SYSBA(fgetxattr,		True),
-   SYSBA(listxattr,		True),
-   SYSBA(llistxattr,		True),
-   SYSBA(flistxattr,		True),
-   SYSB_(removexattr,		True),
-   SYSB_(lremovexattr,		True),
-   SYSB_(fremovexattr,		True),
-
-   SYSB_(quotactl,		False),
-   SYSBA(lookup_dcookie,	False),
-
-   SYSB_(truncate64,		True),
-   SYSB_(fdatasync,		True),
-   SYSB_(msync,			True),
-
-   SYSBA(getpmsg,		True),
-   SYSB_(putpmsg,		True),
-
-   SYSBA(syslog,		True),
-   SYSB_(personality,		False),
-   SYSB_(chroot,		False),
-   SYSB_(madvise,		True),
-   SYSB_(nice,			False),
-   SYSB_(setresgid32,		False),
-   SYSB_(setfsuid32,		False),
-   SYSBA(_sysctl,		False),
-
-   SYSB_(sched_getscheduler,	False),	/* ??? */
-   SYSB_(sched_setscheduler,	False),	/* ??? */
-
-   SYSB_(mlock,			True),
-   SYSB_(munlock,		True),
-   SYSB_(mlockall,		True),
-   SYSB_(munlockall,		True),
-
-   SYSB_(sched_get_priority_max,	False),	/* ??? */
-   SYSB_(sched_get_priority_min,	False),	/* ??? */
-
-   SYSB_(setpriority,		False),
-   SYSB_(getpriority,		False),
-
-   SYSB_(setfsgid,		False),
-   SYSB_(setregid,		False),
-   SYSB_(setresuid,		False),
-   SYSB_(setfsuid,		False),
-
-   SYSBA(sendfile,		True),
-   SYSBA(sendfile64,		True),
-   SYSB_(pwrite64,		True),
-   SYSB_(sync,			True),
-   SYSBA(fstatfs,		False),
-   SYSB_(getsid,		False),
-   SYSBA(pread64,		True),
-   SYSB_(mknod,			False),
-   SYSB_(flock,			True),
-   SYSB_(init_module,		True),
-   SYSB_(ioperm,		False),
-   SYSBA(capget,		False),
-   SYSB_(capset,		False),
-   SYSB_(access,		False),
-   SYSB_(chdir,			False),
-   SYSB_(chmod,			False),
-   SYSB_(chown32,		False),
-   SYSB_(lchown32,		False),
-   SYSB_(chown,			False),
-   SYSBA(close,			False),
-   SYSBA(dup,			False),
-   SYSBA(dup2,			False),
-   SYSBA(fcntl,			True),
-   SYSB_(fchdir,		False),
-   SYSB_(fchown32,		False),
-   SYSB_(fchown,		False),
-   SYSB_(fchmod,		False),
-   SYSBA(fcntl64,		True),
-   SYSBA(fstat,			False),
-   SYSBA(fork,			False),
-   SYSB_(fsync,			True),
-   SYSB_(ftruncate,		True),
-   SYSB_(ftruncate64,		True),
-   SYSBA(getdents,		True),
-   SYSBA(getdents64,		True),
-   SYSBA(getgroups32,		True),
-   SYSBA(getgroups,		False),
-   SYSBA(getcwd,		False),
-   SYSB_(geteuid,		False),
-   SYSB_(geteuid32,		False),
-   SYSB_(getegid,		False),
-   SYSB_(getegid32,		False),
-   SYSB_(getgid,		False),
-   SYSB_(getgid32,		False),
-   SYSB_(getpid,		False),
-   SYSB_(getpgid,		False),
-   SYSB_(getpgrp,		False),
-   SYSB_(getppid,		False),
-   SYSBA(getresgid,		False),
-   SYSBA(getresgid32,		False),
-   SYSBA(getresuid,		False),
-   SYSBA(getresuid32,		False),
-   SYSBA(ugetrlimit,		False),
-   SYSBA(getrlimit,		False),
-   SYSBA(getrusage,		False),
-   SYSBA(gettimeofday,		False),
-   SYSB_(getuid,		False),
-   SYSB_(getuid32,		False),
-   SYSBA(ipc,			True),
-   SYSBA(ioctl,			True),
-   SYSBA(kill,			False),
-   SYSB_(link,			True),
-   SYSB_(lseek,			False),
-   SYSBA(_llseek,		False),
-   SYSBA(lstat,			False),
-   SYSBA(lstat64,		False),
-   SYSB_(mkdir,			True),
-   SYSBA(mprotect,		False),
-   SYSBA(munmap,		False),
-   SYSBA(mincore,		False),
-   SYSBA(nanosleep,		True),
-   SYSB_(_newselect,		True),
-   SYSBA(open,			True),
-   SYSBA(read,			True),
-   SYSB_(write,			True),
-   SYSBA(creat,			True),
-   SYSBA(pipe,			False),
-   SYSBA(poll,			True),
-   SYSBA(readlink,		False),
-   SYSBA(readv,			True),
-   SYSB_(rename,		False),
-   SYSB_(rmdir,			True),
-   SYSBA(sched_setparam,	False),	/* ??? */
-   SYSBA(sched_getparam,	False),	/* ??? */
-   SYSB_(sched_yield,		False),	/* ??? */
-   SYSB_(select,		True),
-   SYSB_(setfsgid32,		False),
-   SYSB_(setgid32,		False),
-   SYSB_(setgid,		False),
-   SYSB_(setsid,		False),
-   SYSB_(setgroups32,		False),
-   SYSB_(setgroups,		False),
-   SYSBA(setpgid,		False),
-   SYSB_(setregid32,		False),
-   SYSB_(setresuid32,		False),
-   SYSB_(setreuid32,		False),
-   SYSB_(setreuid,		False),
-   SYSB_(setrlimit,		False),
-   SYSB_(setuid32,		False),
-   SYSB_(setuid,		False),
-   SYSBA(socketcall,		True),
-   SYSBA(stat,			False),
-   SYSBA(statfs,		False),
-   SYSBA(statfs64,		False),
-   SYSB_(symlink,		True),
-   SYSBA(stat64,		False),
-   SYSBA(fstat64,		False),
-   SYSBA(sysinfo,		False),
-   SYSBA(time,			False),
-   SYSBA(times,			False),
-   SYSB_(truncate,		True),
-   SYSB_(umask,			False),
-   SYSB_(unlink,		True),
-   SYSBA(uname,			False),
-   SYSB_(utime,			True),
-   SYSB_(utimes,                False),
-   SYSBA(waitpid,		True),
-   SYSBA(wait4,			True),
-   SYSB_(writev,		True),
-   SYSB_(prctl,			True),
-   SYSBA(adjtimex,		False),
-   SYSBA(mmap2,			False),
-   SYSBA(clock_gettime,         False),
-   SYSBA(futex,                 True),
-
-   /* new signal handling makes these normal blocking syscalls */
-   SYSB_(pause,			True),
-   SYSB_(sigsuspend,		True),
-   SYSB_(rt_sigsuspend,		True),
-   SYSBA(rt_sigtimedwait,	True),
-   SYSBA(rt_sigqueueinfo,	False),
-
-   SYSBA(sigpending,		True), /* not blocking, but must run in LWP context */
-   SYSBA(rt_sigpending,		True), /* not blocking, but must run in LWP context */
-   SYSB_(alarm,			True), /* not blocking, but must run in LWP context */
-   SYSBA(setitimer,		True), /* not blocking, but must run in LWP context */
-   SYSBA(getitimer,		True), /* not blocking, but must run in LWP context */
-
-#if !SIGNAL_SIMULATION
-   SYSBA(sigaltstack,		False),
-   SYSBA(rt_sigaction,		False),
-   SYSBA(sigaction,		False),
-   SYSBA(rt_sigprocmask,	False),
-   SYSBA(sigprocmask,		False),
-#endif /* !SIGNAL_SIMULATION */
-};
-#define MAX_SYS_INFO		(sizeof(sys_info)/sizeof(sys_info[0]))
-
-#undef SYSB_
-#undef SYSBA
-
-Bool VG_(pre_syscall) ( ThreadId tid )
-{
-   ThreadState* tst;
-   UInt         syscallno;
-   const struct sys_info *sys;
-   Bool special = False;
-   Bool syscall_done = False;	/* we actually ran the syscall */
-
-   VGP_PUSHCC(VgpCoreSysWrap);
-
-   tst = VG_(get_ThreadState)(tid);
-
-   /* Convert vfork to fork, since we can't handle it otherwise. */
-   if (tst->m_eax == __NR_vfork)
-      tst->m_eax = __NR_fork;
-
-   syscallno = tst->m_eax;
-
-   if (tst->syscallno != -1)
-      VG_(printf)("tid %d has syscall %d\n", tst->tid, tst->syscallno);
-
-   vg_assert(tst->syscallno == -1);		/* should be no current syscall */
-   vg_assert(tst->status == VgTs_Runnable);	/* should be runnable */
-
-   /* the syscall no is in %eax.  For syscalls with <= 6 args,
-      args 1 .. 6 to the syscall are in %ebx %ecx %edx %esi %edi %ebp.
-      For calls with > 6 args, %ebx points to a lump of memory
-      containing the args.
-
-      The result is returned in %eax.  If this value >= 0, the call
-      succeeded, and this is the return value.  If < 0, it failed, and
-      the negation of this value is errno.  To be more specific, 
-      if res is in the range -EMEDIUMTYPE (-124) .. -EPERM (-1)
-      (kernel 2.4.9 sources, include/asm-i386/errno.h)
-      then it indicates an error.  Otherwise it doesn't.
-
-      Dirk Mueller (mueller@kde.org) says that values -4095 .. -1
-      (inclusive?) indicate error returns.  Not sure where the -4095
-      comes from.
-   */
-
-   tst->syscallno = syscallno;
-   vg_assert(tst->status == VgTs_Runnable);
-
-   if (syscallno < MAX_SPECIAL_SYS && special_sys[syscallno].before != NULL) {
-      sys = &special_sys[syscallno];
-      special = True;
-   } else if (syscallno < MAX_SYS_INFO && sys_info[syscallno].before != NULL) {
-      sys = &sys_info[syscallno];
-   } else {
-      sys = &bad_sys;
-      special = True;
-   }
-
-   /* Do any pre-syscall actions */
-   if (VG_(needs).syscall_wrapper) {
-      VGP_PUSHCC(VgpSkinSysWrap);
-      tst->sys_pre_res = TL_(pre_syscall)(tid, syscallno, /*isBlocking*/sys->may_block);
-      VGP_POPCC(VgpSkinSysWrap);
-   }
-
-   MAYBE_PRINTF("SYSCALL[%d,%d](%3d)%s%s:", 
-		VG_(getpid)(), tid, syscallno, 
-		special ? " special" : "",
-		sys->may_block ? " blocking" : "");
-
-   if (special) {
-      /* "Special" syscalls are implemented by Valgrind internally,
-	 and do not generate real kernel calls.  The expectation,
-	 therefore, is that the "before" function not only does the
-	 appropriate tests, but also performs the syscall itself and
-	 sets the result.  Special syscalls cannot block. */
-      vg_assert(sys->may_block == False);
-
-      (sys->before)(tst->tid, tst);
-
-      syscall_done = True;
-   } else {
-      (sys->before)(tst->tid, tst);
-
-      if ((Int)tst->m_eax <= 0) {
-	 /* "before" decided the syscall wasn't viable, so don't do
-	    anything - just pretend the syscall happened. */
-	 syscall_done = True;
-      } else if (sys->may_block) {
-	 /* Issue to worker.  If we're waiting on the syscall because
-	    it's in the hands of the ProxyLWP, then set the thread
-	    state to WaitSys. */
-	 tst->status = VgTs_WaitSys;
-	 VG_(sys_issue)(tid);
-      } else {
-	 /* run the syscall directly */
-	 tst->m_eax = VG_(do_syscall)(syscallno, 
-				      tst->m_ebx,
-				      tst->m_ecx, 
-				      tst->m_edx,
-				      tst->m_esi,
-				      tst->m_edi,
-				      tst->m_ebp);
-	 syscall_done = True;
-      }
-   }
-
-   VGP_POPCC(VgpCoreSysWrap);
-
-   vg_assert(( syscall_done && tst->status == VgTs_Runnable) ||
-	     (!syscall_done && tst->status == VgTs_WaitSys ));
-
-   return syscall_done;
-}
-
-
-void VG_(post_syscall) ( ThreadId tid, Bool restart )
-{
-   ThreadState* tst;
-   UInt syscallno;
-   const struct sys_info *sys;
-   Bool special = False;
-   Bool restarted = False;
-   void *pre_res;
-
-   VGP_PUSHCC(VgpCoreSysWrap);
-
-   tst = VG_(get_ThreadState)(tid);
-
-   /* Tell the skin about the syscall return value */
-   SET_SYSCALL_RETVAL(tst->tid, tst->m_eax);
-
-   syscallno = tst->syscallno;
-   pre_res = tst->sys_pre_res;
-
-   vg_assert(syscallno != -1);			/* must be a current syscall */
-
-   if (syscallno < MAX_SPECIAL_SYS && special_sys[syscallno].before != NULL) {
-      sys = &special_sys[syscallno];
-      special = True;
-   } else if (syscallno < MAX_SYS_INFO && sys_info[syscallno].before != NULL) {
-      sys = &sys_info[syscallno];
-   } else {
-      sys = &bad_sys;
-      special = True;
-   }
-
-   if (tst->m_eax == -VKI_ERESTARTSYS) {
-      /* Applications never expect to see this, so we should either
-	 restart the syscall or fail it with EINTR, depending on what
-	 our caller wants.  Generally they'll want to restart, but if
-	 client set the signal state to not restart, then we fail with
-	 EINTR.  Either way, ERESTARTSYS means the syscall made no
-	 progress, and so can be failed or restarted without
-	 consequence. */
-      if (0)
-	 VG_(printf)("syscall %d returned ERESTARTSYS; restart=%d\n",
-		     syscallno, restart);
-
-      if (restart) {
-	 restarted = True;
-	 VG_(restart_syscall)(tid);
-      } else
-	 tst->m_eax = -VKI_EINTR;
-   } 
-
-   if (!restarted) {
-      if (!VG_(is_kerror)(tst->m_eax) && sys->after != NULL)
-	 (sys->after)(tst->tid, tst);
-
-      /* Do any post-syscall actions
-
-	 NOTE: this is only called if the syscall completed.  If the
-	 syscall was restarted, then it will call the Tool's
-	 pre_syscall again, without calling post_syscall (ie, more
-	 pre's than post's)
-       */
-      if (VG_(needs).syscall_wrapper) {
-	 VGP_PUSHCC(VgpSkinSysWrap);
-	 TL_(post_syscall)(tid, syscallno, pre_res, tst->m_eax, /*isBlocking*/True); // did block
-	 VGP_POPCC(VgpSkinSysWrap);
-      }
-   }
-
-   tst->status = VgTs_Runnable;	/* runnable again */
-   tst->syscallno = -1;		/* no current syscall */
-
-   VGP_POPCC(VgpCoreSysWrap);
-}
-
-void VG_(restart_syscall)(ThreadId tid)
-{
-   ThreadState* tst;
-   tst = VG_(get_ThreadState)(tid);
-
-   vg_assert(tst != NULL);
-   vg_assert(tst->status == VgTs_WaitSys);
-   vg_assert(tst->syscallno != -1);
-
-   tst->m_eax = tst->syscallno;
-   tst->m_eip -= 2;		/* sizeof(int $0x80) */
-
-   /* Make sure our caller is actually sane, and we're really backing
-      back over a syscall.
-
-      int $0x80 == CD 80 
-   */
-   {
-      UChar *p = (UChar *)tst->m_eip;
-      
-      if (p[0] != 0xcd || p[1] != 0x80)
-	 VG_(message)(Vg_DebugMsg, 
-		      "?! restarting over syscall at %p %02x %02x\n",
-		      tst->m_eip, p[0], p[1]);
-
-      vg_assert(p[0] == 0xcd && p[1] == 0x80);
-   }
-}
-
-/*--------------------------------------------------------------------*/
-/*--- end                                            vg_syscalls.c ---*/
-/*--------------------------------------------------------------------*/
-
diff -puN include/Makefile.am~archdep include/Makefile.am
--- valgrind/include/Makefile.am~archdep	2004-01-27 11:09:02.000000000 -0800
+++ valgrind-jeremy/include/Makefile.am	2004-01-27 11:09:13.000000000 -0800
@@ -7,8 +7,7 @@ incincdir = $(includedir)/valgrind
 incinc_HEADERS = \
 	valgrind.h \
 	vg_constants_skin.h \
-	vg_skin.h \
-	vg_kerneliface.h
+	vg_skin.h
 
 BUILT_SOURCES = vg_skin.h
 CLEANFILES = vg_skin.h
diff -puN memcheck/Makefile.am~archdep memcheck/Makefile.am
--- valgrind/memcheck/Makefile.am~archdep	2004-01-27 11:09:02.000000000 -0800
+++ valgrind-jeremy/memcheck/Makefile.am	2004-01-27 11:09:13.000000000 -0800
@@ -1,7 +1,7 @@
 
 SUBDIRS = . tests docs
 
-all_includes = -I$(top_srcdir)/include
+all_includes = -I$(top_srcdir)/include $(VG_PLAT_INCLUDES)
 
 AM_CPPFLAGS = $(all_includes) -DVG_LIBDIR="\"$(libdir)"\"
 AM_CFLAGS = $(WERROR) -Winline -Wall -Wshadow -O2 -fomit-frame-pointer \
diff -puN addrcheck/Makefile.am~archdep addrcheck/Makefile.am
--- valgrind/addrcheck/Makefile.am~archdep	2004-01-27 11:09:02.000000000 -0800
+++ valgrind-jeremy/addrcheck/Makefile.am	2004-01-27 11:09:13.000000000 -0800
@@ -3,7 +3,7 @@ SUBDIRS = . docs tests
 
 # include memcheck/ for mac_shared.h
 AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/memcheck \
-		-DVG_LIBDIR="\"$(libdir)"\"
+		-DVG_LIBDIR="\"$(libdir)"\" $(VG_PLAT_INCLUDES)
 AM_CFLAGS = $(WERROR) -Winline -Wall -Wshadow -O -fomit-frame-pointer \
 		@PREFERRED_STACK_BOUNDARY@ -g
 
diff -puN helgrind/Makefile.am~archdep helgrind/Makefile.am
--- valgrind/helgrind/Makefile.am~archdep	2004-01-27 11:09:02.000000000 -0800
+++ valgrind-jeremy/helgrind/Makefile.am	2004-01-27 11:09:13.000000000 -0800
@@ -1,7 +1,7 @@
 
 SUBDIRS = . docs tests
 
-AM_CPPFLAGS = -I$(top_srcdir)/include -DVG_LIBDIR="\"$(libdir)"\"
+AM_CPPFLAGS = -I$(top_srcdir)/include -DVG_LIBDIR="\"$(libdir)"\" $(VG_PLAT_INCLUDES)
 AM_CFLAGS = $(WERROR) -Winline -Wall -Wshadow -O -fomit-frame-pointer \
 		@PREFERRED_STACK_BOUNDARY@ -g
 
diff -puN none/Makefile.am~archdep none/Makefile.am
--- valgrind/none/Makefile.am~archdep	2004-01-27 11:09:02.000000000 -0800
+++ valgrind-jeremy/none/Makefile.am	2004-01-27 11:09:13.000000000 -0800
@@ -1,7 +1,7 @@
 
 SUBDIRS = . docs tests
 
-AM_CPPFLAGS = -I$(top_srcdir)/include -DVG_LIBDIR="\"$(libdir)"\"
+AM_CPPFLAGS = -I$(top_srcdir)/include -DVG_LIBDIR="\"$(libdir)"\" $(VG_PLAT_INCLUDES)
 AM_CFLAGS = $(WERROR) -Winline -Wall -Wshadow -O -fomit-frame-pointer \
 		@PREFERRED_STACK_BOUNDARY@ -g
 
diff -puN corecheck/Makefile.am~archdep corecheck/Makefile.am
--- valgrind/corecheck/Makefile.am~archdep	2004-01-27 11:09:02.000000000 -0800
+++ valgrind-jeremy/corecheck/Makefile.am	2004-01-27 11:09:13.000000000 -0800
@@ -1,7 +1,7 @@
 
 SUBDIRS = . tests docs
 
-AM_CPPFLAGS = -I$(top_srcdir)/include -DVG_LIBDIR="\"$(libdir)"\"
+AM_CPPFLAGS = -I$(top_srcdir)/include -DVG_LIBDIR="\"$(libdir)"\" $(VG_PLAT_INCLUDES)
 AM_CFLAGS = $(WERROR) -Winline -Wall -Wshadow -O -fomit-frame-pointer \
 		@PREFERRED_STACK_BOUNDARY@ -g
 
diff -puN cachegrind/Makefile.am~archdep cachegrind/Makefile.am
--- valgrind/cachegrind/Makefile.am~archdep	2004-01-27 11:09:02.000000000 -0800
+++ valgrind-jeremy/cachegrind/Makefile.am	2004-01-27 11:09:13.000000000 -0800
@@ -1,7 +1,7 @@
 
 SUBDIRS = . docs tests
 
-AM_CPPFLAGS = -I$(top_srcdir)/include -DVG_LIBDIR="\"$(libdir)"\"
+AM_CPPFLAGS = -I$(top_srcdir)/include -DVG_LIBDIR="\"$(libdir)"\" $(VG_PLAT_INCLUDES)
 AM_CFLAGS = $(WERROR) -Winline -Wall -Wshadow -O -fomit-frame-pointer \
 		@PREFERRED_STACK_BOUNDARY@ -g
 
diff -puN lackey/Makefile.am~archdep lackey/Makefile.am
--- valgrind/lackey/Makefile.am~archdep	2004-01-27 11:09:02.000000000 -0800
+++ valgrind-jeremy/lackey/Makefile.am	2004-01-27 11:09:13.000000000 -0800
@@ -1,7 +1,7 @@
 
 SUBDIRS = . docs tests
 
-AM_CPPFLAGS = -I$(top_srcdir)/include -DVG_LIBDIR="\"$(libdir)"\"
+AM_CPPFLAGS = -I$(top_srcdir)/include -DVG_LIBDIR="\"$(libdir)"\" $(VG_PLAT_INCLUDES)
 AM_CFLAGS = $(WERROR) -Winline -Wall -Wshadow -O -fomit-frame-pointer \
 		@PREFERRED_STACK_BOUNDARY@ -g
 
diff -puN auxprogs/Makefile.am~archdep auxprogs/Makefile.am
--- valgrind/auxprogs/Makefile.am~archdep	2004-01-27 11:09:02.000000000 -0800
+++ valgrind-jeremy/auxprogs/Makefile.am	2004-01-27 11:09:13.000000000 -0800
@@ -2,7 +2,8 @@
 SUBDIRS = . 
 
 AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/coregrind \
-		-DVG_LIBDIR="\"$(libdir)"\"
+		$(VG_PLAT_INCLUDES) -DVG_LIBDIR="\"$(libdir)"\"
+
 AM_CFLAGS = $(WERROR) -Winline -Wall -O -g
 
 bin_PROGRAMS = valgrind-listener

_
