This change reduces the number of calls to dlsym() when loading tools from a
lot to one.  This required two basic changes.

1. Tools are responsible for telling the tool about any functions they
provide that the tool may call.  This includes basic functions like
TL_(instrument)(), functions that assist core services such as
TL_(pp_Error)(), and malloc-replacement-related functions like
TL_(malloc)().  

2. Tools that replace malloc now specify the size of the heap block redzones
through an arg to the VG_(malloc_funcs)() function, rather than with a
variable VG_(vg_malloc_redzone_szB).

One consequence of these changes is that VG_(tool_init_dlsym)() no longer
needs to be generated by gen_toolint.pl.

There are a number of further improvements that could follow on from this one.
- Avoid the confusingly different definitions of the TL_() macro in the
  core vs. for tools.  Indeed, the functions provided by the tools now don't
  need to use the TL_() macro at all, as they can have arbitrary names.
- Remove a lot of the auto-generated stuff in vg_toolint.c and vg_toolint.h
  (indeed, it might be possible to not auto-generate these at all, which
  would be nice).
- The handling of VgToolInterface is currently split across vg_needs.c and
  vg_toolint.c, which isn't nice.



git-svn-id: svn://svn.valgrind.org/valgrind/trunk@3487 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/vg_malloc2.c b/coregrind/vg_malloc2.c
index ca3cbe1..ae9463b 100644
--- a/coregrind/vg_malloc2.c
+++ b/coregrind/vg_malloc2.c
@@ -378,6 +378,29 @@
    }
 }
 
+static Bool init_done = False;
+static SizeT client_malloc_redzone_szB = 8;   // default: be paranoid
+
+// Nb: this must be called before the client arena is initialised, ie.
+// before any memory is allocated.
+void VG_(set_client_malloc_redzone_szB)(SizeT rz_szB)
+{
+   if (init_done) {
+      VG_(printf)(
+         "\nTool error:\n"
+         "  __FUNCTION__ cannot be called after the first allocation.\n");
+      VG_(exit)(1);
+   }
+   // This limit is no special figure, just something not too big
+   if (rz_szB > 128) {
+      VG_(printf)(
+         "\nTool error:\n"
+         "  __FUNCTION__ passed a too-big value (%llu)", (ULong)rz_szB);
+      VG_(exit)(1);
+   }
+   client_malloc_redzone_szB = rz_szB;
+}
+
 /* This library is self-initialising, as it makes this more self-contained,
    less coupled with the outside world.  Hence VG_(arena_malloc)() and
    VG_(arena_free)() below always call ensure_mm_init() to ensure things are
@@ -385,21 +408,10 @@
 static
 void ensure_mm_init ( void )
 {
-   static SizeT client_rz_szB;
-   static Bool  init_done = False;
-   
    if (init_done) {
-      // Make sure the client arena's redzone size never changes.  Could
-      // happen if VG_(arena_malloc) was called too early, ie. before the
-      // tool was loaded.
-      vg_assert(client_rz_szB == VG_(vg_malloc_redzone_szB));
       return;
    }
 
-   /* No particular reason for this figure, it's just smallish */
-   tl_assert(VG_(vg_malloc_redzone_szB) < 128);
-   client_rz_szB = VG_(vg_malloc_redzone_szB);
-
    /* Use checked red zones (of various sizes) for our internal stuff,
       and an unchecked zone of arbitrary size for the client.  Of
       course the client's red zone can be checked by the tool, eg. 
@@ -415,7 +427,7 @@
    arena_init ( VG_AR_CORE,      "core",     4, CORE_ARENA_MIN_SZB );
    arena_init ( VG_AR_TOOL,      "tool",     4,            1048576 );
    arena_init ( VG_AR_SYMTAB,    "symtab",   4,            1048576 );
-   arena_init ( VG_AR_CLIENT,    "client",  client_rz_szB, 1048576 );
+   arena_init ( VG_AR_CLIENT,    "client", client_malloc_redzone_szB, 1048576 );
    arena_init ( VG_AR_DEMANGLE,  "demangle", 12/*paranoid*/, 65536 );
    arena_init ( VG_AR_EXECTXT,   "exectxt",  4,              65536 );
    arena_init ( VG_AR_ERRORS,    "errors",   4,              65536 );
@@ -1354,8 +1366,8 @@
 
 Bool VG_(addr_is_in_block)( Addr a, Addr start, SizeT size )
 {  
-   return (start - VG_(vg_malloc_redzone_szB) <= a
-           && a < start + size + VG_(vg_malloc_redzone_szB));
+   return (start - client_malloc_redzone_szB <= a
+           && a < start + size + client_malloc_redzone_szB);
 }