Big clean-up: changed the core/tool interface to be mediated entirely
through the VG_(tdict) function dictionary, rather than using TL_(foo)
functions.

This facilitated the following changes:

- Removed the "TL_" prefix, which is no longer needed.

- Removed the auto-generated files vg_toolint.[ch], which were no longer
  needed, which simplifies the build a great deal.  Their (greatly
  streamlined) contents went into core.h and vg_needs.h (and will soon
  go into a new module defining the core/tool interface).  
  
  This also meant that tool.h.base reverted to tool.h (so no more
  accidentally editing tool.h and not having the changes go into the
  repo, hooray!)  And gen_toolint.pl was removed.  And toolfuncs.def was
  removed.

- Removed VG_(missing_tool_func)(), no longer used.

- Bumped the core/tool interface major version number to 8.  And I
  killed the minor version number, which was never used.  The layout
  of the ToolInfo struct is such that this should not cause problems.



git-svn-id: svn://svn.valgrind.org/valgrind/trunk@3644 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/Makefile.am b/coregrind/Makefile.am
index a819fe1..5d4f753 100644
--- a/coregrind/Makefile.am
+++ b/coregrind/Makefile.am
@@ -47,15 +47,11 @@
 	pub_core_syscalls.h	\
 	ume.h			\
 	vg_symtab2.h		\
-	vg_symtypes.h		\
-	vg_toolint.h
+	vg_symtypes.h
 
 EXTRA_DIST = \
 	valgrind.vs \
-	gen_toolint.pl toolfuncs.def README_MODULES.txt
-
-BUILT_SOURCES = vg_toolint.c vg_toolint.h
-CLEANFILES = vg_toolint.c vg_toolint.h
+	README_MODULES.txt
 
 valgrind_SOURCES = \
 	ume.c \
@@ -93,7 +89,6 @@
 	vg_stabs.c \
 	vg_skiplist.c \
 	vg_symtypes.c \
-	vg_toolint.c \
 	vg_translate.c \
 	vg_transtab.c
 
@@ -131,19 +126,6 @@
 stage2_LDADD= $(stage2_extra) -ldl
 
 
-vg_toolint.c: $(srcdir)/gen_toolint.pl $(srcdir)/toolfuncs.def ./Makefile
-	rm -f $@
-	$(PERL) $(srcdir)/gen_toolint.pl callwrap     < $(srcdir)/toolfuncs.def >  $@ || rm -f $@
-	$(PERL) $(srcdir)/gen_toolint.pl missingfuncs < $(srcdir)/toolfuncs.def >> $@ || rm -f $@
-	$(PERL) $(srcdir)/gen_toolint.pl initfunc     < $(srcdir)/toolfuncs.def >> $@ || rm -f $@
-	$(PERL) $(srcdir)/gen_toolint.pl structdef    < $(srcdir)/toolfuncs.def >> $@ || rm -f $@
-
-vg_toolint.h:  $(srcdir)/gen_toolint.pl $(srcdir)/toolfuncs.def ./Makefile
-	rm -f $@
-	$(PERL) $(srcdir)/gen_toolint.pl proto  < $(srcdir)/toolfuncs.def >  $@ || rm -f $@
-	$(PERL) $(srcdir)/gen_toolint.pl struct < $(srcdir)/toolfuncs.def >> $@ || rm -f $@
-
-
 vg_inject_so_SOURCES = vg_intercept.c
 vg_inject_so_CFLAGS = $(AM_CFLAGS) -fpic
 vg_inject_so_LDADD = -ldl
diff --git a/coregrind/core.h b/coregrind/core.h
index 0174458..f52bf57 100644
--- a/coregrind/core.h
+++ b/coregrind/core.h
@@ -101,10 +101,6 @@
 
 #include "valgrind.h"
 
-#undef TL_
-#define TL_(x)	vgToolInternal_##x
-
-
 /* ---------------------------------------------------------------------
    Global macros.
    ------------------------------------------------------------------ */
@@ -321,13 +317,6 @@
 
 extern VgDetails VG_(details);
 
-/* If new fields are added to this type, update:
- *  - vg_main.c:initialisation of VG_(needs)
- *  - vg_main.c:sanity_check_needs()
- *
- * If the name of this type or any of its fields change, update:
- *  - dependent comments (just search for "VG_(needs)"). 
- */
 typedef
    struct {
       Bool libc_freeres;
@@ -347,7 +336,118 @@
 
 extern VgNeeds VG_(needs);
 
-#include "vg_toolint.h"
+typedef struct {
+   // ---------------------------------------------
+   // 'Needs' and related functions
+   // ---------------------------------------------
+   // Basic functions
+   void  (*tool_pre_clo_init) (void);
+   void  (*tool_post_clo_init)(void);
+   IRBB* (*tool_instrument)   (IRBB*, VexGuestLayout*, IRType, IRType);
+   void  (*tool_fini)         (Int);
+
+   // VG_(needs).core_errors
+   // (none)
+   
+   // VG_(needs).tool_errors
+   Bool  (*tool_eq_Error)                    (VgRes, Error*, Error*);
+   void  (*tool_pp_Error)                    (Error*);
+   UInt  (*tool_update_extra)                (Error*);
+   Bool  (*tool_recognised_suppression)      (Char*, Supp*);
+   Bool  (*tool_read_extra_suppression_info) (Int, Char*, Int, Supp*);
+   Bool  (*tool_error_matches_suppression)   (Error*, Supp*);
+   Char* (*tool_get_error_name)              (Error*);
+   void  (*tool_print_extra_suppression_info)(Error*);
+
+   // VG_(needs).basic_block_discards
+   void (*tool_discard_basic_block_info)(Addr, SizeT);
+
+   // VG_(needs).command_line_options
+   Bool (*tool_process_cmd_line_option)(Char*);
+   void (*tool_print_usage)            (void);
+   void (*tool_print_debug_usage)      (void);
+
+   // VG_(needs).client_requests
+   Bool (*tool_handle_client_request)(ThreadId, UWord*, UWord*);
+
+   // VG_(needs).syscall_wrapper
+   void (*tool_pre_syscall) (ThreadId, UInt);
+   void (*tool_post_syscall)(ThreadId, UInt, Int);
+
+   // VG_(needs).sanity_checks
+   Bool (*tool_cheap_sanity_check)(void);
+   Bool (*tool_expensive_sanity_check)(void);
+
+   // ---------------------------------------------
+   // Event tracking functions
+   // ---------------------------------------------
+   void (*track_new_mem_startup)     (Addr, SizeT, Bool, Bool, Bool);
+   void (*track_new_mem_stack_signal)(Addr, SizeT);
+   void (*track_new_mem_brk)         (Addr, SizeT);
+   void (*track_new_mem_mmap)        (Addr, SizeT, Bool, Bool, Bool);
+
+   void (*track_copy_mem_remap)      (Addr, Addr, SizeT);
+   void (*track_change_mem_mprotect) (Addr, SizeT, Bool, Bool, Bool);
+   void (*track_die_mem_stack_signal)(Addr, SizeT);
+   void (*track_die_mem_brk)         (Addr, SizeT);
+   void (*track_die_mem_munmap)      (Addr, SizeT);
+
+   VGA_REGPARM(1) void (*track_new_mem_stack_4) (Addr);
+   VGA_REGPARM(1) void (*track_new_mem_stack_8) (Addr);
+   VGA_REGPARM(1) void (*track_new_mem_stack_12)(Addr);
+   VGA_REGPARM(1) void (*track_new_mem_stack_16)(Addr);
+   VGA_REGPARM(1) void (*track_new_mem_stack_32)(Addr);
+   void (*track_new_mem_stack)(Addr, SizeT);
+
+   VGA_REGPARM(1) void (*track_die_mem_stack_4) (Addr);
+   VGA_REGPARM(1) void (*track_die_mem_stack_8) (Addr);
+   VGA_REGPARM(1) void (*track_die_mem_stack_12)(Addr);
+   VGA_REGPARM(1) void (*track_die_mem_stack_16)(Addr);
+   VGA_REGPARM(1) void (*track_die_mem_stack_32)(Addr);
+   void (*track_die_mem_stack)(Addr, SizeT);
+
+   void (*track_ban_mem_stack)(Addr, SizeT);
+
+   void (*track_pre_mem_read)       (CorePart, ThreadId, Char*, Addr, SizeT);
+   void (*track_pre_mem_read_asciiz)(CorePart, ThreadId, Char*, Addr);
+   void (*track_pre_mem_write)      (CorePart, ThreadId, Char*, Addr, SizeT);
+   void (*track_post_mem_write)     (CorePart, ThreadId, Addr, SizeT);
+
+   void (*track_pre_reg_read)  (CorePart, ThreadId, Char*, OffT, SizeT);
+   void (*track_post_reg_write)(CorePart, ThreadId,        OffT, SizeT);
+   void (*track_post_reg_write_clientcall_return)(ThreadId, OffT, SizeT, Addr);
+
+   void (*track_thread_run)(ThreadId);
+
+   void (*track_post_thread_create)(ThreadId, ThreadId);
+   void (*track_post_thread_join)  (ThreadId, ThreadId);
+
+   void (*track_pre_mutex_lock)   (ThreadId, void*);
+   void (*track_post_mutex_lock)  (ThreadId, void*);
+   void (*track_post_mutex_unlock)(ThreadId, void*);
+
+   void (*track_pre_deliver_signal) (ThreadId, Int sigNo, Bool);
+   void (*track_post_deliver_signal)(ThreadId, Int sigNo);
+
+   void (*track_init_shadow_page)(Addr);
+
+   // ---------------------------------------------
+   // malloc/free replacements
+   // ---------------------------------------------
+   void* (*malloc_malloc)              (ThreadId, SizeT);
+   void* (*malloc___builtin_new)       (ThreadId, SizeT);
+   void* (*malloc___builtin_vec_new)   (ThreadId, SizeT);
+   void* (*malloc_memalign)            (ThreadId, SizeT, SizeT);
+   void* (*malloc_calloc)              (ThreadId, SizeT, SizeT);
+   void  (*malloc_free)                (ThreadId, void*);
+   void  (*malloc___builtin_delete)    (ThreadId, void*);
+   void  (*malloc___builtin_vec_delete)(ThreadId, void*);
+   void* (*malloc_realloc)             (ThreadId, void*, SizeT);
+
+} VgToolInterface;
+
+extern VgToolInterface VG_(tdict);
+
 
 
 /* ---------------------------------------------------------------------
@@ -1065,15 +1165,21 @@
    Things relating to the used tool
    ------------------------------------------------------------------ */
 
+// Note the use of C's comma operator here -- it means that we execute both
+// statements, and the rvalue of the whole thing is the rvalue of the last
+// statement.  This lets us say "x = VG_TDICT_CALL(...)" in the required
+// places, while still checking the assertion.
+#define VG_TDICT_CALL(fn, args...) \
+   ( tl_assert2(VG_(tdict).fn, \
+                "you forgot to set VgToolInterface function '" #fn "'"), \
+     VG_(tdict).fn(args) )
+
 #define VG_TRACK(fn, args...) 			\
    do {						\
-      if (VG_(defined_##fn)())			\
-	 TL_(fn)(args);				\
+      if (VG_(tdict).track_##fn)		\
+	 VG_(tdict).track_##fn(args);           \
    } while(0)
 
-__attribute__ ((noreturn))
-extern void VG_(missing_tool_func) ( const Char* fn );
-
 // ---------------------------------------------------------------------
 // Architecture-specific things defined in eg. x86/*.c
 // ---------------------------------------------------------------------
diff --git a/coregrind/gen_toolint.pl b/coregrind/gen_toolint.pl
deleted file mode 100644
index e6f629c..0000000
--- a/coregrind/gen_toolint.pl
+++ /dev/null
@@ -1,266 +0,0 @@
-#!/usr/bin/perl -w
-
-#  This file is part of Valgrind, a dynamic binary instrumentation
-#  framework.
-#
-#  Copyright (C) 2000-2005 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.
-
-use strict;
-
-my $output = shift @ARGV;
-my $indent = "";
-my $headerguard;
-my $include;
-my $passcomment = 1;
-my $pre;
-my $post;
-my $generate;
-
-my $struct = "VG_(tdict)";
-
-my %pfxmap = ("track" => "TL_",
-	      "tool"  => "TL_",
-	      "malloc"=> "TL_",
-	     );
-
-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 = "core.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 = "core.h";
-    $generate = sub ($$$@) {
-	my ($pfx, $ret, $func, @args) = @_;
-	my $args = join ', ', @args;
-
-	print "$ret $pfxmap{$pfx}($func)($args);\n";
-	print "$ret VG_(missing_$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 = "core.h";
-    $generate = sub ($$$@) {
-	my ($pfx, $ret, $func, @args) = @_;
-	my $args = join ", ", @args;
-
-	print "__attribute__ ((weak))\n$ret VG_(missing_$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 != VG_(missing_$func);\n";
-	print "}\n\n";
-    };
-    $indent = "   ";
-} elsif ($output eq "struct") {
-    $include = "core.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 = VG_(missing_$func),\n"
-    };
-    $indent = "   ";
-} elsif ($output eq "initfunc") {
-    $include = "tool.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 = VG_(missing_$func);
-	if (VG_(defined_$func)())
-		VG_(printf)("Warning tool is redefining $func\\n");
-	if (func == TL_($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;
-}
-
-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;
-my $prefix;
-
-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/m_aspacemgr/aspacemgr.c b/coregrind/m_aspacemgr/aspacemgr.c
index e5505c0..b4e1a87 100644
--- a/coregrind/m_aspacemgr/aspacemgr.c
+++ b/coregrind/m_aspacemgr/aspacemgr.c
@@ -1228,7 +1228,7 @@
       VG_(printf)("init_shadow_range(%p, %d)\n", p, sz);
 
    vg_assert(VG_(needs).shadow_memory);
-   vg_assert(VG_(defined_init_shadow_page)());
+   vg_assert(VG_(tdict).track_init_shadow_page);
 
    sz = PGROUNDUP(p+sz) - PGROUNDDN(p);
    p = PGROUNDDN(p);
@@ -1254,7 +1254,7 @@
    if (0) show_segments("shadow_alloc(before)");
 
    vg_assert(VG_(needs).shadow_memory);
-   vg_assert(!VG_(defined_init_shadow_page)());
+   vg_assert(!VG_(tdict).track_init_shadow_page);
 
    size = PGROUNDUP(size);
 
diff --git a/coregrind/m_errormgr.c b/coregrind/m_errormgr.c
index fc10a3d..70ccb09 100644
--- a/coregrind/m_errormgr.c
+++ b/coregrind/m_errormgr.c
@@ -235,9 +235,9 @@
      //         vg_assert(VG_(needs).core_errors);
      //         return VG_(tm_error_equal)(res, e1, e2);
       default: 
-         if (VG_(needs).tool_errors)
-            return TL_(eq_Error)(res, e1, e2);
-         else {
+         if (VG_(needs).tool_errors) {
+            return VG_TDICT_CALL(tool_eq_Error, res, e1, e2);
+         } else {
             VG_(printf)("\nUnhandled error type: %u. VG_(needs).tool_errors\n"
                         "probably needs to be set.\n",
                         e1->ekind);
@@ -263,7 +263,7 @@
      //         break;
       default: 
          if (VG_(needs).tool_errors)
-            TL_(pp_Error)( err );
+            VG_TDICT_CALL( tool_pp_Error, err );
          else {
             VG_(printf)("\nUnhandled error type: %u.  VG_(needs).tool_errors\n"
                         "probably needs to be set?\n",
@@ -373,14 +373,14 @@
       VG_(printf)("   core:PThread\n");
 
    } else {
-      Char* name = TL_(get_error_name)(err);
+      Char* name = VG_TDICT_CALL(tool_get_error_name, err);
       if (NULL == name) {
          VG_(message)(Vg_UserMsg, 
                       "(tool does not allow error to be suppressed)");
          return;
       }
       VG_(printf)("   %s:%s\n", VG_(details).name, name);
-      TL_(print_extra_suppression_info)(err);
+      VG_TDICT_CALL(tool_print_extra_suppression_info, err);
    }
 
    // Print stack trace elements
@@ -524,15 +524,15 @@
       will disappear shortly, so we must copy it.  First do the main
       (non-`extra') part.
      
-      Then TL_(update_extra) can update the `extra' part.  This is for when
-      there are more details to fill in which take time to work out but
-      don't affect our earlier decision to include the error -- by
+      Then VG_(tdict).tool_update_extra can update the `extra' part.  This
+      is for when there are more details to fill in which take time to work
+      out but don't affect our earlier decision to include the error -- by
       postponing those details until now, we avoid the extra work in the
       case where we ignore the error.  Ugly.
 
       Then, if there is an `extra' part, copy it too, using the size that
-      TL_(update_extra) returned.  Also allow for people using the void*
-      extra field for a scalar value like an integer.
+      VG_(tdict).tool_update_extra returned.  Also allow for people using
+      the void* extra field for a scalar value like an integer.
    */
 
    /* copy main part */
@@ -548,7 +548,7 @@
      //         break;
       default:
          vg_assert(VG_(needs).tool_errors);
-         extra_size = TL_(update_extra)(p);
+         extra_size = VG_TDICT_CALL(tool_update_extra, p);
          break;
    }
 
@@ -595,10 +595,11 @@
    /* Unless it's suppressed, we're going to show it.  Don't need to make
       a copy, because it's only temporary anyway.
 
-      Then update the `extra' part with TL_(update_extra), because that can
-      have an affect on whether it's suppressed.  Ignore the size return
-      value of TL_(update_extra), because we're not copying `extra'. */
-   (void)TL_(update_extra)(&err);
+      Then update the `extra' part with VG_(tdict).tool_update_extra),
+      because that can have an affect on whether it's suppressed.  Ignore
+      the size return value of VG_(tdict).tool_update_extra, because we're
+      not copying `extra'. */
+   (void)VG_TDICT_CALL(tool_update_extra, &err);
 
    if (NULL == is_suppressible_error(&err)) {
       if (count_error)
@@ -865,7 +866,7 @@
                tool_name_present(VG_(details).name, tool_names))
       {
          // A tool suppression
-         if (TL_(recognised_suppression)(supp_name, supp)) {
+         if (VG_TDICT_CALL(tool_recognised_suppression, supp_name, supp)) {
             /* Do nothing, function fills in supp->skind */
          } else {
             BOMB("unknown tool suppression type");
@@ -883,7 +884,7 @@
       }
 
       if (VG_(needs).tool_errors && 
-          !TL_(read_extra_suppression_info)(fd, buf, N_BUF, supp))
+          !VG_TDICT_CALL(tool_read_extra_suppression_info, fd, buf, N_BUF, supp))
       {
          BOMB("bad or missing extra suppression info");
       }
@@ -965,7 +966,7 @@
          return (err->ekind == ThreadErr || err->ekind == MutexErr);
       default:
          if (VG_(needs).tool_errors) {
-            return TL_(error_matches_suppression)(err, su);
+            return VG_TDICT_CALL(tool_error_matches_suppression, err, su);
          } else {
             VG_(printf)(
                "\nUnhandled suppression type: %u.  VG_(needs).tool_errors\n"
diff --git a/coregrind/m_syscalls/priv_syscalls.h b/coregrind/m_syscalls/priv_syscalls.h
index 8add5ec..1544aab 100644
--- a/coregrind/m_syscalls/priv_syscalls.h
+++ b/coregrind/m_syscalls/priv_syscalls.h
@@ -393,44 +393,44 @@
 */
 
 #define PRRSN \
-      TL_(pre_reg_read)(Vg_CoreSysCall, tid, "(syscallno)", \
-                        O_SYSCALL_NUM, sizeof(UWord));
+      VG_(tdict).track_pre_reg_read(Vg_CoreSysCall, tid, "(syscallno)", \
+                                    O_SYSCALL_NUM, sizeof(UWord));
 #define PRRAn(n,s,t,a) \
-      TL_(pre_reg_read)(Vg_CoreSysCall, tid, s"("#a")", \
-                        O_SYSCALL_ARG##n, sizeof(t));
+      VG_(tdict).track_pre_reg_read(Vg_CoreSysCall, tid, s"("#a")", \
+                                    O_SYSCALL_ARG##n, sizeof(t));
 #define PRE_REG_READ0(tr, s) \
-   if (VG_(defined_pre_reg_read)()) { \
+   if (VG_(tdict).track_pre_reg_read) { \
       PRRSN; \
    }
 #define PRE_REG_READ1(tr, s, t1, a1) \
-   if (VG_(defined_pre_reg_read)()) { \
+   if (VG_(tdict).track_pre_reg_read) { \
       PRRSN; \
       PRRAn(1,s,t1,a1); \
    }
 #define PRE_REG_READ2(tr, s, t1, a1, t2, a2) \
-   if (VG_(defined_pre_reg_read)()) { \
+   if (VG_(tdict).track_pre_reg_read) { \
       PRRSN; \
       PRRAn(1,s,t1,a1); PRRAn(2,s,t2,a2); \
    }
 #define PRE_REG_READ3(tr, s, t1, a1, t2, a2, t3, a3) \
-   if (VG_(defined_pre_reg_read)()) { \
+   if (VG_(tdict).track_pre_reg_read) { \
       PRRSN; \
       PRRAn(1,s,t1,a1); PRRAn(2,s,t2,a2); PRRAn(3,s,t3,a3); \
    }
 #define PRE_REG_READ4(tr, s, t1, a1, t2, a2, t3, a3, t4, a4) \
-   if (VG_(defined_pre_reg_read)()) { \
+   if (VG_(tdict).track_pre_reg_read) { \
       PRRSN; \
       PRRAn(1,s,t1,a1); PRRAn(2,s,t2,a2); PRRAn(3,s,t3,a3); \
       PRRAn(4,s,t4,a4); \
    }
 #define PRE_REG_READ5(tr, s, t1, a1, t2, a2, t3, a3, t4, a4, t5, a5) \
-   if (VG_(defined_pre_reg_read)()) { \
+   if (VG_(tdict).track_pre_reg_read) { \
       PRRSN; \
       PRRAn(1,s,t1,a1); PRRAn(2,s,t2,a2); PRRAn(3,s,t3,a3); \
       PRRAn(4,s,t4,a4); PRRAn(5,s,t5,a5); \
    }
 #define PRE_REG_READ6(tr, s, t1, a1, t2, a2, t3, a3, t4, a4, t5, a5, t6, a6) \
-   if (VG_(defined_pre_reg_read)()) { \
+   if (VG_(tdict).track_pre_reg_read) { \
       PRRSN; \
       PRRAn(1,s,t1,a1); PRRAn(2,s,t2,a2); PRRAn(3,s,t3,a3); \
       PRRAn(4,s,t4,a4); PRRAn(5,s,t5,a5); PRRAn(6,s,t6,a6); \
diff --git a/coregrind/m_syscalls/syscalls.c b/coregrind/m_syscalls/syscalls.c
index 118e956..66d4e1d 100644
--- a/coregrind/m_syscalls/syscalls.c
+++ b/coregrind/m_syscalls/syscalls.c
@@ -841,10 +841,10 @@
 void buf_and_len_pre_check( ThreadId tid, Addr buf_p, Addr buflen_p,
                             Char* buf_s, Char* buflen_s )
 {
-   if (VG_(defined_pre_mem_write)()) {
+   if (VG_(tdict).track_pre_mem_write) {
       UInt buflen_in = deref_UInt( tid, buflen_p, buflen_s);
       if (buflen_in > 0) {
-         TL_(pre_mem_write) ( Vg_CoreSysCall, tid, buf_s, buf_p, buflen_in );
+         VG_(tdict).track_pre_mem_write( Vg_CoreSysCall, tid, buf_s, buf_p, buflen_in );
       }
    }
 }
@@ -853,10 +853,11 @@
 void buf_and_len_post_check( ThreadId tid, Int res,
                              Addr buf_p, Addr buflen_p, Char* s )
 {
-   if (!VG_(is_kerror)(res) && VG_(defined_post_mem_write)()) {
+   if (!VG_(is_kerror)(res) && VG_(tdict).track_post_mem_write) 
+   {
       UInt buflen_out = deref_UInt( tid, buflen_p, s);
       if (buflen_out > 0 && buf_p != (Addr)NULL) {
-         TL_(post_mem_write) ( Vg_CoreSysCall, tid, buf_p, buflen_out );
+         VG_(tdict).track_post_mem_write( Vg_CoreSysCall, tid, buf_p, buflen_out );
       }
    }
 }
@@ -6037,9 +6038,7 @@
       pre_syscall again, without calling post_syscall (ie, more
       pre's than post's) */
    if (VG_(needs).syscall_wrapper) {
-     //VGP_PUSHCC(VgpSkinSysWrap);
-      TL_(post_syscall)(tid, syscallno, RES);
-      //VGP_POPCC(VgpSkinSysWrap);
+      VG_TDICT_CALL(tool_post_syscall, tid, syscallno, RES);
    }
 }
 
@@ -6096,9 +6095,7 @@
 
    /* Do any pre-syscall actions */
    if (VG_(needs).syscall_wrapper) {
-      VGP_PUSHCC(VgpToolSysWrap);
-      TL_(pre_syscall)(tid, syscallno);
-      VGP_POPCC(VgpToolSysWrap);
+      VG_TDICT_CALL(tool_pre_syscall, tid, syscallno);
    }
 
    PRINT("SYSCALL[%d,%d](%3d)%s%s:", 
diff --git a/coregrind/toolfuncs.def b/coregrind/toolfuncs.def
deleted file mode 100644
index 42c9b79..0000000
--- a/coregrind/toolfuncs.def
+++ /dev/null
@@ -1,273 +0,0 @@
-# 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.  Some/all default 
-## definitions are overridden by the tool version.  At the very least, a tool
-## 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 be done before command line processing.
-void,		pre_clo_init
-
-## 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...
-IRBB*, instrument, IRBB* bb, VexGuestLayout* layout, IRType gWordTy, IRType hWordTy
-
-## Finish up, print out any results, etc.  `exitcode' is program's exit
-## code.  The shadow can be found with VG_(get_exit_status_shadow)().
-void,	fini,	Int exitcode
-
-
-## ------------------------------------------------------------------
-## VG_(needs).core_errors
-
-## (none needed)
-
-## ------------------------------------------------------------------
-## VG_(needs).tool_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_Error,	VgRes res, Error* e1, Error* e2
-
-## Print error context.
-void,	pp_Error,	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 TL_(eq_Error)()).  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
-## TL_(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
-## TL_(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, SizeT size
-
-
-## ------------------------------------------------------------------
-## 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 tool operation.
-void,	print_usage
-
-## Print out command line usage for options for debugging the tool.
-void,	print_debug_usage
-
-## ------------------------------------------------------------------
-## VG_(needs).client_requests
-
-## If using client requests, the number of the first request should be equal
-## to VG_USERREQ_TOOL_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_TOOL_USERREQ macro (in
-## include/valgrind.h) to first check if it's a request for this tool.  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, UWord* arg_block, UWord* ret
-
-
-## ------------------------------------------------------------------
-## 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
-void, post_syscall, ThreadId tid, UInt syscallno, Int res
-
-
-## ---------------------------------------------------------------------
-##   VG_(needs).sanity_checks
-
-## Can be useful for ensuring a tool's correctness.  TL_(cheap_sanity_check)
-## is called very frequently;  TL_(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 (the default is for events to be ignored).
-
-## Note that most events aren't passed a ThreadId.  If the event is one called
-## from generated code (eg. new_mem_stack_*), you can use
-## VG_(get_running_tid)() to find it.  Otherwise, it has to be passed in,
-## as in pre_mem_read, and so the event signature will require changing.
-
-## Memory events (Nb: to track heap allocation/freeing, a tool 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, SizeT len, Bool rr, Bool ww, Bool xx
-void,	new_mem_stack_signal,	Addr a, SizeT len
-void,	new_mem_brk,	Addr a, SizeT len
-void,	new_mem_mmap,	Addr a, SizeT len, Bool rr, Bool ww, Bool xx
-
-void,	copy_mem_remap,	Addr from, Addr to, SizeT len
-void,	change_mem_mprotect,	Addr a, SizeT len, Bool rr, Bool ww, Bool xx
-void,	die_mem_stack_signal,	Addr a, SizeT len
-void,	die_mem_brk,	Addr a, SizeT len
-void,	die_mem_munmap,	Addr a, SizeT len
-
-## These ones are called when %esp changes.  A tool 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 VGA_REGPARM(n) attribute.
-VGA_REGPARM(1) void,	new_mem_stack_4,	Addr new_ESP
-VGA_REGPARM(1) void,	new_mem_stack_8,	Addr new_ESP
-VGA_REGPARM(1) void,	new_mem_stack_12,	Addr new_ESP
-VGA_REGPARM(1) void,	new_mem_stack_16,	Addr new_ESP
-VGA_REGPARM(1) void,	new_mem_stack_32,	Addr new_ESP
-void,	new_mem_stack,	Addr a, SizeT len
-
-VGA_REGPARM(1) void,	die_mem_stack_4,	Addr die_ESP
-VGA_REGPARM(1) void,	die_mem_stack_8,	Addr die_ESP
-VGA_REGPARM(1) void,	die_mem_stack_12,	Addr die_ESP
-VGA_REGPARM(1) void,	die_mem_stack_16,	Addr die_ESP
-VGA_REGPARM(1) void,	die_mem_stack_32,	Addr die_ESP
-void,	die_mem_stack,	Addr a, SizeT len
-
-## Used for redzone at end of thread stacks
-void,	ban_mem_stack,	Addr a, SizeT len
-
-## These ones occur around syscalls, signal handling, etc
-void,	pre_mem_read,	    CorePart part, ThreadId tid, Char* s, Addr a, SizeT 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, SizeT size
-void,	post_mem_write,	    CorePart part, ThreadId tid, Addr a, SizeT size
-
-
-## Register events.  Use VG_(set_shadow_state_area)() to set the shadow regs
-## for these events.
-
-void,	pre_reg_read,	CorePart part, ThreadId tid, Char* s, OffT guest_state_offset, SizeT size
-void,	post_reg_write,	CorePart part, ThreadId tid, OffT guest_state_offset, SizeT size
-
-## This one is called for malloc() et al if they are replaced by a tool.
-void,	post_reg_write_clientcall_return,	ThreadId tid, OffT guest_state_offset, SizeT size, 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,			ThreadId tid, SizeT n
-void*,	__builtin_new,		ThreadId tid, SizeT n
-void*,	__builtin_vec_new,	ThreadId tid, SizeT n
-void*,	memalign,		ThreadId tid, SizeT align, SizeT n
-void*,	calloc,			ThreadId tid, SizeT nmemb, SizeT n
-void,	free,			ThreadId tid, void* p
-void,	__builtin_delete,	ThreadId tid, void* p
-void,	__builtin_vec_delete,	ThreadId tid, void* p
-void*,	realloc,		ThreadId tid, void* p, SizeT size
diff --git a/coregrind/vg_main.c b/coregrind/vg_main.c
index 45e9f4d..ba89b42 100644
--- a/coregrind/vg_main.c
+++ b/coregrind/vg_main.c
@@ -1212,31 +1212,29 @@
       goto bad_load;
    }
 
-   toolinfo = dlsym(handle, "vgTool_tool_info");
+   toolinfo = dlsym(handle, "vgPlain_tool_info");
    ok = (NULL != toolinfo);
    if (!ok) {
-      fprintf(stderr, "Tool \"%s\" doesn't define TL_(tool_info) - "
+      fprintf(stderr, "Tool \"%s\" doesn't define its ToolInfo - "
                       "add VG_DETERMINE_INTERFACE_VERSION?\n", toolname);
       goto bad_load;
    }
 
    ok = (toolinfo->sizeof_ToolInfo == sizeof(*toolinfo) &&
-     toolinfo->interface_major_version == VG_CORE_INTERFACE_MAJOR_VERSION &&
-     toolinfo->tl_pre_clo_init != NULL);
+         toolinfo->interface_version == VG_CORE_INTERFACE_VERSION &&
+         toolinfo->tl_pre_clo_init != NULL);
    if (!ok) { 
       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,
+              "  Interface version used by core is: %d (size %d)\n"
+              "  Interface version used by tool is: %d (size %d)\n"
+              "  The version numbers must match.\n",
+              VG_CORE_INTERFACE_VERSION, 
               (Int)sizeof(*toolinfo),
-              toolinfo->interface_major_version,
-              toolinfo->interface_minor_version, 
+              toolinfo->interface_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)
+      if (VG_CORE_INTERFACE_VERSION > toolinfo->interface_version)
          fprintf(stderr, "  your tool to work with this version of Valgrind.\n");
       else
          fprintf(stderr, "  your version of Valgrind to work with this tool.\n");
@@ -1557,7 +1555,7 @@
    if (VG_(details).name) {
       VG_(printf)("  user options for %s:\n", VG_(details).name);
       if (VG_(needs).command_line_options)
-	 TL_(print_usage)();
+	 VG_TDICT_CALL(tool_print_usage);
       else
 	 VG_(printf)("    (none)\n");
    }
@@ -1568,7 +1566,7 @@
          VG_(printf)("  debugging options for %s:\n", VG_(details).name);
       
          if (VG_(needs).command_line_options)
-            TL_(print_debug_usage)();
+            VG_TDICT_CALL(tool_print_debug_usage);
          else
             VG_(printf)("    (none)\n");
       }
@@ -1811,7 +1809,7 @@
          VG_(clo_gen_suppressions) = 2;
 
       else if ( ! VG_(needs).command_line_options
-             || ! TL_(process_cmd_line_option)(arg) ) {
+             || ! VG_TDICT_CALL(tool_process_cmd_line_option, arg) ) {
          VG_(bad_option)(arg);
       }
     skip_arg:
@@ -2297,7 +2295,7 @@
       last 16 pages of memory have become accessible [...] */
    if (VG_(needs).sanity_checks) {
       VGP_PUSHCC(VgpToolCheapSanity);
-      vg_assert(TL_(cheap_sanity_check)());
+      vg_assert(VG_TDICT_CALL(tool_cheap_sanity_check));
       VGP_POPCC(VgpToolCheapSanity);
    }
 
@@ -2320,7 +2318,7 @@
 
       if (VG_(needs).sanity_checks) {
           VGP_PUSHCC(VgpToolExpensiveSanity);
-          vg_assert(TL_(expensive_sanity_check)());
+          vg_assert(VG_TDICT_CALL(tool_expensive_sanity_check));
           VGP_POPCC(VgpToolExpensiveSanity);
       }
 
@@ -2628,7 +2626,7 @@
    }
    process_cmd_line_options(client_auxv, tool);
 
-   TL_(post_clo_init)();
+   VG_TDICT_CALL(tool_post_clo_init);
 
    //--------------------------------------------------------------
    // Determine CPU architecture and subarchitecture
@@ -2857,7 +2855,7 @@
    if (VG_(needs).core_errors || VG_(needs).tool_errors)
       VG_(show_all_errors)();
 
-   TL_(fini)( 0 /*exitcode*/ );
+   VG_TDICT_CALL(tool_fini, 0/*exitcode*/);
 
    VG_(sanity_check_general)( True /*include expensive checks*/ );
 
@@ -2874,21 +2872,6 @@
        LibVEX_ShowAllocStats();
 }
 
-/* If the tool fails to define one or more of the required functions,
- * make it very clear what went wrong! */
-// XXX: this is not a very good place for this function.  Hopefully we'll be
-// able to remove it in the future.
-__attribute__ ((noreturn))
-void VG_(missing_tool_func) ( const Char* fn )
-{
-   VG_(printf)(
-      "\nTool error:\n"
-      "  The tool you have selected is missing the function `%s',\n"
-      "  which is required.\n\n",
-      fn);
-   VG_(tool_panic)("Missing tool function");
-}
-
 /*--------------------------------------------------------------------*/
 /*--- end                                                vg_main.c ---*/
 /*--------------------------------------------------------------------*/
diff --git a/coregrind/vg_needs.c b/coregrind/vg_needs.c
index 74bc314..9627a61 100644
--- a/coregrind/vg_needs.c
+++ b/coregrind/vg_needs.c
@@ -31,10 +31,8 @@
 
 #include "core.h"
 
-
-/* ---------------------------------------------------------------------
-   Tool data structure initialisation
-   ------------------------------------------------------------------ */
+// The core/tool dictionary of functions (initially zeroed, as we want it)
+VgToolInterface VG_(tdict);
 
 /*--------------------------------------------------------------------*/
 /* Setting basic functions */
@@ -50,6 +48,7 @@
    VG_(tdict).tool_fini          = fini;
 }
 
+
 /*--------------------------------------------------------------------*/
 /* Setting details */
 
@@ -77,6 +76,7 @@
 DETAILS(Char*, bug_reports_to)
 DETAILS(UInt,  avg_translation_sizeB)
 
+
 /*--------------------------------------------------------------------*/
 /* Setting needs */
 
@@ -112,24 +112,24 @@
    CHECK_NOT(VG_(details).copyright_author, NULL);
    CHECK_NOT(VG_(details).bug_reports_to,   NULL);
 
-   if ( (VG_(defined_new_mem_stack_4)()  ||
-         VG_(defined_new_mem_stack_8)()  ||
-         VG_(defined_new_mem_stack_12)() ||
-         VG_(defined_new_mem_stack_16)() ||
-         VG_(defined_new_mem_stack_32)()) &&
-       ! VG_(defined_new_mem_stack)()) 
+   if ( (VG_(tdict).track_new_mem_stack_4  ||
+         VG_(tdict).track_new_mem_stack_8  ||
+         VG_(tdict).track_new_mem_stack_12 ||
+         VG_(tdict).track_new_mem_stack_16 ||
+         VG_(tdict).track_new_mem_stack_32 ) &&
+       ! VG_(tdict).track_new_mem_stack) 
    {
       VG_(printf)("\nTool error: one of the specialised `new_mem_stack_n'\n"
                   "events tracked, but not the generic `new_mem_stack' one.\n");
       VG_(tool_panic)("`new_mem_stack' should be defined\n");
    }
 
-   if ( (VG_(defined_die_mem_stack_4)()  ||
-         VG_(defined_die_mem_stack_8)()  ||
-         VG_(defined_die_mem_stack_12)() ||
-         VG_(defined_die_mem_stack_16)() ||
-         VG_(defined_die_mem_stack_32)()) &&
-       ! VG_(defined_die_mem_stack)()) 
+   if ( (VG_(tdict).track_die_mem_stack_4  ||
+         VG_(tdict).track_die_mem_stack_8  ||
+         VG_(tdict).track_die_mem_stack_12 ||
+         VG_(tdict).track_die_mem_stack_16 ||
+         VG_(tdict).track_die_mem_stack_32 ) &&
+       ! VG_(tdict).track_die_mem_stack) 
    {
       VG_(printf)("\nTool error: one of the specialised `die_mem_stack_n'\n"
                   "events tracked, but not the generic `die_mem_stack' one.\n");
@@ -143,7 +143,7 @@
       else
 	 VG_(printf)("\nTool error: tool didn't allocate shadow memory, but apparently "
 		     "needs it.\n");
-      VG_(tool_panic)("VG_(needs).shadow_memory need should be set to match TL_(shadow_ratio)\n");
+      VG_(tool_panic)("VG_(needs).shadow_memory need should be set to match 'shadow_ratio'\n");
    }
 
 #undef CHECK_NOT
@@ -233,6 +233,7 @@
 }
 
 
+/*--------------------------------------------------------------------*/
 /* Replacing malloc() */
 
 extern void VG_(malloc_funcs)(
@@ -261,8 +262,75 @@
    VG_(set_client_malloc_redzone_szB)( client_malloc_redzone_szB );
 }
 
+
 /*--------------------------------------------------------------------*/
-/*--- end                                               vg_needs.c ---*/
+/* Tracked events */
+
+#define DEF(fn, args...) \
+void VG_(fn)(void(*f)(args)) \
+{ \
+   VG_(tdict).fn = f; \
+}
+
+#define DEF2(fn, args...) \
+void VG_(fn)(VGA_REGPARM(1) void(*f)(args)) \
+{ \
+   VG_(tdict).fn = f; \
+}
+
+DEF(track_new_mem_startup,       Addr, SizeT, Bool, Bool, Bool)
+DEF(track_new_mem_stack_signal,  Addr, SizeT)
+DEF(track_new_mem_brk,           Addr, SizeT)
+DEF(track_new_mem_mmap,          Addr, SizeT, Bool, Bool, Bool)
+
+DEF(track_copy_mem_remap,        Addr, Addr, SizeT)
+DEF(track_change_mem_mprotect,   Addr, SizeT, Bool, Bool, Bool)
+DEF(track_die_mem_stack_signal,  Addr, SizeT)
+DEF(track_die_mem_brk,           Addr, SizeT)
+DEF(track_die_mem_munmap,        Addr, SizeT)
+
+DEF2(track_new_mem_stack_4,      Addr)
+DEF2(track_new_mem_stack_8,      Addr)
+DEF2(track_new_mem_stack_12,     Addr)
+DEF2(track_new_mem_stack_16,     Addr)
+DEF2(track_new_mem_stack_32,     Addr)
+DEF (track_new_mem_stack,        Addr, SizeT)
+
+DEF2(track_die_mem_stack_4,      Addr)
+DEF2(track_die_mem_stack_8,      Addr)
+DEF2(track_die_mem_stack_12,     Addr)
+DEF2(track_die_mem_stack_16,     Addr)
+DEF2(track_die_mem_stack_32,     Addr)
+DEF (track_die_mem_stack,        Addr, SizeT)
+
+DEF(track_ban_mem_stack,         Addr, SizeT)
+
+DEF(track_pre_mem_read,          CorePart, ThreadId, Char*, Addr, SizeT)
+DEF(track_pre_mem_read_asciiz,   CorePart, ThreadId, Char*, Addr)
+DEF(track_pre_mem_write,         CorePart, ThreadId, Char*, Addr, SizeT)
+DEF(track_post_mem_write,        CorePart, ThreadId, Addr, SizeT)
+
+DEF(track_pre_reg_read,          CorePart, ThreadId, Char*, OffT, SizeT)
+DEF(track_post_reg_write,        CorePart, ThreadId,        OffT, SizeT)
+
+DEF(track_post_reg_write_clientcall_return, ThreadId, OffT, SizeT, Addr)
+
+DEF(track_thread_run,            ThreadId)
+
+DEF(track_post_thread_create,    ThreadId, ThreadId)
+DEF(track_post_thread_join,      ThreadId, ThreadId)
+
+DEF(track_pre_mutex_lock,        ThreadId, void*)
+DEF(track_post_mutex_lock,       ThreadId, void*)
+DEF(track_post_mutex_unlock,     ThreadId, void*)
+
+DEF(track_pre_deliver_signal,    ThreadId, Int sigNo, Bool)
+DEF(track_post_deliver_signal,   ThreadId, Int sigNo)
+
+DEF(track_init_shadow_page,      Addr)
+
+/*--------------------------------------------------------------------*/
+/*--- end                                                          ---*/
 /*--------------------------------------------------------------------*/
 
 
diff --git a/coregrind/vg_replace_malloc.c b/coregrind/vg_replace_malloc.c
index 3880d92..39ca3f3 100644
--- a/coregrind/vg_replace_malloc.c
+++ b/coregrind/vg_replace_malloc.c
@@ -37,8 +37,8 @@
    gory details.
 
    This file can be linked into the injected so file for any tool that
-   wishes to know about calls to malloc().  It should define functions
-   TL_(malloc) et al that will be called.
+   wishes to know about calls to malloc().  The tool must define all
+   the functions that will be called via 'info'.
    ------------------------------------------------------------------ */
 
 #include "valgrind.h"            /* for VALGRIND_NON_SIMD_CALL[12] */
diff --git a/coregrind/vg_scheduler.c b/coregrind/vg_scheduler.c
index 75dec98..5d7bf02 100644
--- a/coregrind/vg_scheduler.c
+++ b/coregrind/vg_scheduler.c
@@ -1109,7 +1109,7 @@
                VG_(printf)("client request: code %x,  addr %p,  len %d\n",
                            arg[0], (void*)arg[1], arg[2] );
 
-	    if (TL_(handle_client_request) ( tid, arg, &ret ))
+	    if ( VG_TDICT_CALL(tool_handle_client_request, tid, arg, &ret) )
 	       SET_CLREQ_RETVAL(tid, ret);
          } else {
 	    static Bool whined = False;
diff --git a/coregrind/vg_translate.c b/coregrind/vg_translate.c
index b6c31ac..b28d0e9 100644
--- a/coregrind/vg_translate.c
+++ b/coregrind/vg_translate.c
@@ -93,7 +93,7 @@
 
 #  define DO(kind, syze)                                                \
       do {                                                              \
-         if (!VG_(defined_##kind##_mem_stack_##syze)())                 \
+         if (!VG_(tdict).track_##kind##_mem_stack_##syze) \
             goto generic;                                               \
                                                                         \
          /* I don't know if it's really necessary to say that the */    \
@@ -327,19 +327,18 @@
 
 static Bool need_to_handle_SP_assignment(void)
 {
-   return ( VG_(defined_new_mem_stack_4)()  ||
-            VG_(defined_die_mem_stack_4)()  ||
-            VG_(defined_new_mem_stack_8)()  ||
-            VG_(defined_die_mem_stack_8)()  ||
-            VG_(defined_new_mem_stack_12)() ||
-            VG_(defined_die_mem_stack_12)() ||
-            VG_(defined_new_mem_stack_16)() ||
-            VG_(defined_die_mem_stack_16)() ||
-            VG_(defined_new_mem_stack_32)() ||
-            VG_(defined_die_mem_stack_32)() ||
-            VG_(defined_new_mem_stack)()    ||
-            VG_(defined_die_mem_stack)()
-          );
+   return ( VG_(tdict).track_new_mem_stack_4  ||
+            VG_(tdict).track_die_mem_stack_4  ||
+            VG_(tdict).track_new_mem_stack_8  ||
+            VG_(tdict).track_die_mem_stack_8  ||
+            VG_(tdict).track_new_mem_stack_12 ||
+            VG_(tdict).track_die_mem_stack_12 ||
+            VG_(tdict).track_new_mem_stack_16 ||
+            VG_(tdict).track_die_mem_stack_16 ||
+            VG_(tdict).track_new_mem_stack_32 ||
+            VG_(tdict).track_die_mem_stack_32 ||
+            VG_(tdict).track_new_mem_stack    ||
+            VG_(tdict).track_die_mem_stack    );
 }
 
 
@@ -443,6 +442,8 @@
    }
 
    /* Actually do the translation. */
+   tl_assert2(VG_(tdict).tool_instrument,
+              "you forgot to set VgToolInterface function 'tool_instrument'");
    tres = LibVEX_Translate ( 
              VG_(vex_arch), VG_(vex_subarch),
              VG_(vex_arch), VG_(vex_subarch),
@@ -451,7 +452,7 @@
              chase_into_ok,
              &vge,
              tmpbuf, N_TMPBUF, &tmpbuf_used,
-             TL_(instrument),
+             VG_(tdict).tool_instrument,
              need_to_handle_SP_assignment()
                 ? vg_SP_update_pass
                 : NULL,