Add and delete all the files which need adding and deleting.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@2119 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/corecheck/tests/as_mmap.c b/corecheck/tests/as_mmap.c
new file mode 100644
index 0000000..da40a86
--- /dev/null
+++ b/corecheck/tests/as_mmap.c
@@ -0,0 +1,26 @@
+#include <sys/mman.h>
+#include <stdio.h>
+
+int main()
+{
+	char local;
+	char *top = (char *)(((unsigned long)&local + 0x0fffffff) & ~0x0fffffff);
+
+	if (mmap((void *)0x00000000, 0x10000, PROT_READ|PROT_WRITE, 
+		 MAP_PRIVATE|MAP_ANON|MAP_FIXED, -1, 0) == MAP_FAILED)
+		perror("mmap @ 0x00000000");
+	if (mmap((void *)0x00010000, 0x10000, PROT_READ|PROT_WRITE, 
+		 MAP_PRIVATE|MAP_ANON|MAP_FIXED, -1, 0) == MAP_FAILED)
+		perror("mmap @ 0x00010000");
+	if (mmap((void *)0x50000000, 0x10000, PROT_READ|PROT_WRITE, 
+		 MAP_PRIVATE|MAP_ANON|MAP_FIXED, -1, 0) == MAP_FAILED)
+		perror("mmap @ 0x50000000");
+	if (mmap(top, 0x10000, PROT_READ|PROT_WRITE, 
+		 MAP_PRIVATE|MAP_ANON|MAP_FIXED, -1, 0) == MAP_FAILED)
+		perror("mmap @ top");
+	if (mmap(top+0x08000000, 0x10000, PROT_READ|PROT_WRITE, 
+		 MAP_PRIVATE|MAP_ANON|MAP_FIXED, -1, 0) == MAP_FAILED)
+		perror("mmap @ top+.5G");
+
+	return 0;
+}
diff --git a/corecheck/tests/as_mmap.stderr.exp b/corecheck/tests/as_mmap.stderr.exp
new file mode 100644
index 0000000..e5314c8
--- /dev/null
+++ b/corecheck/tests/as_mmap.stderr.exp
@@ -0,0 +1,9 @@
+
+Warning: client syscall mmap2 tried to modify addresses 0x0-0x10000
+mmap @ 0x00000000: Cannot allocate memory
+Warning: client syscall mmap2 tried to modify addresses 0xB0000000-0xB0010000
+mmap @ top: Cannot allocate memory
+Warning: client syscall mmap2 tried to modify addresses 0xB8000000-0xB8010000
+mmap @ top+.5G: Cannot allocate memory
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/corecheck/tests/as_mmap.vgtest b/corecheck/tests/as_mmap.vgtest
new file mode 100644
index 0000000..13cb451
--- /dev/null
+++ b/corecheck/tests/as_mmap.vgtest
@@ -0,0 +1 @@
+prog: as_mmap
diff --git a/corecheck/tests/as_shm.c b/corecheck/tests/as_shm.c
new file mode 100644
index 0000000..2c86cb6
--- /dev/null
+++ b/corecheck/tests/as_shm.c
@@ -0,0 +1,32 @@
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <stdio.h>
+
+int main()
+{
+	int shmid = shmget(IPC_PRIVATE, 0x10000, IPC_CREAT|IPC_EXCL|0777);
+	void *addr;
+	char local;
+	char *top = (char *)(((unsigned long)&local + 0x0fffffff) & ~0x0fffffff);
+
+	if (shmid == -1)
+		perror("shmget");
+
+	addr = shmat(shmid, 0, 0);
+
+	if (addr == (void *)-1)
+		perror("shmat @ 0");
+	else
+		printf("shmat 0: addr=%p\n", addr);
+
+	addr = shmat(shmid, top, 0);
+
+	if (addr == (void *)-1)
+		perror("shmat @ top");
+	else
+		printf("shmat 2: addr=%p\n", addr);
+
+	shmctl(shmid, IPC_RMID, NULL);
+
+	return 0;
+}
diff --git a/corecheck/tests/as_shm.stderr.exp b/corecheck/tests/as_shm.stderr.exp
new file mode 100644
index 0000000..ee51d43
--- /dev/null
+++ b/corecheck/tests/as_shm.stderr.exp
@@ -0,0 +1,5 @@
+
+Warning: client syscall shmat tried to modify addresses 0xB0000000-0xB0010000
+shmat @ top: Invalid argument
+
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/corecheck/tests/as_shm.stdout.exp b/corecheck/tests/as_shm.stdout.exp
new file mode 100644
index 0000000..d2dcf73
--- /dev/null
+++ b/corecheck/tests/as_shm.stdout.exp
@@ -0,0 +1 @@
+shmat 0: addr=0x81156000
diff --git a/corecheck/tests/as_shm.vgtest b/corecheck/tests/as_shm.vgtest
new file mode 100644
index 0000000..1263cea
--- /dev/null
+++ b/corecheck/tests/as_shm.vgtest
@@ -0,0 +1 @@
+prog: as_shm
diff --git a/coregrind/gen_toolint.pl b/coregrind/gen_toolint.pl
new file mode 100644
index 0000000..2738f92
--- /dev/null
+++ b/coregrind/gen_toolint.pl
@@ -0,0 +1,262 @@
+#!/usr/bin/perl
+
+my $output = shift @ARGV;
+my $indent = "";
+my $headerguard;
+my $include;
+my $passcomment = 1;
+
+my $struct = "VG_(tool_interface)";
+
+my %pfxmap = ("track" => "SK_",
+	      "tool"  => "SK_",
+	      "malloc"=> "SK_",
+	     );
+
+sub getargnames(@) {
+    my @args = @_;
+    my @ret;
+
+    foreach my $a (@args) {
+	my @pieces = split /\s+/, $a;
+	my $name = pop @pieces;
+	push @ret, $name unless $name eq "void";
+    }
+    return @ret;
+}
+
+sub getargtypes(@) {
+    my @args = @_;
+    my @ret;
+
+    foreach my $a (@args) {
+	my @pieces = split /\s+/, $a;
+	pop @pieces;
+	push @ret, (join " ", @pieces);
+    }
+    @ret = "void" if ($#ret == -1);
+    return @ret;
+}
+
+# Different output modes
+if ($output eq "callwrap") {
+    $include = "vg_include.h";
+    $generate = sub ($$$@) {
+	my ($pfx, $ret, $func, @args) = @_;
+	my $args = join ", ", @args;
+	my $argnames = join ", ", getargnames(@args);
+	print "$ret $pfxmap{$pfx}($func)($args)\n{\n";
+	print "   return (*$struct.${pfx}_$func)($argnames);\n";
+	print "}\n";
+    }
+} elsif ($output eq "proto") {
+    $include = "vg_include.h";
+    $generate = sub ($$$@) {
+	my ($pfx, $ret, $func, @args) = @_;
+	my $args = join ', ', @args;
+
+	print "$ret $pfxmap{$pfx}($func)($args);\n";
+	print "Bool VG_(defined_$func)(void);\n";
+    }
+} elsif ($output eq "toolproto") {
+    $generate = sub ($$$@) {
+	my ($pfx, $ret, $func, @args) = @_;
+	my $args = join ', ', @args;
+
+	print "$ret $pfxmap{$pfx}($func)($args);\n";
+    }
+} elsif ($output eq "missingfuncs") {
+    $include = "vg_include.h";
+    $generate = sub ($$$@) {
+	my ($pfx, $ret, $func, @args) = @_;
+	my $args = join ", ", @args;
+
+	print "static $ret missing_${pfx}_$func($args) {\n";
+	print "   VG_(missing_tool_func)(\"${pfx}_$func\");\n";
+	print "}\n";
+	print "Bool VG_(defined_$func)(void) {\n";
+	print "   return $struct.${pfx}_$func != missing_${pfx}_$func;\n";
+	print "}\n\n";
+    };
+    $indent = "   ";
+} elsif ($output eq "struct") {
+    $include = "vg_include.h";
+    $pre = sub () {
+	print "typedef struct {\n";
+    };
+    $post = sub () {
+	print "} VgToolInterface;\n\n";
+	print "extern VgToolInterface $struct;\n"
+    };
+    $generate = sub ($$$@) {
+	my ($pfx, $ret, $func, @args) = @_;
+	my $args = join ", ", @args;
+
+	print "$indent$ret (*${pfx}_$func)($args);\n";
+    };
+    $indent = "   ";
+    $headerguard=$output;
+} elsif ($output eq "structdef") {
+    $include = "vg_toolint.h";
+    $pre = sub () {
+	print "VgToolInterface $struct = {\n";
+    };
+    $post = sub () {
+	print "};\n";
+    };
+    $generate = sub ($$$@) {
+	my ($pfx, $ret, $func, @args) = @_;
+
+	print "$indent.${pfx}_$func = missing_${pfx}_$func,\n"
+    };
+    $indent = "   ";
+} elsif ($output eq "initfunc") {
+    $include = "vg_skin.h";
+    $generate = sub ($$$@) {
+	my ($pfx, $ret, $func, @args) = @_;
+	my $args = join ", ", @args;
+	my $argnames = join ", ", getargnames(@args);
+
+	print <<EOF;
+void VG_(init_$func)($ret (*func)($args))
+{
+	if (func == NULL)
+		func = missing_${pfx}_$func;
+	if (VG_(defined_$func)())
+		VG_(printf)("Warning tool is redefining $func\\n");
+	if (func == SK_($func))
+		VG_(printf)("Warning tool is defining $func recursively\\n");
+	$struct.${pfx}_$func = func;
+}
+EOF
+    }
+} elsif ($output eq "initproto") {
+    $generate = sub ($$$@) {
+	my ($pfx, $ret, $func, @args) = @_;
+	my $args = join ', ', @args;
+	print "void VG_(init_$func)($ret (*func)($args));\n";
+    };
+    $headerguard=$output;
+} elsif ($output eq "initdlsym") {
+    $pre = sub () {
+	print <<EOF;
+#include <dlfcn.h>
+void VG_(tool_init_dlsym)(void *dlhandle)
+{
+   void *ret;
+
+EOF
+    };
+    $post = sub () {
+	print "}\n";
+    };
+    $generate = sub ($$$@) {
+	my ($pfx, $ret, $func, @args) = @_;
+	my $args = join ", ", getargtypes(@args);
+
+	print <<EOF;
+   ret = dlsym(dlhandle, "vgSkin_$func");
+   if (ret != NULL)
+      VG_(init_$func)(($ret (*)($args))ret);
+
+EOF
+    };
+
+    $passcomment = 0;
+}
+
+die "Unknown output format \"$output\"" unless defined $generate;
+
+print "/* Generated by \"gen_toolint.pl $output\" */\n";
+
+print <<EOF if defined $headerguard;
+
+#ifndef VG_toolint_$headerguard
+#define VG_toolint_$headerguard
+
+EOF
+
+print <<EOF if defined $include;
+#include \"$include\"
+EOF
+
+&$pre() if defined $pre;	# preamble
+
+my $state = "idle";
+
+my $buf;
+my $lines;
+
+while(<STDIN>) {
+    # skip simple comments
+    next if (/^#[^#]/);
+
+    if (/^:/) {
+	s/^://;
+	chomp;
+	$prefix=$_;
+	next;
+    }
+
+    # look for inserted comments
+    if (/^##/) {
+	if ($state eq "idle") {
+	    $state = "comment";
+	    $lines = 1;
+	    $_ =~ s,^## ,/* ,;
+	    $buf = $_;
+	    next;
+	} elsif ($state eq "comment") {
+	    $lines++;
+	    $_ =~ s,^## ,   ,;
+	    print $indent.$buf if $passcomment;
+	    $buf = $_;
+	    next;
+	}
+	next;
+    }
+
+    # blank lines in a comment are part of the comment
+    if (/^\s*$/) {
+	if ($state eq "comment") {
+	    $lines++;
+	    print $indent.$buf if $passcomment;
+	    $buf = "\n";
+	} else {
+	    print "\n" if $passcomment;
+	}
+	next;
+    }
+
+    # coming out of a comment
+    if ($state eq "comment") {
+	chomp $buf;
+
+	if ($passcomment) {
+	    if ($lines == 1) {
+		print "$indent$buf */\n";
+	    } else {
+		print "$indent$buf\n$indent */\n";
+	    }
+	}
+	$buf = "";
+	$state = "idle";
+    }
+
+    chomp;
+    my @func = split /,\s*/;
+
+    my $rettype = shift @func;
+    my $funcname = shift @func;
+
+    @func = "void" if scalar @func == 0;
+
+    &$generate ($prefix, $rettype, $funcname, @func);
+}
+
+&$post() if defined $post;	# postamble
+
+print <<EOF if defined $headerguard;
+
+#endif /* VG_toolint_$headerguard */
+EOF
diff --git a/coregrind/stage1.c b/coregrind/stage1.c
new file mode 100644
index 0000000..4d6d5db
--- /dev/null
+++ b/coregrind/stage1.c
@@ -0,0 +1,183 @@
+#define _FILE_OFFSET_BITS	64
+
+#include <stdio.h>
+#include <elf.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "vg_include.h"
+
+#include "ume.h"
+#include "ume_arch.h"
+#include "ume_archdefs.h"
+
+static int stack[SIGSTKSZ*4];
+static int our_argc;
+
+/* Where we expect to find all our aux files (namely, stage2) */
+static const char *valgrind_lib = VG_LIBDIR;
+
+/* stage2's name */
+static const char stage2[] = "stage2";
+
+/* Modify the auxv the kernel gave us to make it look like we were
+   execed as the shared object.
+
+   This also inserts a new entry into the auxv table so we can
+   communicate some extra information to stage2 (namely, the fd of the
+   padding file, so it can identiry and remove the padding later).
+*/
+static void *fix_auxv(void *v_init_esp, const struct exeinfo *info)
+{
+   struct ume_auxv *auxv;
+   int *newesp;
+   int seen;
+   int delta;
+   int i;
+   static const int new_entries = 2;
+
+   /* make sure we're running on the private stack */
+   assert(&delta >= stack && &delta < &stack[sizeof(stack)/sizeof(*stack)]);
+   
+   /* find the beginning of the AUXV table */
+   auxv = find_auxv(v_init_esp);
+
+   /* Work out how we should move things to make space for the new
+      auxv entry. It seems that ld.so wants a 16-byte aligned stack on
+      entry, so make sure that's the case. */
+   newesp = (int *)(((unsigned long)v_init_esp - new_entries * sizeof(*auxv)) & ~0xf);
+   delta = (char *)v_init_esp - (char *)newesp;
+
+   memmove(newesp, v_init_esp, (char *)auxv - (char *)v_init_esp);
+   
+   v_init_esp = (void *)newesp;
+   auxv -= delta/sizeof(*auxv);
+
+   /* stage2 needs this so it can clean up the padding we leave in
+      place when we start it */
+   auxv[0].a_type = AT_UME_PADFD;
+   auxv[0].a_val = as_getpadfd();
+
+   /* This will be needed by valgrind itself so that it can
+      subsequently execve() children.  This needs to be done here
+      because /proc/self/exe will go away once we unmap stage1. */
+   auxv[1].a_type = AT_UME_EXECFD;
+   auxv[1].a_val = open("/proc/self/exe", O_RDONLY);
+
+   /* make sure the rest are sane */
+   for(i = new_entries; i < delta/sizeof(*auxv); i++) {
+      auxv[i].a_type = AT_IGNORE;
+      auxv[i].a_val = 0;
+   }
+
+   /* OK, go through and patch up the auxv entries to match the new
+      executable */
+   seen = 0;
+   for(; auxv->a_type != AT_NULL; auxv++) {
+      if (0)
+	 printf("doing auxv %p %4x: %d %p\n", auxv, auxv->a_type, auxv->a_val, auxv->a_ptr);
+
+      switch(auxv->a_type) {
+      case AT_PHDR:
+	 seen |= 1;
+	 auxv->a_val = info->phdr;
+	 break;
+
+      case AT_PHNUM:
+	 seen |= 2;
+	 auxv->a_val = info->phnum;
+	 break;
+
+      case AT_BASE:
+	 seen |= 4;
+	 auxv->a_val = info->interp_base;
+	 break;
+
+      case AT_ENTRY:
+	 seen |= 8;
+	 auxv->a_val = info->entry;
+	 break;
+      }
+   }
+
+   /* If we didn't see all the entries we need to fix up, then we
+      can't make the new executable viable. */
+   if (seen != 0xf) {
+      fprintf(stderr, "fix_auxv: we didn't see enough auxv entries (seen=%x)\n", seen);
+      exit(1);
+   }
+
+   return v_init_esp;
+}
+
+static void hoops(void)
+{
+   int err;
+   struct exeinfo info;
+   extern char _end;
+   int *esp;
+   char buf[strlen(valgrind_lib) + sizeof(stage2) + 16];
+
+   info.exe_base = PGROUNDUP(&_end);
+   info.exe_end  = PGROUNDDN(ume_exec_esp);
+
+   /* XXX FIXME: how can stage1 know where stage2 wants things placed?
+      Options:
+      - we could look for a symbol
+      - it could have a special PHDR (v. ELF specific)
+      - something else?
+    */
+   info.map_base = 0xb0000000;
+   info.setbrk = 1;		/* ask do_exec to move the brk-base */
+   info.argv = NULL;
+
+   strcpy(buf, valgrind_lib);
+   strcat(buf, "/");
+   strcat(buf, stage2);
+
+   err = do_exec(buf, &info);
+
+   if (err != 0) {
+      fprintf(stderr, "failed to load %s: %s\n",
+	      buf, strerror(err));
+      exit(1);
+   }
+
+   /* Make sure stage2's dynamic linker can't tromp on the lower part
+      of the address space. */
+   as_pad(0, (void *)info.map_base);
+   
+   esp = fix_auxv(ume_exec_esp, &info);
+
+   if (0) {
+      int prmap(void *start, void *end, const char *perm, off_t off, int maj, int min, int ino) {
+	 printf("mapping %10p-%10p %s %02x:%02x %d\n",
+		start, end, perm, maj, min, ino);
+	 return 1;
+      }
+      printf("---------- launch stage 2 ----------\n");
+      printf("eip=%p esp=%p\n", (void *)info.init_eip, esp);
+      foreach_map(prmap);
+   }
+
+   ume_go(info.init_eip, (addr_t)esp);   
+}
+
+int main(int argc, char **argv)
+{
+   const char *cp = getenv(VALGRINDLIB);
+
+   if (cp != NULL)
+      valgrind_lib = cp;
+
+   assert(ume_exec_esp != NULL);
+
+   our_argc = argc;
+
+   /* move onto another stack so we can play with the main one */
+   ume_go((addr_t)hoops, (addr_t)stack + sizeof(stack));
+}
diff --git a/coregrind/stage2.c b/coregrind/stage2.c
new file mode 100644
index 0000000..c105bd8
--- /dev/null
+++ b/coregrind/stage2.c
@@ -0,0 +1,967 @@
+#define _FILE_OFFSET_BITS 64
+
+#include "vg_include.h"
+#include "ume.h"
+#include "ume_arch.h"
+#include "ume_archdefs.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <dlfcn.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <dirent.h>
+
+#ifndef AT_SYSINFO
+#define AT_SYSINFO		32
+#endif /* AT_SYSINFO */
+
+#ifndef AT_SYSINFO_EHDR
+#define AT_SYSINFO_EHDR		33
+#endif /* AT_SYSINFO_EHDR */
+
+#ifndef AT_SECURE
+#define AT_SECURE 23   /* secure mode boolean */
+#endif	/* AT_SECURE */
+
+/* Amount to reserve for Valgrind's internal heap */
+#define VALGRIND_HEAPSIZE	(128*1024*1024)
+
+/* Amount to reserve for Valgrind's internal mappings */
+#define VALGRIND_MAPSIZE	(128*1024*1024)
+
+/* redzone gap between client address space and shadow */
+#define REDZONE_SIZE		(1 * 1024*1024)
+
+/* size multiple for client address space */
+#define CLIENT_SIZE_MULTIPLE	(64 * 1024*1024)
+
+extern char kickstart_base;	/* linker-defined base address */
+
+/* Where we expect to find all our aux files */
+static const char *valgrind_lib = VG_LIBDIR;
+
+/* Parameters we're going to pass to Valgrind */
+static KickstartParams kp;
+
+/* Shape of the client address space */
+static addr_t client_base, client_end, client_size;
+
+/* Look for our AUXV table */
+static int scan_auxv(void)
+{
+   const struct ume_auxv *auxv = find_auxv((int *)ume_exec_esp);
+   int found = 0;
+
+   for(; auxv->a_type != AT_NULL; auxv++)
+      switch(auxv->a_type) {
+      case AT_UME_PADFD:
+	 as_setpadfd(auxv->a_val);
+	 found |= 1;
+	 break;
+
+      case AT_UME_EXECFD:
+	 kp.execfd = auxv->a_val;
+	 found |= 2;
+	 break;
+      }
+
+   return found == (1|2);
+}
+
+/* Scan a colon-separated list, and call a function on each element.
+   The string must be mutable, because we insert a temporary '\0', but
+   the string will end up unmodified.  (*func) should return 1 if it
+   doesn't need to see any more.
+*/
+static void scan_colsep(char *colsep, int (*func)(const char *))
+{
+   char *cp, *entry;
+   int end;
+
+   if (colsep == NULL ||
+       *colsep == '\0')
+      return;
+
+   entry = cp = colsep;
+
+   do {
+      end = (*cp == '\0');
+
+      if (*cp == ':' || *cp == '\0') {
+	 char save = *cp;
+
+	 *cp = '\0';
+	 if ((*func)(entry))
+	    end = 1;
+	 *cp = save;
+	 entry = cp+1;
+      }
+      cp++;
+   } while(!end);
+}
+
+/* Add a string onto the string table, and return its address */
+static char *copy_str(char **tab, const char *str)
+{
+   char *cp = *tab;
+   char *orig = cp;
+
+   while(*str)
+      *cp++ = *str++;
+   *cp++ = '\0';
+
+   if (0)
+      printf("copied %p \"%s\" len %d\n",
+	     orig, orig, cp-orig);
+
+   *tab = cp;
+
+   return orig;
+}
+
+/* 
+   This sets up the client's initial stack, containing the args,
+   environment and aux vector.
+
+   The format of the stack is:
+
+   higher address +-----------------+
+                  |                 |
+		  : string table    :
+		  |                 |
+		  +-----------------+
+		  | AT_NULL         |
+		  -                 -
+		  | auxv            |
+		  +-----------------+
+		  |  NULL           |
+		  -                 -
+		  | envp            |
+		  +-----------------+
+		  |  NULL           |
+		  -                 -
+		  | argv            |
+		  +-----------------+
+		  | argc            |
+   lower address  +-----------------+ <- esp
+                  | undefined       |
+		  :                 :
+ */
+static Addr setup_client_stack(char **orig_argv, char **orig_envp, 
+			       const struct ume_auxv *orig_auxv,
+			       const struct exeinfo *info)
+{
+   char **cpp;
+   char *strtab;		/* string table */
+   char *stringbase;
+   addr_t *ptr;
+   struct ume_auxv *auxv;
+   const struct ume_auxv *cauxv;
+   unsigned stringsize;		/* total size of strings in bytes */
+   unsigned auxsize;		/* total size of auxv in bytes */
+   int argc;			/* total argc */
+   int envc;			/* total number of env vars */
+   unsigned stacksize;		/* total client stack size */
+   addr_t cl_esp;		/* client stack base (initial esp) */
+
+   /* ==================== compute sizes ==================== */
+
+   /* first of all, work out how big the client stack will be */
+   stringsize = 0;
+
+   /* paste on the extra args if the loader needs them (ie, the #! 
+      interpreter and its argument) */
+   argc = 0;
+   if (info->argv0 != NULL) {
+      argc++;
+      stringsize += strlen(info->argv0) + 1;
+   }
+   if (info->argv1 != NULL) {
+      argc++;
+      stringsize += strlen(info->argv1) + 1;
+   }
+
+   /* now scan the args we're given... */
+   for(cpp = orig_argv; *cpp; cpp++) {
+      argc++;
+      stringsize += strlen(*cpp) + 1;
+   }
+   
+   /* ...and the environment */
+   envc = 0;
+   for(cpp = orig_envp; cpp && *cpp; cpp++) {
+      envc++;
+      stringsize += strlen(*cpp) + 1;
+   }
+
+   /* now, how big is the auxv? */
+   auxsize = sizeof(*auxv);	/* there's always at least one entry: AT_NULL */
+   for(cauxv = orig_auxv; cauxv->a_type != AT_NULL; cauxv++) {
+      if (cauxv->a_type == AT_PLATFORM)
+	 stringsize += strlen(cauxv->a_ptr) + 1;
+      auxsize += sizeof(*cauxv);
+   }
+
+   /* OK, now we know how big the client stack is */
+   stacksize =
+      sizeof(int) +			/* argc */
+      sizeof(char **)*argc +		/* argv */
+      sizeof(char **) +			/* terminal NULL */
+      sizeof(char **)*envc +		/* envp */
+      sizeof(char **) +			/* terminal NULL */
+      auxsize +				/* auxv */
+      ROUNDUP(stringsize, sizeof(int));	/* strings (aligned) */
+
+   /* cl_esp is the client's stack pointer */
+   cl_esp = client_end - stacksize;
+   cl_esp = ROUNDDN(cl_esp, 16); /* make stack 16 byte aligned */
+
+   if (0)
+      printf("stringsize=%d auxsize=%d stacksize=%d\n",
+	     stringsize, auxsize, stacksize);
+
+   /* base of the string table (aligned) */
+   stringbase = strtab = (char *)(client_end - ROUNDUP(stringsize, sizeof(int)));
+
+   kp.clstk_base = PGROUNDDN(cl_esp);
+   kp.clstk_end = client_end;
+
+   /* ==================== allocate space ==================== */
+
+   /* allocate a stack - mmap enough space for the stack */
+   mmap((void *)PGROUNDDN(cl_esp),
+	client_end - PGROUNDDN(cl_esp),
+	PROT_READ | PROT_WRITE | PROT_EXEC, 
+	MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
+   
+
+   /* ==================== copy client stack ==================== */
+
+   ptr = (addr_t *)cl_esp;
+
+   /* --- argc --- */
+   *ptr++ = argc;		/* client argc */
+
+   /* --- argv --- */
+   if (info->argv0) {
+      *ptr++ = (addr_t)copy_str(&strtab, info->argv0);
+      free(info->argv0);
+   }
+   if (info->argv1) {
+      *ptr++ = (addr_t)copy_str(&strtab, info->argv1);
+      free(info->argv1);
+   }
+   for(cpp = orig_argv; *cpp; ptr++, cpp++) {
+      *ptr = (addr_t)copy_str(&strtab, *cpp);
+   }
+   *ptr++ = 0;
+
+   /* --- envp --- */
+   kp.client_envp = (Char **)ptr;
+   for(cpp = orig_envp; cpp && *cpp; ptr++, cpp++)
+      *ptr = (addr_t)copy_str(&strtab, *cpp);
+   *ptr++ = 0;
+
+   /* --- auxv --- */
+   auxv = (struct ume_auxv *)ptr;
+   kp.client_auxv = (UInt *)auxv;
+
+   for(; orig_auxv->a_type != AT_NULL; auxv++, orig_auxv++) {
+      /* copy the entry... */
+      *auxv = *orig_auxv;
+
+      /* ...and fix up the copy */
+      switch(auxv->a_type) {
+      case AT_PHDR:
+	 if (info->phdr == 0)
+	    auxv->a_type = AT_IGNORE;
+	 else
+	    auxv->a_val = info->phdr;
+	 break;
+
+      case AT_PHNUM:
+	 if (info->phdr == 0)
+	    auxv->a_type = AT_IGNORE;
+	 else
+	    auxv->a_val = info->phnum;
+	 break;
+
+      case AT_BASE:
+	 if (info->interp_base == 0)
+	    auxv->a_type = AT_IGNORE;
+	 else
+	    auxv->a_val = info->interp_base;
+	 break;
+
+      case AT_PLATFORM:		/* points to a platform description string */
+	 auxv->a_ptr = copy_str(&strtab, orig_auxv->a_ptr);
+	 break;
+
+      case AT_ENTRY:
+	 auxv->a_val = info->entry;
+	 break;
+
+      case AT_IGNORE:
+      case AT_EXECFD:
+      case AT_PHENT:
+      case AT_PAGESZ:
+      case AT_FLAGS:
+      case AT_NOTELF:
+      case AT_UID:
+      case AT_EUID:
+      case AT_GID:
+      case AT_EGID:
+      case AT_CLKTCK:
+      case AT_HWCAP:
+      case AT_FPUCW:
+      case AT_DCACHEBSIZE:
+      case AT_ICACHEBSIZE:
+      case AT_UCACHEBSIZE:
+	 /* All these are pointerless, so we don't need to do anything
+	    about them. */
+	 break;
+
+      case AT_SECURE:
+	 /* If this is 1, then it means that this program is running
+	    suid, and therefore the dynamic linker should be careful
+	    about LD_PRELOAD, etc.  However, since stage1 (the thing
+	    the kernel actually execve's) should never be SUID, and we
+	    need LD_PRELOAD/LD_LIBRARY_PATH to work for the client, we
+	    set AT_SECURE to 0. */
+	 auxv->a_val = 0;
+	 break;
+
+#if 1
+      case AT_SYSINFO:
+      case AT_SYSINFO_EHDR:
+	 /* trash vsyscalls for now
+				   
+  	    XXX should probably replace with our own sysinfo page so
+  	    we can intercept sysenter syscalls too - or at least note
+  	    the address so that we can catch jumps here
+	 */
+	 auxv->a_type = AT_IGNORE;
+	 break;
+#endif
+
+      default:
+	 /* stomp out anything we don't know about */
+	 if (0)
+	    printf("stomping auxv entry %d\n", auxv->a_type);
+	 auxv->a_type = AT_IGNORE;
+	 break;
+	 
+      }
+   }
+   *auxv = *orig_auxv;
+   assert(auxv->a_type == AT_NULL);
+
+   assert((strtab-stringbase) == stringsize);
+
+   return cl_esp;
+}
+
+/* Find and load a tool.  Also looks to see if there's a matching
+   vgpreload_*.so file, and returns its name in *preloadpath. */
+static void *load_tool(const char *name, char **preloadpath)
+{
+   int len = strlen(valgrind_lib) + strlen(name)*2 + 16;
+   char buf[len];
+   void *ret;
+
+   *preloadpath = NULL;
+
+   if (strchr(name, '/') != 0) {
+      /* name contains '/', and so must be a pathname */
+      ret = dlopen(name, RTLD_NOW);
+   } else {
+      /* just try in the libdir */
+      snprintf(buf, len, "%s/vgskin_%s.so", valgrind_lib, name);
+      ret = dlopen(buf, RTLD_NOW);
+
+      if (ret != NULL) {
+	 snprintf(buf, len, "%s/vgpreload_%s.so", valgrind_lib, name);
+	 if (access(buf, R_OK) == 0)
+	    *preloadpath = strdup(buf);
+      }
+   }
+
+   return ret;
+}
+
+/* list the available tools */
+static void list_tools(void)
+{
+   DIR *dir = opendir(valgrind_lib);
+   struct dirent *de;
+   int first = 1;
+
+   if (dir == NULL) {
+      fprintf(stderr, "Can't open %s: %s (installation problem?)\n",
+	      valgrind_lib, strerror(errno));
+      return;
+   }
+
+   while((de = readdir(dir)) != NULL) {
+      int len = strlen(de->d_name);
+
+      /* look for vgskin_TOOL.so names */
+      if (len > (7+1+3) &&	/* "vgskin_" + at least on character tool name + ".so" */
+	  strncmp(de->d_name, "vgskin_", 7) == 0 &&
+	  strcmp(de->d_name + len - 3, ".so") == 0) {
+	 if (first) {
+	    printf("Available tools:\n");
+	    first = 0;
+	 }
+	 de->d_name[len-3] = '\0';
+	 printf("\t%s\n", de->d_name+7);
+      }
+   }
+
+   closedir(dir);
+
+   if (first)
+      printf("No tools available in \"%s\" (installation problem?)\n",
+	     valgrind_lib);
+}
+
+/* 
+   Prepare the client's environment.  This is basically a copy of our
+   environment, except:
+   1. LD_LIBRARY_PATH=$VALGRINDLIB:$LD_LIBRARY_PATH
+   2. LD_PRELOAD=$VALGRINDLIB/vg_inject.so:($VALGRINDLIB/vgpreload_TOOL.so:)?$LD_PRELOAD
+   3. LD_ASSUME_KERNEL=2.4.1
+
+   If any of these is missing, then it is added.
+
+   Yummy.  String hacking in C.
+
+   XXX If this needs to handle any more variables it should be hacked
+   into something table driven.
+ */
+static char **fix_environment(char **origenv, const char *preload)
+{
+   static const char inject_so[] = "vg_inject.so";
+   static const char ld_library_path[]   = "LD_LIBRARY_PATH=";
+   static const int  ld_library_path_len = sizeof(ld_library_path)-1;
+   static const char ld_preload[]   = "LD_PRELOAD=";
+   static const int  ld_preload_len = sizeof(ld_preload)-1;
+   static const char ld_assume_kernel[]   = "LD_ASSUME_KERNEL=";
+   static const int  ld_assume_kernel_len = sizeof(ld_assume_kernel)-1;
+   static const char valgrind_clo[]   = VALGRINDCLO "=";
+   static const char valgrind_clo_len = sizeof(valgrind_clo)-1;
+   int ld_preload_done       = 0;
+   int ld_library_path_done  = 0;
+   int ld_assume_kernel_done = 0;
+   char *inject_path;
+   int   inject_path_len;
+   int vgliblen = strlen(valgrind_lib);
+   char **cpp;
+   char **ret;
+   int envc;
+   const int preloadlen = (preload == NULL) ? 0 : strlen(preload);
+
+   /* Find the vg_inject.so; also make room for the tool preload
+      library */
+   inject_path_len = sizeof(inject_so) + vgliblen + preloadlen + 16;
+   inject_path = malloc(inject_path_len);
+
+   if (preload)
+      snprintf(inject_path, inject_path_len, "%s/%s:%s", 
+	       valgrind_lib, inject_so, preload);
+   else
+      snprintf(inject_path, inject_path_len, "%s/%s", 
+	       valgrind_lib, inject_so);
+   
+   /* Count the original size of the env */
+   envc = 0;			/* trailing NULL */
+   for(cpp = origenv; cpp && *cpp; cpp++)
+      envc++;
+
+   /* Allocate a new space */
+   ret = malloc(sizeof(char *) * (envc+3+1)); /* 3 new entries + NULL */
+
+   /* copy it over */
+   for(cpp = ret; *origenv; )
+      *cpp++ = *origenv++;
+   *cpp = NULL;
+   
+   assert(envc == (cpp - ret));
+
+   /* Walk over the new environment, mashing as we go */
+   for(cpp = ret; cpp && *cpp; cpp++) {
+      if (memcmp(*cpp, ld_library_path, ld_library_path_len) == 0) {
+	 int done = 0;
+	 int contains(const char *p) {
+	    if (strcmp(p, valgrind_lib) == 0) {
+	       done = 1;
+	       return 1;
+	    }
+	    return 0;
+	 }
+
+	 /* If the LD_LIBRARY_PATH already contains libdir, then don't
+	    bother adding it again, even if it isn't the first (it
+	    seems that the Java runtime will keep reexecing itself
+	    unless its paths are at the front of LD_LIBRARY_PATH) */
+	 scan_colsep(*cpp + ld_library_path_len, contains);
+
+	 if (!done) {
+	    int len = strlen(*cpp) + vgliblen*2 + 16;
+	    char *cp = malloc(len);
+
+	    snprintf(cp, len, "%s%s:%s",
+		     ld_library_path, valgrind_lib,
+		     (*cpp)+ld_library_path_len);
+
+	    *cpp = cp;
+	 }
+
+	 ld_library_path_done = 1;
+      } else if (memcmp(*cpp, ld_preload, ld_preload_len) == 0) {
+	 int len = strlen(*cpp) + inject_path_len;
+	 char *cp = malloc(len);
+
+	 snprintf(cp, len, "%s%s:%s",
+		  ld_preload, inject_path, (*cpp)+ld_preload_len);
+
+	 *cpp = cp;
+	 
+	 ld_preload_done = 1;
+      } else if (memcmp(*cpp, ld_assume_kernel, ld_assume_kernel_len) == 0) {
+	 *cpp = "LD_ASSUME_KERNEL=2.4.1";
+	 ld_assume_kernel_done = 1;
+      } else if (memcmp(*cpp, valgrind_clo, valgrind_clo_len) == 0) {
+	 *cpp = "";
+      }
+   }
+
+   /* Add the missing bits */
+
+   if (!ld_library_path_done) {
+      int len = ld_library_path_len + vgliblen*2 + 16;
+      char *cp = malloc(len);
+
+      snprintf(cp, len, "%s%s",
+	       ld_library_path, valgrind_lib);
+
+      ret[envc++] = cp;
+   }
+
+   if (!ld_preload_done) {
+      int len = ld_preload_len + inject_path_len;
+      char *cp = malloc(len);
+      
+      snprintf(cp, len, "%s%s",
+	       ld_preload, inject_path);
+      
+      ret[envc++] = cp;
+   }
+
+   if (!ld_assume_kernel_done)
+      ret[envc++] = "LD_ASSUME_KERNEL=2.4.1";
+      
+   ret[envc] = NULL;
+
+   return ret;
+}
+
+extern char **environ;		/* our environment */
+
+int main(int argc, char **argv)
+{
+   int vg_argc;
+   char **vg_argv;
+   char **cl_argv;
+   const char *tool = NULL;
+   const char *exec = NULL;
+   float ratio = 0.;	/* ratio of client bytes:shadow bytes */
+   addr_t valgrind_base, valgrind_mmap_end;
+   addr_t shadow_base, shadow_end, shadow_size;
+   struct exeinfo info;
+   ToolInfo *toolinfo = NULL;
+   void *dl_handle;
+   char *preload;		/* tool-specific LD_PRELOAD .so */
+   int ok;
+   char *env_clo;
+   int i;
+
+   if (!scan_auxv()) {
+      fprintf(stderr, "stage2 must be launched by stage1\n");
+      exit(1);
+   }
+
+   if (0) {
+      int prmap(void *start, void *end, const char *perm, off_t off, int maj, int min, int ino) {
+	 printf("mapping %10p-%10p %s %02x:%02x %d\n",
+		start, end, perm, maj, min, ino);
+	 return 1;
+      }
+      printf("========== stage2 ==========\n");
+      foreach_map(prmap);
+   }
+
+   /* Pad out client's part of memory, so that we don't accidentally
+      put things there - do this before anything else */
+   valgrind_mmap_end = (addr_t)&kickstart_base; /* end of valgrind's mmaps */
+   valgrind_base =  valgrind_mmap_end - VALGRIND_MAPSIZE;
+   as_pad((void *)CLIENT_BASE, (void *)valgrind_base);
+
+   /* Work out if we're getting our main set of arguments from the
+      command line or from the environment (_VALGRIND_CLO). */
+   env_clo = getenv(VALGRINDCLO);
+   if (env_clo != NULL && *env_clo != '\0') {
+      char *cp;
+      char **cpp;
+
+      /* OK, we're getting all our arguments from the environment -
+	 the entire command line belongs to the client (including
+	 argv[0]) */
+      vg_argc = 1;		/* argv[0] */
+      for(cp = env_clo; *cp; cp++)
+	 if (*cp == '\01')
+	    vg_argc++;
+
+      vg_argv = malloc(sizeof(char **) * (vg_argc + 1));
+
+      cpp = vg_argv;
+
+      *cpp++ = "valgrind";	/* nominal argv[0] */
+      *cpp++ = env_clo;
+
+      for(cp = env_clo;
+	  *cp; cp++) {
+	 if (*cp == '\01') {
+	    *cp++ = '\0';	/* chop it up in place */
+	    *cpp++ = cp;
+	 }
+      }
+      *cpp = NULL;
+      cl_argv = argv;
+
+      if (0)
+	 for(i = 0; i < vg_argc; i++)
+	    printf("vg_argv[%d]=\"%s\"\n", i, vg_argv[i]);
+   } else {
+      /* Count the arguments on the command line. */
+      vg_argv = argv;
+
+      for(vg_argc = 1; vg_argc < argc; vg_argc++) {
+	 if (argv[vg_argc][0] != '-') /* exe name */
+	    break;
+	 if (strcmp(argv[vg_argc], "--") == 0) { /* dummy arg */
+	    vg_argc++;
+	    break;
+	 }
+      }
+      
+      cl_argv = &argv[vg_argc];
+
+      if (cl_argv[0] == NULL) {
+	 VG_(usage)();
+	 exit(1);
+      }
+   }
+
+   /* look for additional user-set options from the environment (VALGRIND_OPTS) */
+   env_clo = getenv(VALGRINDOPTS);
+   if (env_clo && *env_clo) {
+      /* ' ' separated extra options */
+      char *cp;
+      char **from;
+      char **to;
+      char **new_argv;
+      int count;
+      
+      count = 1;
+      for(cp = env_clo; *cp; cp++)
+	 if (*cp == ' ' || *cp == '\t') {
+	    while(cp[1] == ' ' || cp[1] == '\t')
+	       cp++;
+	    count++;
+	 }
+
+      if (0)
+	 printf("VALGRIND_OPTS=%s argc=%d\n",
+		env_clo, count);
+
+      new_argv = malloc((vg_argc + count + 3) * sizeof(char **));
+      
+      from = vg_argv;
+      to = new_argv;
+
+      *to++ = *from++;		/* copy argv[0] */
+
+      /* add args out of environment, skipping multiple spaces and --
+	 args */
+      *to++ = env_clo;
+      for(cp = env_clo; *cp; cp++) 
+	 if (*cp == ' ' || *cp == '\t') {
+	    *cp = '\0';
+	    while(cp[1] == ' ' || cp[1] == '\t')
+	       cp++;
+	    if (strcmp(to[-1], "--") == 0) {
+	       to--;
+	    }
+
+	    *to++ = cp+1;
+	 }
+
+      /* copy original arguments, stopping at command or -- */
+      while(*from) {
+	 if (**from != '-')
+	    break;
+	 if (strcmp(*from, "--") == 0) {
+	    from++;		/* skip -- */
+	    break;
+	 }
+	 *to++ = *from++;
+      }
+
+      /* add -- if not already present */
+      if (strcmp(to[-1], "--") != 0)
+	 *to++ = "--";
+
+      vg_argc = to-new_argv;
+
+      /* reset of original command line */
+      while(*from)
+	 *to++ = *from++;
+
+      *to = NULL;
+      
+      vg_argv = new_argv;
+
+      if (0)
+	 for(i = 0; i < vg_argc; i++)
+	    printf("vg_argv[%d]=%s\n",
+		   i, vg_argv[i]);
+   }
+
+   /* parse the options we have */
+   for(i = 1; i < vg_argc; i++) {
+      if (0)
+	 printf("vg_argv[%d]=%s\n",
+		i, vg_argv[i]);
+      if (strncmp(vg_argv[i], "--tool=", 7) == 0 ||
+	  strncmp(vg_argv[i], "--skin=", 7) == 0)
+	 tool = &vg_argv[i][7];
+	 
+      if (strncmp(vg_argv[i], "--exec=", 7) == 0)
+	 exec = &vg_argv[i][7];
+   }
+
+   if (tool == NULL) {
+      if (tool == NULL)
+	 list_tools();
+
+      if (0) {
+	 for(i = 0; i < argc; i++)
+	    fprintf(stderr, "argv[%d%s]=%s\n", i, i==vg_argc?"*":"", argv[i]);
+	 fprintf(stderr, "tool=%s\n", tool);
+      }
+
+      VG_(usage)();
+      exit(1);
+   }
+
+   /* If they didn't specify an executable, then use client argv[0] - 
+      search $PATH if it isn't already specified */
+   if (exec == NULL) {
+      exec = cl_argv[0];
+
+      if (strchr(exec, '/') == NULL) {
+	 /* no '/' - we need to search the path */
+	 char *path = getenv("PATH");
+	 int pathlen = path ? strlen(path) : 0;
+
+	 int match_exe(const char *entry) {
+	    char buf[pathlen + strlen(entry) + 3];
+
+	    /* empty PATH element means . */
+	    if (*entry == '\0')
+	       entry = ".";
+
+	    snprintf(buf, sizeof(buf), "%s/%s", entry, exec);
+
+	    if (access(buf, R_OK|X_OK) == 0) {
+	       exec = strdup(buf);
+	       return 1;
+	    }
+	    return 0;
+	 }
+
+	 scan_colsep(path, match_exe);
+      }
+   }
+
+   /* Look to see if we should be finding our pieces elsewhere */
+   {
+      char *cp = getenv(VALGRINDLIB);
+      if (cp != NULL)
+	 valgrind_lib = cp;
+   }
+
+   /* While the client part of the address space is all padded
+      out, map in valgrind+tool proper */
+   ok = 1;
+
+   dl_handle = load_tool(tool, &preload);
+
+   if (dl_handle == NULL) {
+      fprintf(stderr, "Can't open tool \"%s\": %s\n", tool, dlerror());
+      ok = 0;
+   } 
+   if (ok) {
+      Int *vg_malloc_redzonep = NULL;
+
+      toolinfo = dlsym(dl_handle, "vgSkin_tool_info");
+
+      if (toolinfo == NULL) {
+	 fprintf(stderr, "Tool \"%s\" doesn't define SK_(tool_info) - add VG_DETERMINE_INTERFACE_VERSION?\n", tool);
+	 ok = 0;
+      }
+
+      if (ok && 
+	  (toolinfo->sizeof_ToolInfo != sizeof(*toolinfo) ||
+	   toolinfo->interface_major_version != VG_CORE_INTERFACE_MAJOR_VERSION ||
+	   toolinfo->sk_pre_clo_init == NULL)) {
+	 fprintf(stderr, "Error:\n"
+		 "  Tool and core interface versions do not match.\n"
+		 "  Interface version used by core is: %d.%d (size %d)\n"
+		 "  Interface version used by tool is: %d.%d (size %d)\n"
+		 "  The major version numbers must match.\n",
+		 VG_CORE_INTERFACE_MAJOR_VERSION, 
+		 VG_CORE_INTERFACE_MINOR_VERSION,
+		 sizeof(*toolinfo),
+		 toolinfo->interface_major_version,
+		 toolinfo->interface_minor_version, 
+		 toolinfo->sizeof_ToolInfo);
+	 fprintf(stderr, "  You need to at least recompile, and possibly update,\n");
+	 if (VG_CORE_INTERFACE_MAJOR_VERSION > toolinfo->interface_major_version)
+	    fprintf(stderr, "  your skin to work with this version of Valgrind.\n");
+	 else
+	    fprintf(stderr, "  your version of Valgrind to work with this skin.\n");
+	 fprintf(stderr, "  Aborting, sorry.\n");
+
+	 ok = 0;
+      }
+
+      ratio = toolinfo->shadow_ratio;
+
+      /* If the tool wants a different malloc heap redzone size, then
+	 set it up here, before we start using the core's
+	 allocator. */
+      if (ok && (vg_malloc_redzonep = dlsym(dl_handle, STR(VG_(vg_malloc_redzone_szB)))) != NULL)
+	 VG_(vg_malloc_redzone_szB) = *vg_malloc_redzonep;
+   }
+
+   if (!ok) {
+      if (dl_handle != NULL)
+	 dlclose(dl_handle);
+
+      fprintf(stderr, "Aborting: couldn't initialize valgrind\n");
+      list_tools();
+      exit(1);
+   }
+   
+   /* Work out overall shape of the address space. This tries to give
+      the client as large as possible address space while taking into
+      account the tool's shadow needs.  */
+   client_size = ROUNDDN((valgrind_base - REDZONE_SIZE) / (1. + ratio), CLIENT_SIZE_MULTIPLE);
+   client_end = CLIENT_BASE + client_size;
+
+   shadow_size = PGROUNDUP(client_size * ratio);
+   shadow_base = client_end + REDZONE_SIZE;
+   shadow_end = shadow_base + shadow_size;
+
+   if (0)
+      printf("valgrind_base=%x client_size=%x shadow=%x-%x (%x)\n", 
+	     valgrind_base, client_size,
+	     shadow_base, shadow_end, shadow_size);
+   
+   /* make the redzone inaccessible */
+   mmap((void *)client_end, REDZONE_SIZE, PROT_NONE,
+	MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
+
+   munmap(CLIENT_BASE, client_size);	/* make client hole */
+
+   kp.client_mapbase = PGROUNDDN((client_size/4)*3); /* where !FIXED mmap goes */
+
+   info.exe_base = client_base;
+   info.exe_end  = client_end;
+   info.map_base = kp.client_mapbase;
+
+   info.setbrk = 0;
+   info.argv = cl_argv;
+
+   {
+      int ret = do_exec(exec, &info);
+      if (ret != 0) {
+	 fprintf(stderr, "do_exec(%s) failed: %s\n", exec, strerror(ret));
+	 exit(1);
+      }
+   }
+
+   /* Shadow memory - initially all inaccessible, but then
+      incrementally initialized as it is used */
+   if (shadow_size != 0)
+      mmap((char *)shadow_base, shadow_size, PROT_NONE,
+	   MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0);
+
+   /* unpad us */
+   as_unpad((void *)shadow_end, (void *)~0);
+
+   {
+      char **env;
+      const struct ume_auxv *auxv;
+
+      /* use our own auxv as a prototype */
+      auxv = find_auxv(ume_exec_esp);
+
+      /* set up the client's environment */
+      env = fix_environment(environ, preload);
+
+      /* client's stack and eip */
+      kp.client_esp = setup_client_stack(cl_argv, env, auxv, &info);
+      kp.client_eip = info.init_eip;
+   }
+
+   /* Valgrind's argc/argv */
+   kp.argc = vg_argc;
+   kp.argv = (Char **)vg_argv;
+   kp.libdir = valgrind_lib;
+
+   /* client address space */
+   kp.client_base = CLIENT_BASE;
+   kp.client_end = client_end;
+   kp.client_brkbase = info.brkbase;
+
+   /* shadow segment */
+   kp.shadow_base = shadow_base;
+   kp.shadow_end = shadow_end;
+
+   /* valgrind address space */
+   kp.vg_base = valgrind_base;
+   kp.vg_mmap_end = valgrind_mmap_end;
+   kp.vg_end = ROUNDUP((Addr)&argc, 0x10000);		/* stack */
+
+   as_closepadfile();		/* no more padding */
+
+   if (0)
+      printf("entry=%x client esp=%x vg_argc=%d brkbase=%x\n",
+	     kp.client_eip, kp.client_esp, kp.argc, kp.client_brkbase);
+
+#if 1
+   VG_(main)(&kp, toolinfo->sk_pre_clo_init, dl_handle);
+#else
+   ume_go(kp.client_eip, kp.client_esp);
+#endif
+
+   abort();
+}
diff --git a/coregrind/toolfuncs.def b/coregrind/toolfuncs.def
new file mode 100644
index 0000000..c4d9577
--- /dev/null
+++ b/coregrind/toolfuncs.def
@@ -0,0 +1,302 @@
+# Tool interface functions
+# The format for an interface function definition is:
+#	return_type,	func_name,	type arg, type arg
+# If the function has no arguments, specify no arguments (rather than void)
+#
+# Comments starting with "##" are turned into C comments in the output
+#
+# Lines starting with : set the prefix
+
+## These are the parameterised functions in the core.  The default definitions
+## are overridden by LD_PRELOADed skin version.  At the very least, a skin
+## must define the fundamental template functions.  Depending on what needs
+## are set, extra template functions will be used too.  Functions are
+## grouped under the needs that govern their use.
+
+:tool
+## ------------------------------------------------------------------
+## Fundamental template functions
+
+## Do initialisation that can only be done after command line processing.
+void,		post_clo_init
+
+## Instrument a basic block.  Must be a true function, ie. the same input
+## always results in the same output, because basic blocks can be
+## retranslated.  Unless you're doing something really strange...
+## 'orig_addr' is the address of the first instruction in the block.
+UCodeBlock*,	instrument,	UCodeBlock* cb, Addr orig_addr
+
+## Finish up, print out any results, etc.  `exitcode' is program's exit
+## code.  The shadow (if the `shadow_regs' need is set) can be found with
+## VG_(get_shadow_archreg)(R_EBX), since %ebx holds the argument to the
+## exit() syscall.
+void,	fini,	Int exitcode
+
+
+## ------------------------------------------------------------------
+## VG_(needs).core_errors
+
+## (none needed)
+
+## ------------------------------------------------------------------
+## VG_(needs).skin_errors
+
+## Identify if two errors are equal, or equal enough.  `res' indicates how
+## close is "close enough".  `res' should be passed on as necessary, eg. if
+## the Error's `extra' part contains an ExeContext, `res' should be
+## passed to VG_(eq_ExeContext)() if the ExeContexts are considered.  Other
+## than that, probably don't worry about it unless you have lots of very
+## similar errors occurring.
+Bool,	eq_SkinError,	VgRes res, Error* e1, Error* e2
+
+## Print error context.
+void,	pp_SkinError,	Error* err
+
+## Should fill in any details that could be postponed until after the
+## decision whether to ignore the error (ie. details not affecting the
+## result of SK_(eq_SkinError)()).  This saves time when errors are ignored.
+## Yuk.
+
+## Return value: must be the size of the `extra' part in bytes -- used by
+## the core to make a copy.
+UInt,	update_extra,	Error* err
+
+## Return value indicates recognition.  If recognised, must set skind using
+## VG_(set_supp_kind)().
+Bool,	recognised_suppression,	Char* name, Supp* su
+
+## Read any extra info for this suppression kind.  Most likely for filling
+## in the `extra' and `string' parts (with VG_(set_supp_{extra, string})())
+## of a suppression if necessary.  Should return False if a syntax error
+## occurred, True otherwise.
+Bool,	read_extra_suppression_info,	Int fd, Char* buf, Int nBuf, Supp* su
+
+## This should just check the kinds match and maybe some stuff in the
+## `string' and `extra' field if appropriate (using VG_(get_supp_*)() to
+## get the relevant suppression parts).
+Bool,	error_matches_suppression,		Error* err, Supp* su
+
+## This should return the suppression name, for --gen-suppressions, or NULL
+## if that error type cannot be suppressed.  This is the inverse of
+## SK_(recognised_suppression)().
+Char*,	get_error_name,			Error* err
+
+## This should print any extra info for the error, for --gen-suppressions,
+## including the newline.  This is the inverse of
+## SK_(read_extra_suppression_info)().
+void,	print_extra_suppression_info,	Error* err
+
+
+## ------------------------------------------------------------------
+## VG_(needs).basic_block_discards
+
+## Should discard any information that pertains to specific basic blocks
+## or instructions within the address range given.
+void,	discard_basic_block_info,		Addr a, UInt size
+
+
+## ------------------------------------------------------------------
+## VG_(needs).shadow_regs
+
+## No functions must be defined, but the post_reg[s]_write_* events should
+## be tracked.
+
+## ------------------------------------------------------------------
+## VG_(needs).command_line_options
+
+## Return True if option was recognised.  Presumably sets some state to
+## record the option as well.
+Bool,	process_cmd_line_option,	Char* argv
+
+## Print out command line usage for options for normal skin operation.
+void,	print_usage
+
+## Print out command line usage for options for debugging the skin.
+void,	print_debug_usage
+
+## ------------------------------------------------------------------
+## VG_(needs).client_requests
+
+## If using client requests, the number of the first request should be equal
+## to VG_USERREQ_SKIN_BASE('X', 'Y'), where 'X' and 'Y' form a suitable two
+## character identification for the string.  The second and subsequent
+## requests should follow.
+
+## This function should use the VG_IS_SKIN_USERREQ macro (in
+## include/valgrind.h) to first check if it's a request for this skin.  Then
+## should handle it if it's recognised (and return True), or return False if
+## not recognised.  arg_block[0] holds the request number, any further args
+## from the request are in arg_block[1..].  'ret' is for the return value...
+## it should probably be filled, if only with 0.
+Bool, handle_client_request, ThreadId tid, UInt* arg_block, UInt* ret
+
+
+## ------------------------------------------------------------------
+## VG_(needs).extends_UCode
+
+## 'X' prefix indicates eXtended UCode.
+Int, get_Xreg_usage, UInstr* u, Tag tag, Int* regs, Bool* isWrites
+void, emit_XUInstr, UInstr* u, RRegSet regs_live_before
+Bool, sane_XUInstr, Bool beforeRA, Bool beforeLiveness, UInstr* u
+Char *, name_XUOpcode, Opcode opc
+void, pp_XUInstr, UInstr* u
+
+
+## ------------------------------------------------------------------
+## VG_(needs).syscall_wrapper
+
+## If either of the pre_ functions malloc() something to return, the
+## corresponding post_ function had better free() it!
+
+void *, pre_syscall, ThreadId tid, UInt syscallno, Bool is_blocking
+void, post_syscall, ThreadId tid, UInt syscallno, void* pre_result, Int res, Bool is_blocking
+
+
+## ---------------------------------------------------------------------
+##   VG_(needs).sanity_checks
+
+## Can be useful for ensuring a skin's correctness.  SK_(cheap_sanity_check)
+## is called very frequently;  SK_(expensive_sanity_check) is called less
+## frequently and can be more involved.
+Bool, cheap_sanity_check
+Bool, expensive_sanity_check
+
+
+## ================================================================================
+## Event tracking functions
+:track
+
+## Events happening in core to track.  To be notified, pass a callback
+## function to the appropriate function.  To ignore an event, don't do
+## anything (default is for events to be ignored).
+
+## Note that most events aren't passed a ThreadId.  To find out the ThreadId
+## of the affected thread, use VG_(get_current_or_recent_tid)().  For the
+## ones passed a ThreadId, use that instead, since
+## VG_(get_current_or_recent_tid)() might not give the right ThreadId in
+## that case.
+
+## Memory events (Nb: to track heap allocation/freeing, a skin must replace
+## malloc() et al.  See above how to do this.)
+
+## These ones occur at startup, upon some signals, and upon some syscalls
+void,	new_mem_startup,	Addr a, UInt len, Bool rr, Bool ww, Bool xx
+void,	new_mem_stack_signal,	Addr a, UInt len
+void,	new_mem_brk,	Addr a, UInt len
+void,	new_mem_mmap,	Addr a, UInt len, Bool rr, Bool ww, Bool xx
+
+void,	copy_mem_remap,	Addr from, Addr to, UInt len
+void,	change_mem_mprotect,	Addr a, UInt len, Bool rr, Bool ww, Bool xx
+void,	die_mem_stack_signal,	Addr a, UInt len
+void,	die_mem_brk,	Addr a, UInt len
+void,	die_mem_munmap,	Addr a, UInt len
+
+## These ones are called when %esp changes.  A skin could track these itself
+## (except for ban_mem_stack) but it's much easier to use the core's help.
+
+## The specialised ones are called in preference to the general one, if they
+## are defined.  These functions are called a lot if they are used, so
+## specialising can optimise things significantly.  If any of the
+## specialised cases are defined, the general case must be defined too.
+
+## Nb: they must all use the __attribute__((regparm(n))) attribute.
+void,	new_mem_stack_4,	Addr new_ESP
+void,	new_mem_stack_8,	Addr new_ESP
+void,	new_mem_stack_12,	Addr new_ESP
+void,	new_mem_stack_16,	Addr new_ESP
+void,	new_mem_stack_32,	Addr new_ESP
+void,	new_mem_stack,	Addr a, UInt len
+
+void,	die_mem_stack_4,	Addr die_ESP
+void,	die_mem_stack_8,	Addr die_ESP
+void,	die_mem_stack_12,	Addr die_ESP
+void,	die_mem_stack_16,	Addr die_ESP
+void,	die_mem_stack_32,	Addr die_ESP
+void,	die_mem_stack,	Addr a, UInt len
+
+## Used for redzone at end of thread stacks
+void,	ban_mem_stack,	Addr a, UInt len
+
+## These ones occur around syscalls, signal handling, etc
+void,	pre_mem_read,	CorePart part, ThreadId tid, Char* s, Addr a, UInt size
+void,	pre_mem_read_asciiz,	CorePart part, ThreadId tid, Char* s, Addr a
+void,	pre_mem_write,	CorePart part, ThreadId tid, Char* s, Addr a, UInt size
+## Not implemented yet -- have to add in lots of places, which is a
+## pain.  Won't bother unless/until there's a need.
+## void (*post_mem_read)  ( ThreadState* tst, Char* s, Addr a, UInt size );
+void,	post_mem_write,	Addr a, UInt size
+
+
+## Register events -- if `shadow_regs' need is set, all should probably be
+## used.  Use VG_(set_thread_shadow_archreg)() to set the shadow of the
+## changed register.
+
+## Use VG_(set_shadow_archreg)() to set the eight general purpose regs,
+## and use VG_(set_shadow_eflags)() to set eflags.
+void,	post_regs_write_init,	void
+
+## Use VG_(set_thread_shadow_archreg)() to set the shadow regs for these
+## events.
+void,	post_reg_write_syscall_return,	ThreadId tid, UInt reg
+void,	post_reg_write_deliver_signal,	ThreadId tid, UInt reg
+void,	post_reg_write_pthread_return,	ThreadId tid, UInt reg
+void,	post_reg_write_clientreq_return,	ThreadId tid, UInt reg
+## This one is called for malloc() et al if they are replaced by a skin.
+void,	post_reg_write_clientcall_return,	ThreadId tid, UInt reg, Addr f
+
+
+## Scheduler events (not exhaustive)
+void,	thread_run,	ThreadId tid
+
+
+## Thread events (not exhaustive)
+
+## Called during thread create, before the new thread has run any
+## instructions (or touched any memory).
+void,	post_thread_create,	ThreadId tid, ThreadId child
+void,	post_thread_join,	ThreadId joiner, ThreadId joinee
+
+
+## Mutex events (not exhaustive)
+## "void *mutex" is really a pthread_mutex *
+
+## Called before a thread can block while waiting for a mutex (called
+## regardless of whether the thread will block or not).
+void,	pre_mutex_lock,	ThreadId tid, void* mutex
+## Called once the thread actually holds the mutex (always paired with
+## pre_mutex_lock).
+void,	post_mutex_lock,	ThreadId tid, void* mutex
+## Called after a thread has released a mutex (no need for a corresponding
+## pre_mutex_unlock, because unlocking can't block).
+void,	post_mutex_unlock,	ThreadId tid, void* mutex
+
+## Signal events (not exhaustive)
+
+## ... pre_send_signal, post_send_signal ...
+
+## Called before a signal is delivered;  `alt_stack' indicates if it is
+## delivered on an alternative stack. 
+void,	 pre_deliver_signal,	ThreadId tid, Int sigNo, Bool alt_stack
+## Called after a signal is delivered.  Nb: unfortunately, if the signal
+## handler longjmps, this won't be called.
+void,	post_deliver_signal,	ThreadId tid, Int sigNo
+
+
+## Others... condition variable...
+## ...
+
+## Shadow memory management
+void,	init_shadow_page,	Addr p
+
+## ================================================================================
+## malloc and friends
+:malloc
+void*,	malloc,			Int n
+void*,	__builtin_new,		Int n
+void*,	__builtin_vec_new,	Int n
+void*,	memalign,		Int align, Int n
+void*,	calloc,			Int nmemb, Int n
+void,	free,			void* p
+void,	__builtin_delete,	void* p
+void,	__builtin_vec_delete,	void* p
+void*,	realloc,		void* p, Int size
diff --git a/coregrind/ume.c b/coregrind/ume.c
new file mode 100644
index 0000000..bf8fb15
--- /dev/null
+++ b/coregrind/ume.c
@@ -0,0 +1,652 @@
+/*
+  User-mode exec
+
+  This bootstraps Valgrind.  This code decides on the layout of the
+  client and Valgrind address spaces, loads valgrind.so and the
+  skin.so into the valgrind part, loads the client executable (and the
+  dynamic linker, if necessary) into the client part, and calls into
+  Valgrind proper.
+
+  The code is careful not to allow spurious mappings to appear in the
+  wrong parts of the address space.  In particular, to make sure
+  dlopen puts things in the right place, it will pad out the forbidden
+  chunks of address space so that dlopen is forced to put things where
+  we want them.
+
+  The memory map it creates is:
+
+  CLIENT_BASE    +-------------------------+
+                 | client address space    |
+	         :                         :
+	         :                         :
+		 | client stack            |
+  client_end     +-------------------------+
+                 | redzone                 |
+  shadow_base    +-------------------------+
+                 |                         |
+	         : shadow memory for skins :
+	         | (may be 0 sized)        |
+  shadow_end     +-------------------------+
+                 : gap (may be 0 sized)    :
+  valgrind_base  +-------------------------+
+                 | valgrind .so files      |
+		 | and mappings            |
+  valgrind_mmap_end                        -
+                 | kickstart executable    |
+                 -                         -
+                 | valgrind heap  vvvvvvvvv|
+  valgrind_end   -                         -
+		 | valgrind stack ^^^^^^^^^|
+                 +-------------------------+
+		 : kernel                  :
+ */
+
+#define _GNU_SOURCE
+#define _FILE_OFFSET_BITS 64
+
+#include "vg_include.h"
+
+#include <stddef.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <elf.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <asm/unistd.h>
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
+#include <dlfcn.h>
+#include <assert.h>
+
+#include "ume.h"
+
+static int padfile = -1;
+static struct stat padstat;
+
+extern int kickstart_base;	/* linker created */
+
+void foreach_map(int (*fn)(void *start, void *end,
+			   const char *perm, off_t offset,
+			   int maj, int min, int ino))
+{
+   static char buf[10240];
+   char *bufptr = buf;
+   int ret, fd;
+
+   fd = open("/proc/self/maps", O_RDONLY);
+
+   if (fd == -1) {
+      perror("open /proc/self/maps");
+      return;
+   }
+
+   ret = read(fd, buf, sizeof(buf));
+
+   if (ret == -1) {
+      perror("read /proc/self/maps");
+      close(fd);
+      return;
+   }
+   close(fd);
+
+   if (ret == sizeof(buf)) {
+      fprintf(stderr, "buf too small\n");
+      return;
+   }
+
+   while(bufptr && bufptr < buf+ret) {
+      char perm[5];
+      off_t offset;
+      int maj, min;
+      int ino;
+      void *segstart, *segend;
+
+      sscanf(bufptr, "%p-%p %s %Lx %x:%x %d",
+	     &segstart, &segend, perm, &offset, &maj, &min, &ino);
+      bufptr = strchr(bufptr, '\n');
+      if (bufptr != NULL)
+	 bufptr++; /* skip \n */
+
+      if (!(*fn)(segstart, segend, perm, offset, maj, min, ino))
+	 break;
+   }
+}
+
+/* pad all the empty spaces in a range of address space to stop
+   interlopers */
+void as_pad(void *start, void *end)
+{
+   char buf[1024];
+   char *addr;
+
+   int fillgap(void *segstart, void *segend, const char *perm, off_t off, 
+	       int maj, int min, int ino) {
+      if (segstart >= end)
+	 return 0;
+
+      if ((char *)segstart > addr)
+	 mmap(addr, (char *)segstart-addr, PROT_NONE, MAP_FIXED|MAP_PRIVATE,
+	      padfile, 0);
+      addr = segend;
+	 
+      return 1;
+   }
+
+   if (padfile == -1) {
+      int seq = 1;
+      do {
+	 sprintf(buf, "/tmp/.pad.%d.%d", getpid(), seq++);
+	 padfile = open(buf, O_RDWR|O_CREAT|O_EXCL, 0);
+	 unlink(buf);
+	 if (padfile == -1 && errno != EEXIST)
+	    exit(44);
+      } while(padfile == -1);
+      fstat(padfile, &padstat);
+   }
+
+   addr = start;
+
+   foreach_map(fillgap);
+	
+   if (addr < (char *)end)
+      mmap(addr, (char *)end-addr, PROT_NONE, MAP_FIXED|MAP_PRIVATE,
+	   padfile, 0);
+}
+
+/* remove padding from a range of address space - padding is always a
+   mapping of padfile*/
+void as_unpad(void *start, void *end)
+{
+   int killpad(void *segstart, void *segend, const char *perm, off_t off, 
+	       int maj, int min, int ino) {
+      void *b, *e;
+
+      if (padstat.st_dev != makedev(maj, min) || padstat.st_ino != ino)
+	 return 1;
+
+      if (segend <= start || segstart >= end)
+	 return 1;
+
+      if (segstart <= start)
+	 b = start;
+      else
+	 b = segstart;
+
+      if (segend >= end)
+	 e = end;
+      else
+	 e = segend;
+
+      munmap(b, (char *)e-(char *)b);
+
+      return 1;
+   }
+
+   if (padfile == -1)	/* no padfile, no padding */
+      return;
+
+   foreach_map(killpad);
+}
+
+void as_closepadfile(void)
+{
+   /* don't unpad */
+   close(padfile);
+   padfile = -1;
+}
+
+int as_getpadfd(void)
+{
+   return padfile;
+}
+
+void as_setpadfd(int fd)
+{
+   as_closepadfile();
+   padfile = fd;
+   fstat(padfile, &padstat);
+}
+
+struct ume_auxv *find_auxv(int *esp)
+{
+   esp++;			/* skip argc */
+
+   while(*esp != 0)		/* skip argv */
+      esp++;
+   esp++;
+
+   while(*esp != 0)		/* skip env */
+      esp++;
+   esp++;
+   
+   return (struct ume_auxv *)esp;
+}
+
+
+struct elfinfo *readelf(int fd, const char *filename)
+{
+   struct elfinfo *e = malloc(sizeof(*e));
+   int phsz;
+
+   e->fd = fd;
+
+   if (pread(fd, &e->e, sizeof(e->e), 0) != sizeof(e->e)) {
+      fprintf(stderr, "%s: can't read elf header: %s\n", 
+	      filename, strerror(errno));
+      return NULL;
+   }
+
+   if (memcmp(&e->e.e_ident[0], ELFMAG, SELFMAG) != 0) {
+      fprintf(stderr, "%s: bad ELF magic\n",
+	      filename);
+      return NULL;
+   }
+   if (e->e.e_ident[EI_CLASS] != ELFCLASS32) {
+      fprintf(stderr, "Can only handle 32-bit executables\n");
+      return NULL;
+   }
+   if (e->e.e_ident[EI_DATA] != ELFDATA2LSB) {
+      fprintf(stderr, "Expecting little-endian\n");
+      return NULL;
+   }
+   if (!(e->e.e_type == ET_EXEC || e->e.e_type == ET_DYN)) {
+      fprintf(stderr, "need executable\n");
+      return NULL;
+   }
+
+   if (e->e.e_machine != EM_386) {
+      fprintf(stderr, "need x86\n");
+      return NULL;
+   }
+
+   if (e->e.e_phentsize != sizeof(ESZ(Phdr))) {
+      fprintf(stderr, "sizeof Phdr wrong\n");
+      return NULL;
+   }
+
+   phsz = sizeof(ESZ(Phdr)) * e->e.e_phnum;
+   e->p = malloc(phsz);
+
+   if (pread(fd, e->p, phsz, e->e.e_phoff) != phsz) {
+      fprintf(stderr, "can't read phdr: %s\n", strerror(errno));
+      return NULL;
+   }
+
+   return e;
+}
+
+#define REMAINS(x, a)   ((x)        & ((a)-1))
+
+/* Map an ELF file.  Returns the brk address. */
+ESZ(Addr) mapelf(struct elfinfo *e, ESZ(Addr) base, int setbrk)
+{
+   int i;
+   ESZ(Addr) elfbrk = 0;
+
+   for(i = 0; i < e->e.e_phnum; i++) {
+      ESZ(Phdr) *ph = &e->p[i];
+      ESZ(Addr) addr, brkaddr;
+      ESZ(Word) memsz;
+
+      if (ph->p_type != PT_LOAD)
+	 continue;
+
+      addr = ph->p_vaddr+base;
+      memsz = ph->p_memsz;
+      brkaddr = addr+memsz;
+
+      if (brkaddr > elfbrk)
+	 elfbrk = brkaddr;
+   }
+
+   if (setbrk) {
+      /* sneaking up on the brk limit works better than actually
+	 jumping directly there.  Unfortunately, setting the brk is
+	 tested against the datasize rlimit, even though we're not
+	 actually using any memory. */
+      char *b = sbrk(0);
+      char *initb = (char *)PGROUNDUP(b);
+
+      while(b < (char *)elfbrk) {
+	 unsigned delta = (char *)elfbrk - b;
+	 static const unsigned limit = 256*1024*1024;
+	 char *bb;
+
+	 if (delta > limit)
+	    delta = limit;
+	 //printf("elfbrk=%p b=%p delta=%u\n", elfbrk, b, delta);
+	 bb = sbrk(delta);
+	 if (bb != b) {
+	    fprintf(stderr, "sbrk failed while adjusting brk base: "
+		    "perhaps we hit the datasize ulimit?\n");
+	    break;
+	 }
+	 b += delta;
+      }
+      munmap(initb, (char *)PGROUNDDN(elfbrk)-initb);
+   }
+
+   for(i = 0; i < e->e.e_phnum; i++) {
+      ESZ(Phdr) *ph = &e->p[i];
+      ESZ(Addr) addr, bss, brkaddr;
+      ESZ(Off) off;
+      ESZ(Word) filesz;
+      ESZ(Word) memsz;
+      ESZ(Word) align;
+      unsigned prot = 0;
+
+      if (ph->p_type != PT_LOAD)
+	 continue;
+
+      if (ph->p_flags & PF_X)
+	 prot |= PROT_EXEC;
+      if (ph->p_flags & PF_W)
+	 prot |= PROT_WRITE;
+      if (ph->p_flags & PF_R)
+	 prot |= PROT_READ;
+
+      align = ph->p_align;
+
+      addr = ph->p_vaddr+base;
+      off =  ph->p_offset;
+      filesz = ph->p_filesz;
+      bss = addr+filesz;
+      memsz = ph->p_memsz;
+      brkaddr = addr+memsz;
+
+      mmap((char *)ROUNDDN(addr, align), ROUNDUP(bss, align)-ROUNDDN(addr, align),
+	   prot, MAP_FIXED|MAP_PRIVATE, e->fd, ROUNDDN(off, align));
+
+      /* if memsz > filesz, then we need to fill the remainder with zeroed pages */
+      if (memsz > filesz) {
+	 UInt bytes;
+
+	 bytes = ROUNDUP(brkaddr, align)-ROUNDUP(bss, align);
+	 if (bytes > 0)
+	    mmap((char *)ROUNDUP(bss, align), bytes,
+		 prot, MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
+
+	 bytes = bss & (VKI_BYTES_PER_PAGE - 1);
+	 if (bytes > 0) {
+	    bytes = VKI_BYTES_PER_PAGE - bytes;
+	    memset((char *)bss, 0, bytes);
+	 }
+      }
+   }
+
+   return elfbrk;
+}
+
+
+static int do_exec_inner(const char *exe, struct exeinfo *info);
+
+
+static int match_ELF(const char *hdr, int len)
+{
+   ESZ(Ehdr) *e = (ESZ(Ehdr) *)hdr;
+   return (len > sizeof(*e)) && memcmp(&e->e_ident[0], ELFMAG, SELFMAG) == 0;
+}
+
+static int load_ELF(char *hdr, int len, int fd, const char *name, struct exeinfo *info)
+{
+   struct elfinfo *e;
+   struct elfinfo *interp = NULL;
+   ESZ(Addr) minaddr = ~0;
+   ESZ(Addr) maxaddr = 0;
+   ESZ(Addr) interp_addr = 0;
+   ESZ(Word) interp_size = 0;
+   int i;
+   void *entry;
+
+   e = readelf(fd, name);
+
+   if (e == NULL)
+      return ENOEXEC;
+
+   info->phnum = e->e.e_phnum;
+   info->entry = e->e.e_entry;
+
+   for(i = 0; i < e->e.e_phnum; i++) {
+      ESZ(Phdr) *ph = &e->p[i];
+
+      switch(ph->p_type) {
+      case PT_PHDR:
+	 info->phdr = ph->p_vaddr;
+	 break;
+
+      case PT_LOAD:
+	 if (ph->p_vaddr < minaddr)
+	    minaddr = ph->p_vaddr;
+	 if (ph->p_vaddr+ph->p_memsz > maxaddr)
+	    maxaddr = ph->p_vaddr+ph->p_memsz;
+	 break;
+			
+      case PT_INTERP: {
+	 char *buf = malloc(ph->p_filesz+1);
+	 int j;
+	 int intfd;
+	 int baseaddr_set;
+
+	 pread(fd, buf, ph->p_filesz, ph->p_offset);
+	 buf[ph->p_filesz] = '\0';
+
+	 intfd = open(buf, O_RDONLY);
+	 if (intfd == -1) {
+	    perror("open interp");
+	    exit(1);
+	 }
+
+	 interp = readelf(intfd, buf);
+	 if (interp == NULL) {
+	    fprintf(stderr, "Can't read interpreter\n");
+	    return 1;
+	 }
+	 free(buf);
+
+	 baseaddr_set = 0;
+	 for(j = 0; j < interp->e.e_phnum; j++) {
+	    ESZ(Phdr) *iph = &interp->p[j];
+	    ESZ(Addr) end;
+
+	    if (iph->p_type != PT_LOAD)
+	       continue;
+	    
+	    if (!baseaddr_set) {
+	       interp_addr = iph->p_vaddr;
+	       baseaddr_set = 1;
+	    }
+
+	    /* assumes that all segments in the interp are close */
+	    end = (iph->p_vaddr - interp_addr) + iph->p_memsz;
+
+	    if (end > interp_size)
+	       interp_size = end;
+	 }
+	 break;
+      }
+      }
+   }
+
+   if (info->exe_base != info->exe_end) {
+      if (minaddr >= maxaddr ||
+	  (minaddr < info->exe_base ||
+	   maxaddr > info->exe_end)) {
+	 fprintf(stderr, "Executable is mapped outside of range %p-%p\n",
+		 (void *)info->exe_base, (void *)info->exe_end);
+	 return ENOMEM;
+      }
+   }
+
+   info->brkbase = mapelf(e, 0, info->setbrk);		/* map the executable */
+
+   if (interp != NULL) {
+      /* reserve a chunk of address space for interpreter */
+      char *base = (char *)info->exe_base;
+      char *baseoff;
+      int flags = MAP_PRIVATE|MAP_ANONYMOUS;
+
+      if (info->map_base != 0) {
+	 base = (char *)info->map_base;
+	 flags |= MAP_FIXED;
+      }
+
+      base = mmap(base, interp_size, PROT_NONE, flags, -1, 0);
+
+      baseoff = base - interp_addr;
+
+      mapelf(interp, (ESZ(Addr))baseoff, 0);
+
+      close(interp->fd);
+      free(interp);
+
+      entry = baseoff + interp->e.e_entry;
+      info->interp_base = (ESZ(Addr))base;
+   } else
+      entry = (void *)e->e.e_entry;
+
+   info->exe_base = minaddr;
+   info->exe_end = maxaddr;
+
+   info->init_eip = (addr_t)entry;
+
+   free(e);
+
+   return 0;
+}
+
+
+static int match_script(const char *hdr, Int len)
+{
+   return (len > 2) && memcmp(hdr, "#!", 2) == 0;
+}
+
+static int load_script(char *hdr, int len, int fd, const char *name, struct exeinfo *info)
+{
+   char *interp;
+   char *const end = hdr+len;
+   char *cp;
+   char *arg = NULL;
+   int eol;
+
+   interp = hdr + 2;
+   while(interp < end && (*interp == ' ' || *interp == '\t'))
+      interp++;
+
+   if (*interp != '/')
+      return ENOEXEC;		/* absolute path only for interpreter */
+
+   /* skip over interpreter name */
+   for(cp = interp; cp < end && *cp != ' ' && *cp != '\t' && *cp != '\n'; cp++)
+      ;
+
+   eol = (*cp == '\n');
+
+   *cp++ = '\0';
+
+   if (!eol && cp < end) {
+      /* skip space before arg */
+      while (cp < end && (*cp == '\t' || *cp == ' '))
+	 cp++;
+
+      /* arg is from here to eol */
+      arg = cp;
+      while (cp < end && *cp != '\n')
+	 cp++;
+      *cp = '\0';
+   }
+   
+   info->argv0 = strdup(interp);
+   if (arg != NULL && *arg != '\0')
+      info->argv1 = strdup(arg);
+
+   if (info->argv && info->argv[0] != NULL)
+      info->argv[0] = (char *)name;
+
+   if (0)
+      printf("#! script: argv0=\"%s\" argv1=\"%s\"\n",
+	     info->argv0, info->argv1);
+
+   return do_exec_inner(interp, info);
+}
+
+struct binfmt {
+   int	(*match)(const char *hdr, int len);
+   int	(*load) (      char *hdr, int len, int fd, const char *name, struct exeinfo *);
+};
+
+static const struct binfmt formats[] = {
+   { match_ELF,		load_ELF },
+   { match_script,	load_script },
+};
+
+
+static int do_exec_inner(const char *exe, struct exeinfo *info)
+{
+   int fd;
+   char buf[VKI_BYTES_PER_PAGE];
+   int bufsz;
+   int i;
+   int ret;
+   struct stat st;
+
+   fd = open(exe, O_RDONLY);
+   if (fd == -1) {
+      if (0)
+	 fprintf(stderr, "Can't open executable %s: %s\n",
+		 exe, strerror(errno));
+      return errno;
+   }
+
+   if (fstat(fd, &st) == -1) 
+      return errno;
+   else {
+      uid_t uid = geteuid();
+      gid_t gid = getegid();
+      gid_t groups[32];
+      int ngrp = getgroups(32, groups);
+
+      if (uid == st.st_uid && !(st.st_mode & S_IXUSR))
+	 return EACCES;
+
+      if (gid == st.st_gid && !(st.st_mode & S_IXGRP))
+	 return EACCES;
+
+      for(i = 0; i < ngrp; i++)
+	 if (groups[i] == st.st_gid && !(st.st_mode & S_IXGRP))
+	    return EACCES;
+
+      if (!(st.st_mode & S_IXOTH))
+	 return EACCES;
+   }
+
+   bufsz = pread(fd, buf, sizeof(buf), 0);
+   if (bufsz < 0) {
+      fprintf(stderr, "Can't read executable header: %s\n",
+	      strerror(errno));
+      close(fd);
+      return errno;
+   }
+
+   ret = ENOEXEC;
+   for(i = 0; i < sizeof(formats)/sizeof(*formats); i++) {
+      if ((formats[i].match)(buf, bufsz)) {
+	 ret = (formats[i].load)(buf, bufsz, fd, exe, info);
+	 break;
+      }
+   }
+
+   close(fd);
+
+   return ret;
+}
+
+int do_exec(const char *exe, struct exeinfo *info)
+{
+   info->argv0 = NULL;
+   info->argv1 = NULL;
+
+   return do_exec_inner(exe, info);
+}
diff --git a/coregrind/ume.h b/coregrind/ume.h
new file mode 100644
index 0000000..664c125
--- /dev/null
+++ b/coregrind/ume.h
@@ -0,0 +1,77 @@
+#ifndef _COREGRIND_UME_H
+#define _COREGRIND_UME_H
+
+#include <elf.h>
+#include <sys/types.h>
+
+#if	ELFSZ == 64
+#define ESZ(x)	Elf64_##x
+#elif	ELFSZ == 32
+#define ESZ(x)	Elf32_##x
+#else
+#error ELFSZ needs to ==32 or ==64
+#endif
+
+/* Integer type the same size as a pointer */
+typedef ESZ(Addr) addr_t;
+
+struct exeinfo
+{
+   int		setbrk;		/* INPUT: if true, set the brk segment base */
+   addr_t	map_base;	/* INPUT: if non-zero, base address of mappings  */
+
+   addr_t	exe_base;	/* INOUT: lowest (allowed) address of exe	*/
+   addr_t	exe_end;	/* INOUT: highest (allowed) address	*/
+
+   addr_t	phdr;		/* address phdr was mapped at		*/
+   int		phnum;		/* number of phdrs			*/
+   addr_t	interp_base;	/* where interpreter (ld.so) was mapped	*/
+   addr_t	entry;		/* entrypoint in main executable	*/
+   addr_t	init_eip;	/* initial eip				*/
+   addr_t	brkbase;	/* base address of brk segment		*/
+
+   /* these are the extra args added by #! scripts */
+   char		*argv0;		/* the interpreter name */
+   char		*argv1;		/* the args for the interpreter */
+
+   char		**argv;		/* the original argv */
+};
+
+int do_exec(const char *exe, struct exeinfo *info);
+
+void foreach_map(int (*fn)(void *start, void *end,
+			   const char *perm, off_t offset,
+			   int maj, int min, int ino));
+void as_pad(void *start, void *end);
+void as_unpad(void *start, void *end);
+void as_closepadfile(void);
+int  as_getpadfd(void);
+void as_setpadfd(int);
+
+struct elfinfo
+{
+   ESZ(Ehdr)	e;
+   ESZ(Phdr)	*p;
+   int		fd;
+};
+
+struct elfinfo *readelf(int fd, const char *filename);
+ESZ(Addr) mapelf(struct elfinfo *e, ESZ(Addr) base, int setbrk);
+
+struct ume_auxv
+{
+   int	a_type;
+   union {
+      void *a_ptr;
+      int   a_val;
+      void (*a_fcn)(void);
+   };
+};
+
+struct ume_auxv *find_auxv(int *orig_esp);
+
+/* Our private auxv entries */
+#define AT_UME_PADFD	0xff01	/* padding file fd */
+#define AT_UME_EXECFD	0xff02	/* stage1 executable fd */
+
+#endif /* _COREGRIND_UME_H */
diff --git a/coregrind/ume_arch.h b/coregrind/ume_arch.h
new file mode 100644
index 0000000..6c77fbc
--- /dev/null
+++ b/coregrind/ume_arch.h
@@ -0,0 +1,10 @@
+#ifndef UME_ARCH
+#define UME_ARCH
+
+#include "ume.h"
+
+void ume_go(addr_t eip, addr_t esp) __attribute__((noreturn));
+
+extern void *ume_exec_esp;	/* esp on entry at exec time */
+
+#endif /* UME_ARCH */
diff --git a/coregrind/valgrind.in b/coregrind/valgrind.in
deleted file mode 100755
index 540af80..0000000
--- a/coregrind/valgrind.in
+++ /dev/null
@@ -1,175 +0,0 @@
-#!/bin/sh
-##--------------------------------------------------------------------##
-##--- The startup script.                                 valgrind ---##
-##--------------------------------------------------------------------##
-
-#  This file is part of Valgrind, an extensible x86 protected-mode
-#  emulator for monitoring program execution on x86-Unixes.
-#
-#  Copyright (C) 2002-2003 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.
-
-
-# Should point to the installation directory
-prefix="@prefix@"
-exec_prefix="@exec_prefix@"
-VALGRIND="@libdir@/valgrind"
-
-# Other stuff ...
-version="@VERSION@"
-emailto="jseward@acm.org"
-
-# The default name of the suppressions file
-vgsupp="--suppressions=$VALGRIND/default.supp"
-
-# Valgrind options
-vgopts=
-
-# Tool to use, chosen by --tool=<foo>, defaults to Memcheck 
-tool=memcheck
-
-# --in-place=<dir> arg, for using non-installed version
-in_place_arg=
-
-# Default core+tool to use are the installed ones
-coredir=$VALGRIND
-tooldir=$VALGRIND
-
-# Collect up args for Valgrind.  Only some are intercepted here;
-# the rest are passed to vg_main.c.  Allow --skin for backwards compatibility.
-while [ $# != 0 ]
-do
-  arg=$1
-  case "$arg" in
-    --version)              echo "valgrind-$version"; exit 1 ;;
-    --tool=*)               tool=`echo $arg | sed 's/--tool=//'`;  shift;;
-    --skin=*)               tool=`echo $arg | sed 's/--skin=//'`;  shift;;
-    --in-place=*)           in_place_arg=$arg;        shift;;
-    -*)                     vgopts="$vgopts $arg";    shift;;
-    *)                      break;;
-  esac
-done
-
-
-# If running uninstalled version in-place...
-if [ z"$in_place_arg" != z ]; then
-   in_place_dir=`echo $in_place_arg | sed 's/--in-place=//'`
-   tooldir="$in_place_dir/$tool"
-   coredir="$in_place_dir/coregrind/.in_place"
-   vgsupp="--suppressions=$in_place_dir/default.supp"
-fi
-
-# Setup tool shared object.
-tool_so="vgskin_${tool}.so"
-if [ ! -r "$tooldir/$tool_so" ] ; then
-   echo >&2
-   echo "Tool error:" >&2
-   echo "  The shared library \`$tool_so' for the chosen" >&2
-   echo "  tool \`$tool' could not be found in" >&2
-   echo "  $tooldir" >&2
-   echo >&2
-   exit 1
-fi
-
-VG_ARGS="$VALGRIND_OPTS $vgsupp $vgopts"
-
-export VG_ARGS
-
-# Red Hat Linux 9 uses NPTL, which has a kernel interface 
-# unlike the linuxthreads interface valgrind expects.  We can
-# tell the dynamic loader to disable this interface using
-# an environment variable.
-
-if getconf GNU_LIBPTHREAD_VERSION 2>/dev/null | grep -qi NPTL 2>/dev/null; then
-   LD_ASSUME_KERNEL=2.4.1
-   export LD_ASSUME_KERNEL
-fi
-
-# Check that the program looks ok
-is_prog=0
-
-if [ $# != 0 ] ; then
-
-   # Ensure the program exists.  Ignore any error messages from 'which'.
-   which_prog=`which $1 2> /dev/null`
-   if [ z$which_prog = z ] && (echo "$1" | grep -q '/'); then
-      which_prog=$1
-   fi
-
-   if  [ z$which_prog = z ]; then
-      echo "$0: '$1' not found in \$PATH, aborting." >&2
-      exit 1
-   fi
-
-   if [ $# != 0 ] ; then
-      case `file -L "$which_prog"` in       # must follow symlinks, hence -L
-      # Ensure the program isn't statically linked.
-      *"statically linked"*)
-        echo "\`$which_prog' is statically linked" >&2
-        echo "Valgrind only works on dynamically linked executables;  your" >&2
-        echo "program must rely on at least one shared object for Valgrind" >&2
-        echo "to work with it.  Read FAQ #5 for more information." >&2
-        exit 1 ;;
-      # Ensure that there are no setuid or gid flags
-      *:\ set?id\ ELF*)
-        echo "\`$which_prog' is suid/sgid." >&2
-        echo "Valgrind can't handle these executables, as it" >&2
-        echo "requires the LD_PRELOAD feature in order to work." >&2
-        echo "" >&2
-        echo "Remove those flags and try again." >&2
-        echo "" >&2
-        exit 1
-        ;;
-      esac
-   fi
-
-   is_prog=1
-fi
-
-# A bit subtle.  The LD_PRELOAD added entry must be absolute
-# and not depend on LD_LIBRARY_PATH.  This is so that we can
-# mess with LD_LIBRARY_PATH for child processes, which makes
-# libpthread.so fall out of visibility, independently of
-# whether valgrind.so is visible.
-
-LD_LIBRARY_PATH=$coredir:$LD_LIBRARY_PATH
-export LD_LIBRARY_PATH
-
-# Insert tool .so before valgrind.so to override template functions.
-LD_PRELOAD=$tooldir/$tool_so:$coredir/valgrind.so:$LD_PRELOAD
-export LD_PRELOAD
-#LD_DEBUG=files
-#LD_DEBUG=symbols
-#export LD_DEBUG
-    
-# Actually run the program, under Valgrind's control
-if [ $is_prog = 1 ] ; then
-   exec "$@"
-else
-   # If no command given, act like -h was given so vg_main.c prints out the
-   # usage string.  And pass to 'exec' the name of any program -- it doesn't
-   # matter which -- because it won't be run anyway (we use 'true').
-   VG_ARGS="$VG_ARGS -h"
-   exec true
-fi
-
-##--------------------------------------------------------------------##
-##--- end                                                 valgrind ---##
-##--------------------------------------------------------------------##
diff --git a/coregrind/vg_skiplist.c b/coregrind/vg_skiplist.c
new file mode 100644
index 0000000..911e923
--- /dev/null
+++ b/coregrind/vg_skiplist.c
@@ -0,0 +1,317 @@
+#include "vg_include.h"
+
+#include <stdlib.h>
+
+#define SKIPLIST_DEBUG	0
+
+#define SK_MAXHEIGHT	20	/* 2^20 elements */
+#define SKIPLIST_MAGIC		0x5b1ff872
+#define SKIPLIST_HEAD_MAGIC	(~SKIPLIST_MAGIC)
+
+
+#if SKIPLIST_DEBUG
+#define inline
+#endif /* SKIPLIST_DEBUG */
+
+struct _SkipNode {
+   UInt		magic;
+   UShort	level;		/* level is the max level (level == 0 means 1 next pointer) */
+   SkipNode	*next[0];
+};
+
+
+
+static inline Int get_height(void)
+{
+   UInt ret = 0;
+
+   while((ret < SK_MAXHEIGHT) && (random() & 1))
+      ret++;
+
+   return ret;
+}
+
+static inline void *key_of_data(const SkipList *l, void *d)
+{
+   return (void *)((Char *)d + l->keyoff);
+}
+
+static inline SkipNode *node_of_data(const SkipList *l, const void *d)
+{
+   SkipNode *n = (SkipNode *)((Char *)d + l->size);
+
+   if (SKIPLIST_DEBUG && n->magic != SKIPLIST_MAGIC)
+      VG_(printf)("bad magic on node %p = %x (not %x)\n",
+		  n, n->magic, SKIPLIST_MAGIC);
+
+   vg_assert(n->magic == SKIPLIST_MAGIC);
+
+   return n; 
+}
+
+static inline void *data_of_node(const SkipList *l, const SkipNode *n)
+{
+   if (SKIPLIST_DEBUG && n->magic != SKIPLIST_MAGIC)
+      VG_(printf)("bad magic on node %p = %x (not %x)\n",
+		  n, n->magic, SKIPLIST_MAGIC);
+
+   vg_assert(n->magic == SKIPLIST_MAGIC);
+   return (void *)((Char *)n - l->size);
+}
+
+static inline void *key_of_node(const SkipList *l, const SkipNode *n)
+{
+   return key_of_data(l, data_of_node(l, n));
+}
+
+static inline void validate_skiplist(const SkipList *l, const Char *where)
+{
+#if SKIPLIST_DEBUG
+   const SkipNode *prev[SK_MAXHEIGHT];
+   Int i;
+   const SkipNode *n, *next;
+   
+   VG_(printf)("---------------- %s ----------------\n", where);
+
+   if (l->head == NULL)
+      return;
+
+   for(i = 0; i <= l->head->level; i++) {
+      VG_(printf)("l->head->next[%d]=%p\n",
+		  i, l->head->next[i]);
+      prev[i] = l->head->next[i];
+   }
+
+   for(n = l->head->next[0]; n != NULL; n = next) {
+      next = n->next[0];
+
+      VG_(printf)("n=%p next=%p, n->level=%d k=%s\n",
+		  n, next, n->level, (*l->strkey)(key_of_node(l, n)));
+      for(i = 0; i <= n->level; i++) {
+	 VG_(printf)("  n->next[%d] = %p\n",
+		     i, n->next[i]);
+	 VG_(printf)("  prev[%d] = %p\n",
+		     i, prev[i]);
+      }
+      
+      vg_assert(l->head->level >= n->level);
+
+      for(i = 0; i <= n->level; i++)
+	 vg_assert(prev[i] == n);
+
+      for(i = 0; i <= n->level; i++)
+	 prev[i] = n->next[i];
+
+      vg_assert(next == NULL || (l->cmp)(key_of_node(l, n), key_of_node(l, next)) < 0);
+   }
+#endif	/* SKIPLIST_DEBUG */
+}
+
+void *VG_(SkipNode_Alloc)(const SkipList *l)
+{
+   UInt size = l->size;
+   Int h = get_height();
+   SkipNode *n;
+   Char *ret;
+
+   size += sizeof(SkipNode) + (h+1)*sizeof(SkipNode *);
+
+   if (l->arena == -1)
+      *(Short *)&l->arena = VG_AR_SKIN;
+
+   ret = VG_(arena_malloc)(l->arena, size);
+
+   if (ret == NULL)
+      return NULL;
+
+   n = (SkipNode *)(ret + l->size);
+   n->level = h;
+   n->magic = SKIPLIST_MAGIC;
+
+   while(h-- >= 0)
+      n->next[h] = NULL;
+
+   return ret;
+}
+
+void VG_(SkipNode_Free)(const SkipList *l, void *p)
+{
+   if (SKIPLIST_DEBUG) {
+      SkipNode *n = node_of_data(l, p);
+
+      VG_(printf)("SkipNode_Free: freeing %p (node %p)\n",
+		  p, n);
+      n->magic = 0x55ffaabb;
+   }
+   VG_(arena_free)(l->arena, p);
+}
+
+void *VG_(SkipNode_First)(const SkipList *l)
+{
+   SkipNode *n = l->head ? l->head->next[0] : NULL;
+
+   if (n == NULL)
+      return NULL;
+   else
+      return data_of_node(l, n);
+}
+
+void *VG_(SkipNode_Next)(const SkipList *l, void *data)
+{
+   SkipNode *n = node_of_data(l, data);
+   
+   n = n->next[0];
+
+   if (n == NULL)
+      return NULL;
+
+   return data_of_node(l, n);
+}
+
+
+
+static Int cmp(const SkipList *l, SkipNode *n, void *k2)
+{
+   void *k1 = key_of_node(l, n);
+
+   if (k1 == k2)
+      return 0;
+
+   if (l->head == n)
+      return -1;
+
+   return (l->cmp)(k1, k2);
+}
+
+/* Search the list for k; it either returns the k if it exists, or the
+   one before if not.  */
+static SkipNode *SkipList__Find(const SkipList *l, void *k, SkipNode **prevs)
+{
+   SkipNode *n;
+   Int lvl;
+
+   if (SKIPLIST_DEBUG)
+      VG_(printf)("SkipList__Find: finding %s\n", (*l->strkey)(k));
+
+   validate_skiplist(l, "SkipList__Find");
+
+   if (l->head == NULL)
+      return NULL;
+
+   for(lvl = l->head->level, n = l->head; lvl >= 0; lvl--) {
+      while(n->next[lvl] != NULL && cmp(l, n->next[lvl], k) < 0) {
+	 if (SKIPLIST_DEBUG)
+	    VG_(printf)("SkipList__Find: n=%p n->next[%d]=%p\n",
+			n, lvl, n->next[lvl]);
+	 n = n->next[lvl];
+      }
+      if (prevs)
+	 prevs[lvl] = n;
+   }
+
+   /* XXX Is there a cleaner way of getting this? 
+      
+      If we get an exact match, return it.
+      If we get the head, return NULL.
+      Otherwise return the one before where the hit would be.
+    */
+   if (n->next[0] != NULL && cmp(l, n->next[0], k) == 0)
+      n =  n->next[0];
+   if (n == l->head)
+      n = NULL;
+
+   if (SKIPLIST_DEBUG) {
+
+      VG_(printf)("SkipList__Find returning node %p\n", n);
+
+      if (n == NULL) {
+	 SkipNode *nn;
+
+	 for(nn = l->head->next[0]; nn != NULL; nn = nn->next[0])
+	    vg_assert(cmp(l, nn, k) != 0);
+      } else
+	 vg_assert(cmp(l, n, k) <= 0);
+   }
+
+   return n;
+}
+
+void *VG_(SkipList_Find)(const SkipList *l, void *k)
+{
+   SkipNode *n = SkipList__Find(l, k, NULL);
+
+   if (n != NULL)
+      return data_of_node(l, n);
+   return NULL;
+}
+
+void VG_(SkipList_Insert)(SkipList *l, void *data)
+{
+   SkipNode *update[SK_MAXHEIGHT];
+   SkipNode *n;
+   void *k = key_of_data(l, data);
+   Int i;
+
+   if (SKIPLIST_DEBUG)
+      VG_(printf)("inserting node %p, key %s, height %d\n",
+		  data, (*l->strkey)(key_of_data(l, data)), node_of_data(l, data)->level);
+
+   validate_skiplist(l, "SkipList_Insert before");
+
+   if (l->head == NULL) {
+      Int size = sizeof(SkipNode) * sizeof(SkipNode *) * SK_MAXHEIGHT;
+
+      if (l->arena == -1)
+	 *(Short *)&l->arena = VG_AR_SKIN;
+      
+      l->head = VG_(arena_malloc)(l->arena, size);
+      VG_(memset)(l->head, 0, size);
+
+      l->head->magic = SKIPLIST_HEAD_MAGIC;
+      l->head->level = 0;
+   }
+
+   n = SkipList__Find(l, k, update);
+   
+   vg_assert(n == NULL || (l->cmp)(key_of_node(l, n), k) != 0);
+
+   n = node_of_data(l, data);
+
+   vg_assert(l->head != NULL);
+   if (l->head->level < n->level) {
+      for(i = l->head->level+1; i <= n->level; i++)
+	 l->head->next[i] = n;
+      l->head->level = n->level;
+   }
+
+   for(i = 0; i <= n->level; i++) {
+      n->next[i] = update[i]->next[i];
+      update[i]->next[i] = n;
+   }
+
+   validate_skiplist(l, "SkipList_Insert after");
+}
+
+void *VG_(SkipList_Remove)(SkipList *l, void *k)
+{
+   SkipNode *update[SK_MAXHEIGHT];
+   SkipNode *n;
+   Int i;
+   
+   validate_skiplist(l, "SkipList_Remove before");
+
+   n = SkipList__Find(l, k, update);
+   if (n == NULL)
+      return NULL;
+
+   vg_assert((l->cmp)(k, key_of_node(l, n)) == 0);
+
+   for(i = 0; i <= n->level; i++) {
+      update[i]->next[i] = n->next[i];
+      n->next[i] = NULL;
+   }
+
+   validate_skiplist(l, "SkipList_Remove after");
+
+   return data_of_node(l, n);
+}
diff --git a/coregrind/x86/Makefile.am b/coregrind/x86/Makefile.am
new file mode 100644
index 0000000..1ef4d9c
--- /dev/null
+++ b/coregrind/x86/Makefile.am
@@ -0,0 +1,11 @@
+noinst_HEADERS = \
+	ume_archdefs.h
+
+EXTRA_DIST =		\
+	Make.inc	\
+	stage2.lds	\
+	ume_archdefs.c	\
+	ume_archdefs.h	\
+	ume_entry.S	\
+	ume_go.c
+
diff --git a/coregrind/x86/stage2.lds b/coregrind/x86/stage2.lds
new file mode 100644
index 0000000..7153162
--- /dev/null
+++ b/coregrind/x86/stage2.lds
@@ -0,0 +1,191 @@
+/* Linker script for kickstart - slightly modified from the output of ld --verbose */
+OUTPUT_FORMAT("elf32-i386", "elf32-i386",
+	      "elf32-i386")
+OUTPUT_ARCH(i386)
+ENTRY(_ume_entry)
+SEARCH_DIR("/usr/i386-redhat-linux/lib"); SEARCH_DIR("/usr/lib"); SEARCH_DIR("/usr/local/lib"); SEARCH_DIR("/lib");
+/* Do we need any of these for elf?
+   __DYNAMIC = 0;    */
+
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = kickstart_base + SIZEOF_HEADERS;
+  .interp         : { *(.interp) }
+  .hash           : { *(.hash) }
+  .dynsym         : { *(.dynsym) }
+  .dynstr         : { *(.dynstr) }
+  .gnu.version    : { *(.gnu.version) }
+  .gnu.version_d  : { *(.gnu.version_d) }
+  .gnu.version_r  : { *(.gnu.version_r) }
+  .rel.dyn        :
+    {
+      *(.rel.init)
+      *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*)
+      *(.rel.fini)
+      *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*)
+      *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*)
+      *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*)
+      *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*)
+      *(.rel.ctors)
+      *(.rel.dtors)
+      *(.rel.got)
+      *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*)
+    }
+  .rela.dyn       :
+    {
+      *(.rela.init)
+      *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
+      *(.rela.fini)
+      *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
+      *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
+      *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
+      *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
+      *(.rela.ctors)
+      *(.rela.dtors)
+      *(.rela.got)
+      *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
+    }
+  .rel.plt        : { *(.rel.plt) }
+  .rela.plt       : { *(.rela.plt) }
+  .init           :
+  {
+    KEEP (*(.init))
+  } =0x90909090
+  .plt            : { *(.plt) }
+  .text           :
+  {
+    *(.text .stub .text.* .gnu.linkonce.t.*)
+    /* .gnu.warning sections are handled specially by elf32.em.  */
+    *(.gnu.warning)
+  } =0x90909090
+  .fini           :
+  {
+    KEEP (*(.fini))
+  } =0x90909090
+  PROVIDE (__etext = .);
+  PROVIDE (_etext = .);
+  PROVIDE (etext = .);
+  .rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
+  .rodata1        : { *(.rodata1) }
+  .eh_frame_hdr : { *(.eh_frame_hdr) }
+  .eh_frame       : ONLY_IF_RO { KEEP (*(.eh_frame)) }
+  .gcc_except_table   : ONLY_IF_RO { *(.gcc_except_table) }
+  /* Adjust the address for the data segment.  We want to adjust up to
+     the same address within the page on the next page up.  */
+  . = ALIGN (0x1000) - ((0x1000 - .) & (0x1000 - 1)); . = DATA_SEGMENT_ALIGN (0x1000, 0x1000);
+  /* For backward-compatibility with tools that don't support the
+     *_array_* sections below, our glibc's crt files contain weak
+     definitions of symbols that they reference.  We don't want to use
+     them, though, unless they're strictly necessary, because they'd
+     bring us empty sections, unlike PROVIDE below, so we drop the
+     sections from the crt files here.  */
+  /DISCARD/ : {
+      */crti.o(.init_array .fini_array .preinit_array)
+      */crtn.o(.init_array .fini_array .preinit_array)
+  }
+  /* Ensure the __preinit_array_start label is properly aligned.  We
+     could instead move the label definition inside the section, but
+     the linker would then create the section even if it turns out to
+     be empty, which isn't pretty.  */
+  . = ALIGN(32 / 8);
+  PROVIDE (__preinit_array_start = .);
+  .preinit_array     : { *(.preinit_array) }
+  PROVIDE (__preinit_array_end = .);
+  PROVIDE (__init_array_start = .);
+  .init_array     : { *(.init_array) }
+  PROVIDE (__init_array_end = .);
+  PROVIDE (__fini_array_start = .);
+  .fini_array     : { *(.fini_array) }
+  PROVIDE (__fini_array_end = .);
+  .data           :
+  {
+    *(.data .data.* .gnu.linkonce.d.*)
+    SORT(CONSTRUCTORS)
+  }
+  .data1          : { *(.data1) }
+  .tdata	  : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
+  .tbss		  : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
+  .eh_frame       : ONLY_IF_RW { KEEP (*(.eh_frame)) }
+  .gcc_except_table   : ONLY_IF_RW { *(.gcc_except_table) }
+  .dynamic        : { *(.dynamic) }
+  .ctors          :
+  {
+    /* gcc uses crtbegin.o to find the start of
+       the constructors, so we make sure it is
+       first.  Because this is a wildcard, it
+       doesn't matter if the user does not
+       actually link against crtbegin.o; the
+       linker won't look for a file to match a
+       wildcard.  The wildcard also means that it
+       doesn't matter which directory crtbegin.o
+       is in.  */
+    KEEP (*crtbegin.o(.ctors))
+    /* We don't want to include the .ctor section from
+       from the crtend.o file until after the sorted ctors.
+       The .ctor section from the crtend file contains the
+       end of ctors marker and it must be last */
+    KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors))
+    KEEP (*(SORT(.ctors.*)))
+    KEEP (*(.ctors))
+  }
+  .dtors          :
+  {
+    KEEP (*crtbegin.o(.dtors))
+    KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors))
+    KEEP (*(SORT(.dtors.*)))
+    KEEP (*(.dtors))
+  }
+  .jcr            : { KEEP (*(.jcr)) }
+  .got            : { *(.got.plt) *(.got) }
+  _edata = .;
+  PROVIDE (edata = .);
+  __bss_start = .;
+  .bss            :
+  {
+   *(.dynbss)
+   *(.bss .bss.* .gnu.linkonce.b.*)
+   *(COMMON)
+   /* Align here to ensure that the .bss section occupies space up to
+      _end.  Align after .bss to ensure correct alignment even if the
+      .bss section disappears because there are no input sections.  */
+   . = ALIGN(32 / 8);
+  }
+  . = ALIGN(32 / 8);
+  _end = .;
+  PROVIDE (end = .);
+  . = DATA_SEGMENT_END (.);
+  /* Stabs debugging sections.  */
+  .stab          0 : { *(.stab) }
+  .stabstr       0 : { *(.stabstr) }
+  .stab.excl     0 : { *(.stab.excl) }
+  .stab.exclstr  0 : { *(.stab.exclstr) }
+  .stab.index    0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment       0 : { *(.comment) }
+  /* DWARF debug sections.
+     Symbols in the DWARF debugging sections are relative to the beginning
+     of the section so we begin them at 0.  */
+  /* DWARF 1 */
+  .debug          0 : { *(.debug) }
+  .line           0 : { *(.line) }
+  /* GNU DWARF 1 extensions */
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  /* DWARF 1.1 and DWARF 2 */
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  /* DWARF 2 */
+  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
+  .debug_abbrev   0 : { *(.debug_abbrev) }
+  .debug_line     0 : { *(.debug_line) }
+  .debug_frame    0 : { *(.debug_frame) }
+  .debug_str      0 : { *(.debug_str) }
+  .debug_loc      0 : { *(.debug_loc) }
+  .debug_macinfo  0 : { *(.debug_macinfo) }
+  /* SGI/MIPS DWARF 2 extensions */
+  .debug_weaknames 0 : { *(.debug_weaknames) }
+  .debug_funcnames 0 : { *(.debug_funcnames) }
+  .debug_typenames 0 : { *(.debug_typenames) }
+  .debug_varnames  0 : { *(.debug_varnames) }
+}
diff --git a/coregrind/x86/ume_archdefs.c b/coregrind/x86/ume_archdefs.c
new file mode 100644
index 0000000..b6641aa
--- /dev/null
+++ b/coregrind/x86/ume_archdefs.c
@@ -0,0 +1,3 @@
+#include "ume_archdefs.h"
+
+const unsigned long CLIENT_START = 0;
diff --git a/coregrind/x86/ume_archdefs.h b/coregrind/x86/ume_archdefs.h
new file mode 100644
index 0000000..8bf017f
--- /dev/null
+++ b/coregrind/x86/ume_archdefs.h
@@ -0,0 +1,6 @@
+#ifndef UME_ARCHDEFS_H
+#define UME_ARCHDEFS_H
+
+#define CLIENT_BASE	0x00000000ul			/* base address of client address space */
+
+#endif /* UME_ARCHDEFS_H */
diff --git a/coregrind/x86/ume_entry.S b/coregrind/x86/ume_entry.S
new file mode 100644
index 0000000..6f2b2a3
--- /dev/null
+++ b/coregrind/x86/ume_entry.S
@@ -0,0 +1,12 @@
+	.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 --git a/coregrind/x86/ume_go.c b/coregrind/x86/ume_go.c
new file mode 100644
index 0000000..7370ac6
--- /dev/null
+++ b/coregrind/x86/ume_go.c
@@ -0,0 +1,20 @@
+#include "ume_arch.h"
+
+void ume_go(addr_t eip, addr_t esp)
+{
+   asm volatile ("movl %1, %%esp;"
+		 "pushl %%eax;"
+		 "xorl	%%eax,%%eax;"
+		 "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(;;)
+	   ;
+} 
diff --git a/include/vg_skin.h b/include/vg_skin.h.base
similarity index 74%
rename from include/vg_skin.h
rename to include/vg_skin.h.base
index 8c328ed..1477f98 100644
--- a/include/vg_skin.h
+++ b/include/vg_skin.h.base
@@ -1870,651 +1870,3 @@
 #endif   /* NDEF __VG_SKIN_H */
 
 /* gen_toolint.pl will put the VG_(init_*)() functions here: */
-/* Generated by "gen_toolint.pl toolproto" */
-
-/* These are the parameterised functions in the core.  The default definitions
-   are overridden by LD_PRELOADed skin version.  At the very least, a skin
-   must define the fundamental template functions.  Depending on what needs
-   are set, extra template functions will be used too.  Functions are
-   grouped under the needs that govern their use.
-
-   ------------------------------------------------------------------
-   Fundamental template functions
-
-   Do initialisation that can only be done after command line processing.
- */
-void SK_(post_clo_init)(void);
-
-/* Instrument a basic block.  Must be a true function, ie. the same input
-   always results in the same output, because basic blocks can be
-   retranslated.  Unless you're doing something really strange...
-   'orig_addr' is the address of the first instruction in the block.
- */
-UCodeBlock* SK_(instrument)(UCodeBlock* cb, Addr orig_addr);
-
-/* Finish up, print out any results, etc.  `exitcode' is program's exit
-   code.  The shadow (if the `shadow_regs' need is set) can be found with
-   VG_(get_shadow_archreg)(R_EBX), since %ebx holds the argument to the
-   exit() syscall.
- */
-void SK_(fini)(Int exitcode);
-
-
-/* ------------------------------------------------------------------
-   VG_(needs).core_errors
-
-   (none needed)
-
-   ------------------------------------------------------------------
-   VG_(needs).skin_errors
-
-   Identify if two errors are equal, or equal enough.  `res' indicates how
-   close is "close enough".  `res' should be passed on as necessary, eg. if
-   the Error's `extra' part contains an ExeContext, `res' should be
-   passed to VG_(eq_ExeContext)() if the ExeContexts are considered.  Other
-   than that, probably don't worry about it unless you have lots of very
-   similar errors occurring.
- */
-Bool SK_(eq_SkinError)(VgRes res, Error* e1, Error* e2);
-
-/* Print error context. */
-void SK_(pp_SkinError)(Error* err);
-
-/* Should fill in any details that could be postponed until after the
-   decision whether to ignore the error (ie. details not affecting the
-   result of SK_(eq_SkinError)()).  This saves time when errors are ignored.
-   Yuk.
-
-   Return value: must be the size of the `extra' part in bytes -- used by
-   the core to make a copy.
- */
-UInt SK_(update_extra)(Error* err);
-
-/* Return value indicates recognition.  If recognised, must set skind using
-   VG_(set_supp_kind)().
- */
-Bool SK_(recognised_suppression)(Char* name, Supp* su);
-
-/* Read any extra info for this suppression kind.  Most likely for filling
-   in the `extra' and `string' parts (with VG_(set_supp_{extra, string})())
-   of a suppression if necessary.  Should return False if a syntax error
-   occurred, True otherwise.
- */
-Bool SK_(read_extra_suppression_info)(Int fd, Char* buf, Int nBuf, Supp* su);
-
-/* This should just check the kinds match and maybe some stuff in the
-   `string' and `extra' field if appropriate (using VG_(get_supp_*)() to
-   get the relevant suppression parts).
- */
-Bool SK_(error_matches_suppression)(Error* err, Supp* su);
-
-/* This should return the suppression name, for --gen-suppressions, or NULL
-   if that error type cannot be suppressed.  This is the inverse of
-   SK_(recognised_suppression)().
- */
-Char* SK_(get_error_name)(Error* err);
-
-/* This should print any extra info for the error, for --gen-suppressions,
-   including the newline.  This is the inverse of
-   SK_(read_extra_suppression_info)().
- */
-void SK_(print_extra_suppression_info)(Error* err);
-
-
-/* ------------------------------------------------------------------
-   VG_(needs).basic_block_discards
-
-   Should discard any information that pertains to specific basic blocks
-   or instructions within the address range given.
- */
-void SK_(discard_basic_block_info)(Addr a, UInt size);
-
-
-/* ------------------------------------------------------------------
-   VG_(needs).shadow_regs
-
-   No functions must be defined, but the post_reg[s]_write_* events should
-   be tracked.
-
-   ------------------------------------------------------------------
-   VG_(needs).command_line_options
-
-   Return True if option was recognised.  Presumably sets some state to
-   record the option as well.
- */
-Bool SK_(process_cmd_line_option)(Char* argv);
-
-/* Print out command line usage for options for normal skin operation. */
-void SK_(print_usage)(void);
-
-/* Print out command line usage for options for debugging the skin. */
-void SK_(print_debug_usage)(void);
-
-/* ------------------------------------------------------------------
-   VG_(needs).client_requests
-
-   If using client requests, the number of the first request should be equal
-   to VG_USERREQ_SKIN_BASE('X', 'Y'), where 'X' and 'Y' form a suitable two
-   character identification for the string.  The second and subsequent
-   requests should follow.
-
-   This function should use the VG_IS_SKIN_USERREQ macro (in
-   include/valgrind.h) to first check if it's a request for this skin.  Then
-   should handle it if it's recognised (and return True), or return False if
-   not recognised.  arg_block[0] holds the request number, any further args
-   from the request are in arg_block[1..].  'ret' is for the return value...
-   it should probably be filled, if only with 0.
- */
-Bool SK_(handle_client_request)(ThreadId tid, UInt* arg_block, UInt* ret);
-
-
-/* ------------------------------------------------------------------
-   VG_(needs).extends_UCode
-
-   'X' prefix indicates eXtended UCode.
- */
-Int SK_(get_Xreg_usage)(UInstr* u, Tag tag, Int* regs, Bool* isWrites);
-void SK_(emit_XUInstr)(UInstr* u, RRegSet regs_live_before);
-Bool SK_(sane_XUInstr)(Bool beforeRA, Bool beforeLiveness, UInstr* u);
-Char * SK_(name_XUOpcode)(Opcode opc);
-void SK_(pp_XUInstr)(UInstr* u);
-
-
-/* ------------------------------------------------------------------
-   VG_(needs).syscall_wrapper
-
-   If either of the pre_ functions malloc() something to return, the
-   corresponding post_ function had better free() it!
-
- */
-void * SK_(pre_syscall)(ThreadId tid, UInt syscallno, Bool is_blocking);
-void SK_(post_syscall)(ThreadId tid, UInt syscallno, void* pre_result, Int res, Bool is_blocking);
-
-
-/* ---------------------------------------------------------------------
-     VG_(needs).sanity_checks
-
-   Can be useful for ensuring a skin's correctness.  SK_(cheap_sanity_check)
-   is called very frequently;  SK_(expensive_sanity_check) is called less
-   frequently and can be more involved.
- */
-Bool SK_(cheap_sanity_check)(void);
-Bool SK_(expensive_sanity_check)(void);
-
-
-/* ================================================================================
-   Event tracking functions
-
-   Events happening in core to track.  To be notified, pass a callback
-   function to the appropriate function.  To ignore an event, don't do
-   anything (default is for events to be ignored).
-
-   Note that most events aren't passed a ThreadId.  To find out the ThreadId
-   of the affected thread, use VG_(get_current_or_recent_tid)().  For the
-   ones passed a ThreadId, use that instead, since
-   VG_(get_current_or_recent_tid)() might not give the right ThreadId in
-   that case.
-
-   Memory events (Nb: to track heap allocation/freeing, a skin must replace
-   malloc() et al.  See above how to do this.)
-
-   These ones occur at startup, upon some signals, and upon some syscalls
- */
-void SK_(new_mem_startup)(Addr a, UInt len, Bool rr, Bool ww, Bool xx);
-void SK_(new_mem_stack_signal)(Addr a, UInt len);
-void SK_(new_mem_brk)(Addr a, UInt len);
-void SK_(new_mem_mmap)(Addr a, UInt len, Bool rr, Bool ww, Bool xx);
-
-void SK_(copy_mem_remap)(Addr from, Addr to, UInt len);
-void SK_(change_mem_mprotect)(Addr a, UInt len, Bool rr, Bool ww, Bool xx);
-void SK_(die_mem_stack_signal)(Addr a, UInt len);
-void SK_(die_mem_brk)(Addr a, UInt len);
-void SK_(die_mem_munmap)(Addr a, UInt len);
-
-/* These ones are called when %esp changes.  A skin could track these itself
-   (except for ban_mem_stack) but it's much easier to use the core's help.
-
-   The specialised ones are called in preference to the general one, if they
-   are defined.  These functions are called a lot if they are used, so
-   specialising can optimise things significantly.  If any of the
-   specialised cases are defined, the general case must be defined too.
-
-   Nb: they must all use the __attribute__((regparm(n))) attribute.
- */
-void SK_(new_mem_stack_4)(Addr new_ESP);
-void SK_(new_mem_stack_8)(Addr new_ESP);
-void SK_(new_mem_stack_12)(Addr new_ESP);
-void SK_(new_mem_stack_16)(Addr new_ESP);
-void SK_(new_mem_stack_32)(Addr new_ESP);
-void SK_(new_mem_stack)(Addr a, UInt len);
-
-void SK_(die_mem_stack_4)(Addr die_ESP);
-void SK_(die_mem_stack_8)(Addr die_ESP);
-void SK_(die_mem_stack_12)(Addr die_ESP);
-void SK_(die_mem_stack_16)(Addr die_ESP);
-void SK_(die_mem_stack_32)(Addr die_ESP);
-void SK_(die_mem_stack)(Addr a, UInt len);
-
-/* Used for redzone at end of thread stacks */
-void SK_(ban_mem_stack)(Addr a, UInt len);
-
-/* These ones occur around syscalls, signal handling, etc */
-void SK_(pre_mem_read)(CorePart part, ThreadId tid, Char* s, Addr a, UInt size);
-void SK_(pre_mem_read_asciiz)(CorePart part, ThreadId tid, Char* s, Addr a);
-void SK_(pre_mem_write)(CorePart part, ThreadId tid, Char* s, Addr a, UInt size);
-/* Not implemented yet -- have to add in lots of places, which is a
-   pain.  Won't bother unless/until there's a need.
-   void (*post_mem_read)  ( ThreadState* tst, Char* s, Addr a, UInt size );
- */
-void SK_(post_mem_write)(Addr a, UInt size);
-
-
-/* Register events -- if `shadow_regs' need is set, all should probably be
-   used.  Use VG_(set_thread_shadow_archreg)() to set the shadow of the
-   changed register.
-
-   Use VG_(set_shadow_archreg)() to set the eight general purpose regs,
-   and use VG_(set_shadow_eflags)() to set eflags.
- */
-void SK_(post_regs_write_init)(void);
-
-/* Use VG_(set_thread_shadow_archreg)() to set the shadow regs for these
-   events.
- */
-void SK_(post_reg_write_syscall_return)(ThreadId tid, UInt reg);
-void SK_(post_reg_write_deliver_signal)(ThreadId tid, UInt reg);
-void SK_(post_reg_write_pthread_return)(ThreadId tid, UInt reg);
-void SK_(post_reg_write_clientreq_return)(ThreadId tid, UInt reg);
-/* This one is called for malloc() et al if they are replaced by a skin. */
-void SK_(post_reg_write_clientcall_return)(ThreadId tid, UInt reg, Addr f);
-
-
-/* Scheduler events (not exhaustive) */
-void SK_(thread_run)(ThreadId tid);
-
-
-/* Thread events (not exhaustive)
-
-   Called during thread create, before the new thread has run any
-   instructions (or touched any memory).
- */
-void SK_(post_thread_create)(ThreadId tid, ThreadId child);
-void SK_(post_thread_join)(ThreadId joiner, ThreadId joinee);
-
-
-/* Mutex events (not exhaustive)
-   "void *mutex" is really a pthread_mutex *
-
-   Called before a thread can block while waiting for a mutex (called
-   regardless of whether the thread will block or not).
- */
-void SK_(pre_mutex_lock)(ThreadId tid, void* mutex);
-/* Called once the thread actually holds the mutex (always paired with
-   pre_mutex_lock).
- */
-void SK_(post_mutex_lock)(ThreadId tid, void* mutex);
-/* Called after a thread has released a mutex (no need for a corresponding
-   pre_mutex_unlock, because unlocking can't block).
- */
-void SK_(post_mutex_unlock)(ThreadId tid, void* mutex);
-
-/* Signal events (not exhaustive)
-
-   ... pre_send_signal, post_send_signal ...
-
-   Called before a signal is delivered;  `alt_stack' indicates if it is
-   delivered on an alternative stack. 
- */
-void SK_(pre_deliver_signal)(ThreadId tid, Int sigNo, Bool alt_stack);
-/* Called after a signal is delivered.  Nb: unfortunately, if the signal
-   handler longjmps, this won't be called.
- */
-void SK_(post_deliver_signal)(ThreadId tid, Int sigNo);
-
-
-/* Others... condition variable...
-   ...
-
-   Shadow memory management
- */
-void SK_(init_shadow_page)(Addr p);
-
-/* ================================================================================
-   malloc and friends
- */
-void* SK_(malloc)(Int n);
-void* SK_(__builtin_new)(Int n);
-void* SK_(__builtin_vec_new)(Int n);
-void* SK_(memalign)(Int align, Int n);
-void* SK_(calloc)(Int nmemb, Int n);
-void SK_(free)(void* p);
-void SK_(__builtin_delete)(void* p);
-void SK_(__builtin_vec_delete)(void* p);
-void* SK_(realloc)(void* p, Int size);
-/* Generated by "gen_toolint.pl initproto" */
-
-#ifndef VG_toolint_initproto
-#define VG_toolint_initproto
-
-
-/* These are the parameterised functions in the core.  The default definitions
-   are overridden by LD_PRELOADed skin version.  At the very least, a skin
-   must define the fundamental template functions.  Depending on what needs
-   are set, extra template functions will be used too.  Functions are
-   grouped under the needs that govern their use.
-
-   ------------------------------------------------------------------
-   Fundamental template functions
-
-   Do initialisation that can only be done after command line processing.
- */
-void VG_(init_post_clo_init)(void (*func)(void));
-
-/* Instrument a basic block.  Must be a true function, ie. the same input
-   always results in the same output, because basic blocks can be
-   retranslated.  Unless you're doing something really strange...
-   'orig_addr' is the address of the first instruction in the block.
- */
-void VG_(init_instrument)(UCodeBlock* (*func)(UCodeBlock* cb, Addr orig_addr));
-
-/* Finish up, print out any results, etc.  `exitcode' is program's exit
-   code.  The shadow (if the `shadow_regs' need is set) can be found with
-   VG_(get_shadow_archreg)(R_EBX), since %ebx holds the argument to the
-   exit() syscall.
- */
-void VG_(init_fini)(void (*func)(Int exitcode));
-
-
-/* ------------------------------------------------------------------
-   VG_(needs).core_errors
-
-   (none needed)
-
-   ------------------------------------------------------------------
-   VG_(needs).skin_errors
-
-   Identify if two errors are equal, or equal enough.  `res' indicates how
-   close is "close enough".  `res' should be passed on as necessary, eg. if
-   the Error's `extra' part contains an ExeContext, `res' should be
-   passed to VG_(eq_ExeContext)() if the ExeContexts are considered.  Other
-   than that, probably don't worry about it unless you have lots of very
-   similar errors occurring.
- */
-void VG_(init_eq_SkinError)(Bool (*func)(VgRes res, Error* e1, Error* e2));
-
-/* Print error context. */
-void VG_(init_pp_SkinError)(void (*func)(Error* err));
-
-/* Should fill in any details that could be postponed until after the
-   decision whether to ignore the error (ie. details not affecting the
-   result of SK_(eq_SkinError)()).  This saves time when errors are ignored.
-   Yuk.
-
-   Return value: must be the size of the `extra' part in bytes -- used by
-   the core to make a copy.
- */
-void VG_(init_update_extra)(UInt (*func)(Error* err));
-
-/* Return value indicates recognition.  If recognised, must set skind using
-   VG_(set_supp_kind)().
- */
-void VG_(init_recognised_suppression)(Bool (*func)(Char* name, Supp* su));
-
-/* Read any extra info for this suppression kind.  Most likely for filling
-   in the `extra' and `string' parts (with VG_(set_supp_{extra, string})())
-   of a suppression if necessary.  Should return False if a syntax error
-   occurred, True otherwise.
- */
-void VG_(init_read_extra_suppression_info)(Bool (*func)(Int fd, Char* buf, Int nBuf, Supp* su));
-
-/* This should just check the kinds match and maybe some stuff in the
-   `string' and `extra' field if appropriate (using VG_(get_supp_*)() to
-   get the relevant suppression parts).
- */
-void VG_(init_error_matches_suppression)(Bool (*func)(Error* err, Supp* su));
-
-/* This should return the suppression name, for --gen-suppressions, or NULL
-   if that error type cannot be suppressed.  This is the inverse of
-   SK_(recognised_suppression)().
- */
-void VG_(init_get_error_name)(Char* (*func)(Error* err));
-
-/* This should print any extra info for the error, for --gen-suppressions,
-   including the newline.  This is the inverse of
-   SK_(read_extra_suppression_info)().
- */
-void VG_(init_print_extra_suppression_info)(void (*func)(Error* err));
-
-
-/* ------------------------------------------------------------------
-   VG_(needs).basic_block_discards
-
-   Should discard any information that pertains to specific basic blocks
-   or instructions within the address range given.
- */
-void VG_(init_discard_basic_block_info)(void (*func)(Addr a, UInt size));
-
-
-/* ------------------------------------------------------------------
-   VG_(needs).shadow_regs
-
-   No functions must be defined, but the post_reg[s]_write_* events should
-   be tracked.
-
-   ------------------------------------------------------------------
-   VG_(needs).command_line_options
-
-   Return True if option was recognised.  Presumably sets some state to
-   record the option as well.
- */
-void VG_(init_process_cmd_line_option)(Bool (*func)(Char* argv));
-
-/* Print out command line usage for options for normal skin operation. */
-void VG_(init_print_usage)(void (*func)(void));
-
-/* Print out command line usage for options for debugging the skin. */
-void VG_(init_print_debug_usage)(void (*func)(void));
-
-/* ------------------------------------------------------------------
-   VG_(needs).client_requests
-
-   If using client requests, the number of the first request should be equal
-   to VG_USERREQ_SKIN_BASE('X', 'Y'), where 'X' and 'Y' form a suitable two
-   character identification for the string.  The second and subsequent
-   requests should follow.
-
-   This function should use the VG_IS_SKIN_USERREQ macro (in
-   include/valgrind.h) to first check if it's a request for this skin.  Then
-   should handle it if it's recognised (and return True), or return False if
-   not recognised.  arg_block[0] holds the request number, any further args
-   from the request are in arg_block[1..].  'ret' is for the return value...
-   it should probably be filled, if only with 0.
- */
-void VG_(init_handle_client_request)(Bool (*func)(ThreadId tid, UInt* arg_block, UInt* ret));
-
-
-/* ------------------------------------------------------------------
-   VG_(needs).extends_UCode
-
-   'X' prefix indicates eXtended UCode.
- */
-void VG_(init_get_Xreg_usage)(Int (*func)(UInstr* u, Tag tag, Int* regs, Bool* isWrites));
-void VG_(init_emit_XUInstr)(void (*func)(UInstr* u, RRegSet regs_live_before));
-void VG_(init_sane_XUInstr)(Bool (*func)(Bool beforeRA, Bool beforeLiveness, UInstr* u));
-void VG_(init_name_XUOpcode)(Char * (*func)(Opcode opc));
-void VG_(init_pp_XUInstr)(void (*func)(UInstr* u));
-
-
-/* ------------------------------------------------------------------
-   VG_(needs).syscall_wrapper
-
-   If either of the pre_ functions malloc() something to return, the
-   corresponding post_ function had better free() it!
-
- */
-void VG_(init_pre_syscall)(void * (*func)(ThreadId tid, UInt syscallno, Bool is_blocking));
-void VG_(init_post_syscall)(void (*func)(ThreadId tid, UInt syscallno, void* pre_result, Int res, Bool is_blocking));
-
-
-/* ---------------------------------------------------------------------
-     VG_(needs).sanity_checks
-
-   Can be useful for ensuring a skin's correctness.  SK_(cheap_sanity_check)
-   is called very frequently;  SK_(expensive_sanity_check) is called less
-   frequently and can be more involved.
- */
-void VG_(init_cheap_sanity_check)(Bool (*func)(void));
-void VG_(init_expensive_sanity_check)(Bool (*func)(void));
-
-
-/* ================================================================================
-   Event tracking functions
-
-   Events happening in core to track.  To be notified, pass a callback
-   function to the appropriate function.  To ignore an event, don't do
-   anything (default is for events to be ignored).
-
-   Note that most events aren't passed a ThreadId.  To find out the ThreadId
-   of the affected thread, use VG_(get_current_or_recent_tid)().  For the
-   ones passed a ThreadId, use that instead, since
-   VG_(get_current_or_recent_tid)() might not give the right ThreadId in
-   that case.
-
-   Memory events (Nb: to track heap allocation/freeing, a skin must replace
-   malloc() et al.  See above how to do this.)
-
-   These ones occur at startup, upon some signals, and upon some syscalls
- */
-void VG_(init_new_mem_startup)(void (*func)(Addr a, UInt len, Bool rr, Bool ww, Bool xx));
-void VG_(init_new_mem_stack_signal)(void (*func)(Addr a, UInt len));
-void VG_(init_new_mem_brk)(void (*func)(Addr a, UInt len));
-void VG_(init_new_mem_mmap)(void (*func)(Addr a, UInt len, Bool rr, Bool ww, Bool xx));
-
-void VG_(init_copy_mem_remap)(void (*func)(Addr from, Addr to, UInt len));
-void VG_(init_change_mem_mprotect)(void (*func)(Addr a, UInt len, Bool rr, Bool ww, Bool xx));
-void VG_(init_die_mem_stack_signal)(void (*func)(Addr a, UInt len));
-void VG_(init_die_mem_brk)(void (*func)(Addr a, UInt len));
-void VG_(init_die_mem_munmap)(void (*func)(Addr a, UInt len));
-
-/* These ones are called when %esp changes.  A skin could track these itself
-   (except for ban_mem_stack) but it's much easier to use the core's help.
-
-   The specialised ones are called in preference to the general one, if they
-   are defined.  These functions are called a lot if they are used, so
-   specialising can optimise things significantly.  If any of the
-   specialised cases are defined, the general case must be defined too.
-
-   Nb: they must all use the __attribute__((regparm(n))) attribute.
- */
-void VG_(init_new_mem_stack_4)(void (*func)(Addr new_ESP));
-void VG_(init_new_mem_stack_8)(void (*func)(Addr new_ESP));
-void VG_(init_new_mem_stack_12)(void (*func)(Addr new_ESP));
-void VG_(init_new_mem_stack_16)(void (*func)(Addr new_ESP));
-void VG_(init_new_mem_stack_32)(void (*func)(Addr new_ESP));
-void VG_(init_new_mem_stack)(void (*func)(Addr a, UInt len));
-
-void VG_(init_die_mem_stack_4)(void (*func)(Addr die_ESP));
-void VG_(init_die_mem_stack_8)(void (*func)(Addr die_ESP));
-void VG_(init_die_mem_stack_12)(void (*func)(Addr die_ESP));
-void VG_(init_die_mem_stack_16)(void (*func)(Addr die_ESP));
-void VG_(init_die_mem_stack_32)(void (*func)(Addr die_ESP));
-void VG_(init_die_mem_stack)(void (*func)(Addr a, UInt len));
-
-/* Used for redzone at end of thread stacks */
-void VG_(init_ban_mem_stack)(void (*func)(Addr a, UInt len));
-
-/* These ones occur around syscalls, signal handling, etc */
-void VG_(init_pre_mem_read)(void (*func)(CorePart part, ThreadId tid, Char* s, Addr a, UInt size));
-void VG_(init_pre_mem_read_asciiz)(void (*func)(CorePart part, ThreadId tid, Char* s, Addr a));
-void VG_(init_pre_mem_write)(void (*func)(CorePart part, ThreadId tid, Char* s, Addr a, UInt size));
-/* Not implemented yet -- have to add in lots of places, which is a
-   pain.  Won't bother unless/until there's a need.
-   void (*post_mem_read)  ( ThreadState* tst, Char* s, Addr a, UInt size );
- */
-void VG_(init_post_mem_write)(void (*func)(Addr a, UInt size));
-
-
-/* Register events -- if `shadow_regs' need is set, all should probably be
-   used.  Use VG_(set_thread_shadow_archreg)() to set the shadow of the
-   changed register.
-
-   Use VG_(set_shadow_archreg)() to set the eight general purpose regs,
-   and use VG_(set_shadow_eflags)() to set eflags.
- */
-void VG_(init_post_regs_write_init)(void (*func)(void));
-
-/* Use VG_(set_thread_shadow_archreg)() to set the shadow regs for these
-   events.
- */
-void VG_(init_post_reg_write_syscall_return)(void (*func)(ThreadId tid, UInt reg));
-void VG_(init_post_reg_write_deliver_signal)(void (*func)(ThreadId tid, UInt reg));
-void VG_(init_post_reg_write_pthread_return)(void (*func)(ThreadId tid, UInt reg));
-void VG_(init_post_reg_write_clientreq_return)(void (*func)(ThreadId tid, UInt reg));
-/* This one is called for malloc() et al if they are replaced by a skin. */
-void VG_(init_post_reg_write_clientcall_return)(void (*func)(ThreadId tid, UInt reg, Addr f));
-
-
-/* Scheduler events (not exhaustive) */
-void VG_(init_thread_run)(void (*func)(ThreadId tid));
-
-
-/* Thread events (not exhaustive)
-
-   Called during thread create, before the new thread has run any
-   instructions (or touched any memory).
- */
-void VG_(init_post_thread_create)(void (*func)(ThreadId tid, ThreadId child));
-void VG_(init_post_thread_join)(void (*func)(ThreadId joiner, ThreadId joinee));
-
-
-/* Mutex events (not exhaustive)
-   "void *mutex" is really a pthread_mutex *
-
-   Called before a thread can block while waiting for a mutex (called
-   regardless of whether the thread will block or not).
- */
-void VG_(init_pre_mutex_lock)(void (*func)(ThreadId tid, void* mutex));
-/* Called once the thread actually holds the mutex (always paired with
-   pre_mutex_lock).
- */
-void VG_(init_post_mutex_lock)(void (*func)(ThreadId tid, void* mutex));
-/* Called after a thread has released a mutex (no need for a corresponding
-   pre_mutex_unlock, because unlocking can't block).
- */
-void VG_(init_post_mutex_unlock)(void (*func)(ThreadId tid, void* mutex));
-
-/* Signal events (not exhaustive)
-
-   ... pre_send_signal, post_send_signal ...
-
-   Called before a signal is delivered;  `alt_stack' indicates if it is
-   delivered on an alternative stack. 
- */
-void VG_(init_pre_deliver_signal)(void (*func)(ThreadId tid, Int sigNo, Bool alt_stack));
-/* Called after a signal is delivered.  Nb: unfortunately, if the signal
-   handler longjmps, this won't be called.
- */
-void VG_(init_post_deliver_signal)(void (*func)(ThreadId tid, Int sigNo));
-
-
-/* Others... condition variable...
-   ...
-
-   Shadow memory management
- */
-void VG_(init_init_shadow_page)(void (*func)(Addr p));
-
-/* ================================================================================
-   malloc and friends
- */
-void VG_(init_malloc)(void* (*func)(Int n));
-void VG_(init___builtin_new)(void* (*func)(Int n));
-void VG_(init___builtin_vec_new)(void* (*func)(Int n));
-void VG_(init_memalign)(void* (*func)(Int align, Int n));
-void VG_(init_calloc)(void* (*func)(Int nmemb, Int n));
-void VG_(init_free)(void (*func)(void* p));
-void VG_(init___builtin_delete)(void (*func)(void* p));
-void VG_(init___builtin_vec_delete)(void (*func)(void* p));
-void VG_(init_realloc)(void* (*func)(void* p, Int size));
-
-#endif /* VG_toolint_initproto */