Malloc replacement worked very much like a 'need', but wasn't one.
I've changed it so it now is, which makes it consistent with the
other 'needs'.  Because of this, I was also able to invert the dependence
between m_mallocfree and m_tooliface, which is related to setting
the redzone size for client heap blocks.  As a result, m_tooliface
now doesn't depend on anything except pub_core_basics.h, hooray!
 


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@3979 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/addrcheck/ac_main.c b/addrcheck/ac_main.c
index d36684d..d33564a 100644
--- a/addrcheck/ac_main.c
+++ b/addrcheck/ac_main.c
@@ -1344,7 +1344,7 @@
                                    ac_expensive_sanity_check);
    VG_(needs_shadow_memory)       ();
 
-   VG_(malloc_funcs)              (MAC_(malloc),
+   VG_(needs_malloc_replacement)  (MAC_(malloc),
                                    MAC_(__builtin_new),
                                    MAC_(__builtin_vec_new),
                                    MAC_(memalign),
diff --git a/coregrind/m_mallocfree.c b/coregrind/m_mallocfree.c
index 35730c1..cc203c4 100644
--- a/coregrind/m_mallocfree.c
+++ b/coregrind/m_mallocfree.c
@@ -37,6 +37,7 @@
 #include "pub_core_mallocfree.h"
 #include "pub_core_options.h"
 #include "pub_core_profile.h"
+#include "pub_core_tooliface.h"
 #include "valgrind.h"
 
 //zz#include "memcheck/memcheck.h"
@@ -386,31 +387,6 @@
    }
 }
 
-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"
-         "%s cannot be called after the first allocation.\n",
-         __PRETTY_FUNCTION__);
-      VG_(exit)(1);
-   }
-   // This limit is no special figure, just something not too big
-   if (rz_szB > 128) {
-      VG_(printf)(
-         "\nTool error:\n"
-         "  %s passed a too-big value (%llu)", 
-         __PRETTY_FUNCTION__, (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
@@ -418,10 +394,29 @@
 static
 void ensure_mm_init ( void )
 {
+   static Bool  init_done = False;
+   static SizeT client_redzone_szB = 8;   // default: be paranoid
+
    if (init_done) {
+      // This assertion ensures that a tool cannot try to change the client
+      // redzone size with VG_(needs_malloc_replacement)() after this module
+      // has done its first allocation.
+      if (VG_(needs).malloc_replacement)
+         vg_assert(client_redzone_szB == VG_(tdict).tool_client_redzone_szB);
       return;
    }
 
+   if (VG_(needs).malloc_replacement) {
+      client_redzone_szB = VG_(tdict).tool_client_redzone_szB;
+      // 128 is no special figure, just something not too big
+      if (client_redzone_szB > 128) {
+         VG_(printf)( "\nTool error:\n"
+                      "  specified redzone size is too big (%llu)\n", 
+                      (ULong)client_redzone_szB);
+         VG_(exit)(1);
+      }
+   }
+
    /* 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. 
@@ -437,7 +432,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_malloc_redzone_szB, 1048576 );
+   arena_init ( VG_AR_CLIENT,    "client", client_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 );
diff --git a/coregrind/m_scheduler/scheduler.c b/coregrind/m_scheduler/scheduler.c
index afbedd0..26def4d 100644
--- a/coregrind/m_scheduler/scheduler.c
+++ b/coregrind/m_scheduler/scheduler.c
@@ -980,15 +980,15 @@
       case VG_USERREQ__GET_MALLOCFUNCS: {
 	 struct vg_mallocfunc_info *info = (struct vg_mallocfunc_info *)arg[1];
 
-	 info->tl_malloc               = VG_(tdict).malloc_malloc;
-	 info->tl_calloc               = VG_(tdict).malloc_calloc;
-	 info->tl_realloc              = VG_(tdict).malloc_realloc;
-	 info->tl_memalign             = VG_(tdict).malloc_memalign;
-	 info->tl___builtin_new        = VG_(tdict).malloc___builtin_new;
-	 info->tl___builtin_vec_new    = VG_(tdict).malloc___builtin_vec_new;
-	 info->tl_free                 = VG_(tdict).malloc_free;
-	 info->tl___builtin_delete     = VG_(tdict).malloc___builtin_delete;
-	 info->tl___builtin_vec_delete = VG_(tdict).malloc___builtin_vec_delete;
+	 info->tl_malloc               = VG_(tdict).tool_malloc;
+	 info->tl_calloc               = VG_(tdict).tool_calloc;
+	 info->tl_realloc              = VG_(tdict).tool_realloc;
+	 info->tl_memalign             = VG_(tdict).tool_memalign;
+	 info->tl___builtin_new        = VG_(tdict).tool___builtin_new;
+	 info->tl___builtin_vec_new    = VG_(tdict).tool___builtin_vec_new;
+	 info->tl_free                 = VG_(tdict).tool_free;
+	 info->tl___builtin_delete     = VG_(tdict).tool___builtin_delete;
+	 info->tl___builtin_vec_delete = VG_(tdict).tool___builtin_vec_delete;
 
 	 info->arena_payload_szB       = VG_(arena_payload_szB);
 	 info->clo_trace_malloc        = VG_(clo_trace_malloc);
diff --git a/coregrind/m_tooliface.c b/coregrind/m_tooliface.c
index db8962e..619f2d3 100644
--- a/coregrind/m_tooliface.c
+++ b/coregrind/m_tooliface.c
@@ -30,7 +30,6 @@
 */
 
 #include "pub_core_basics.h"
-#include "pub_core_mallocfree.h"    // For VG_(set_client_malloc_redzone_szB)()
 #include "pub_core_tooliface.h"
 
 // The core/tool dictionary of functions (initially zeroed, as we want it)
@@ -87,14 +86,13 @@
    .tool_errors          = False,
    .libc_freeres         = False,
    .basic_block_discards = False,
-   .no_longer_used_1     = False,
    .command_line_options = False,
    .client_requests      = False,
-   .no_longer_used_0     = False,
    .syscall_wrapper      = False,
    .sanity_checks        = False,
    .data_syms	         = False,
    .shadow_memory        = False,
+   .malloc_replacement   = False,
 };
 
 /* static */
@@ -233,11 +231,7 @@
    VG_(tdict).tool_expensive_sanity_check = expen;
 }
 
-
-/*--------------------------------------------------------------------*/
-/* Replacing malloc() */
-
-extern void VG_(malloc_funcs)(
+void VG_(needs_malloc_replacement)(
    void* (*malloc)               ( ThreadId, SizeT ),
    void* (*__builtin_new)        ( ThreadId, SizeT ),
    void* (*__builtin_vec_new)    ( ThreadId, SizeT ),
@@ -250,17 +244,17 @@
    SizeT client_malloc_redzone_szB
 )
 {
-   VG_(tdict).malloc_malloc               = malloc;
-   VG_(tdict).malloc___builtin_new        = __builtin_new;
-   VG_(tdict).malloc___builtin_vec_new    = __builtin_vec_new;
-   VG_(tdict).malloc_memalign             = memalign;
-   VG_(tdict).malloc_calloc               = calloc;
-   VG_(tdict).malloc_free                 = free;
-   VG_(tdict).malloc___builtin_delete     = __builtin_delete;
-   VG_(tdict).malloc___builtin_vec_delete = __builtin_vec_delete;
-   VG_(tdict).malloc_realloc              = realloc;
-
-   VG_(set_client_malloc_redzone_szB)( client_malloc_redzone_szB );
+   VG_(needs).malloc_replacement        = True;
+   VG_(tdict).tool_malloc               = malloc;
+   VG_(tdict).tool___builtin_new        = __builtin_new;
+   VG_(tdict).tool___builtin_vec_new    = __builtin_vec_new;
+   VG_(tdict).tool_memalign             = memalign;
+   VG_(tdict).tool_calloc               = calloc;
+   VG_(tdict).tool_free                 = free;
+   VG_(tdict).tool___builtin_delete     = __builtin_delete;
+   VG_(tdict).tool___builtin_vec_delete = __builtin_vec_delete;
+   VG_(tdict).tool_realloc              = realloc;
+   VG_(tdict).tool_client_redzone_szB   = client_malloc_redzone_szB;
 }
 
 
diff --git a/coregrind/pub_core_tooliface.h b/coregrind/pub_core_tooliface.h
index dcd30ee..2b2d10b 100644
--- a/coregrind/pub_core_tooliface.h
+++ b/coregrind/pub_core_tooliface.h
@@ -84,14 +84,13 @@
       Bool core_errors;
       Bool tool_errors;
       Bool basic_block_discards;
-      Bool no_longer_used_1;     // for backwards compatibility
       Bool command_line_options;
       Bool client_requests;
-      Bool no_longer_used_0;     // for backwards compatibility
       Bool syscall_wrapper;
       Bool sanity_checks;
       Bool data_syms;
       Bool shadow_memory;
+      Bool malloc_replacement;
    } 
    VgNeeds;
 
@@ -141,6 +140,18 @@
    Bool (*tool_cheap_sanity_check)(void);
    Bool (*tool_expensive_sanity_check)(void);
 
+   // VG_(needs).malloc_replacement
+   void* (*tool_malloc)              (ThreadId, SizeT);
+   void* (*tool___builtin_new)       (ThreadId, SizeT);
+   void* (*tool___builtin_vec_new)   (ThreadId, SizeT);
+   void* (*tool_memalign)            (ThreadId, SizeT, SizeT);
+   void* (*tool_calloc)              (ThreadId, SizeT, SizeT);
+   void  (*tool_free)                (ThreadId, void*);
+   void  (*tool___builtin_delete)    (ThreadId, void*);
+   void  (*tool___builtin_vec_delete)(ThreadId, void*);
+   void* (*tool_realloc)             (ThreadId, void*, SizeT);
+   SizeT tool_client_redzone_szB;
+
    // -- Event tracking functions ------------------------------------
    void (*track_new_mem_startup)     (Addr, SizeT, Bool, Bool, Bool);
    void (*track_new_mem_stack_signal)(Addr, SizeT);
@@ -192,17 +203,6 @@
 
    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);
diff --git a/helgrind/hg_main.c b/helgrind/hg_main.c
index 372f6f8..f66448d 100644
--- a/helgrind/hg_main.c
+++ b/helgrind/hg_main.c
@@ -3392,7 +3392,7 @@
                                    hg_print_debug_usage);
    VG_(needs_shadow_memory)       ();
 
-   VG_(malloc_funcs)              (hg_malloc,
+   VG_(needs_malloc_replacement)  (hg_malloc,
                                    hg___builtin_new,
                                    hg___builtin_vec_new,
                                    hg_memalign,
diff --git a/include/pub_tool_tooliface.h b/include/pub_tool_tooliface.h
index 5514080..ab39e7c 100644
--- a/include/pub_tool_tooliface.h
+++ b/include/pub_tool_tooliface.h
@@ -253,11 +253,9 @@
 /* Does the tool need shadow memory allocated? */
 extern void VG_(needs_shadow_memory)( void );
 
-/* ------------------------------------------------------------------ */
-/* Malloc replacement */
-
+/* Does the tool replace malloc() and friends with its own versions? */
 // The 'p' prefix avoids GCC complaints about overshadowing global names.
-extern void VG_(malloc_funcs)(
+extern void VG_(needs_malloc_replacement)(
    void* (*pmalloc)               ( ThreadId tid, SizeT n ),
    void* (*p__builtin_new)        ( ThreadId tid, SizeT n ),
    void* (*p__builtin_vec_new)    ( ThreadId tid, SizeT n ),
diff --git a/massif/ms_main.c b/massif/ms_main.c
index 18890a1..16f387d 100644
--- a/massif/ms_main.c
+++ b/massif/ms_main.c
@@ -1802,9 +1802,7 @@
                                    ms_print_usage,
                                    ms_print_debug_usage);
    VG_(needs_client_requests)     (ms_handle_client_request);
-
-   // Malloc replacement
-   VG_(malloc_funcs)              (ms_malloc,
+   VG_(needs_malloc_replacement)  (ms_malloc,
                                    ms___builtin_new,
                                    ms___builtin_vec_new,
                                    ms_memalign,
diff --git a/memcheck/mc_main.c b/memcheck/mc_main.c
index 6a1365b..cb75c2f 100644
--- a/memcheck/mc_main.c
+++ b/memcheck/mc_main.c
@@ -2554,7 +2554,7 @@
                                    mc_expensive_sanity_check);
    VG_(needs_shadow_memory)       ();
 
-   VG_(malloc_funcs)              (MAC_(malloc),
+   VG_(needs_malloc_replacement)  (MAC_(malloc),
                                    MAC_(__builtin_new),
                                    MAC_(__builtin_vec_new),
                                    MAC_(memalign),