Modularised the malloc/free stuff into two modules:  m_mallocfree for the
malloc/free implementation, and m_replacemalloc with the stuff for the tools
that replace malloc with their own version.  Previously these two areas of
functionality were mixed up somewhat.




git-svn-id: svn://svn.valgrind.org/valgrind/trunk@3648 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/Makefile.tool.am b/Makefile.tool.am
index 39aa6a1..f835685 100644
--- a/Makefile.tool.am
+++ b/Makefile.tool.am
@@ -4,3 +4,6 @@
 include $(top_srcdir)/Makefile.all.am
 include $(top_srcdir)/Makefile.tool-flags.am
 include $(top_srcdir)/Makefile.tool-inplace.am
+
+LIBREPLACEMALLOC = $(top_builddir)/coregrind/m_replacemalloc/libreplacemalloc_toolpreload.a
+
diff --git a/addrcheck/Makefile.am b/addrcheck/Makefile.am
index e49f5fa..88c53f8 100644
--- a/addrcheck/Makefile.am
+++ b/addrcheck/Makefile.am
@@ -16,10 +16,10 @@
 vgpreload_addrcheck_so_LDADD = \
 	../memcheck/mac_replace_strmem.o
 vgpreload_addrcheck_so_DEPENDENCIES = \
-	$(top_builddir)/coregrind/lib_replace_malloc.a \
+	$(LIBREPLACEMALLOC) \
 	../memcheck/mac_replace_strmem.o
 vgpreload_addrcheck_so_LDFLAGS = -shared -Wl,-z,interpose,-z,initfirst \
 	-Wl,--whole-archive \
-	$(top_builddir)/coregrind/lib_replace_malloc.a \
+	$(LIBREPLACEMALLOC) \
 	-Wl,--no-whole-archive
 
diff --git a/cachegrind/cg_main.c b/cachegrind/cg_main.c
index 2b36d43..02fccc1 100644
--- a/cachegrind/cg_main.c
+++ b/cachegrind/cg_main.c
@@ -30,7 +30,7 @@
 */
 
 #include "tool.h"
-//#include "vg_profile.c"
+#include "pub_tool_mallocfree.h"
 
 #include "cg_arch.h"
 #include "cg_sim.c"
diff --git a/configure.in b/configure.in
index 9c36557..8976935 100644
--- a/configure.in
+++ b/configure.in
@@ -395,6 +395,7 @@
    coregrind/Makefile 
    coregrind/demangle/Makefile 
    coregrind/m_aspacemgr/Makefile 
+   coregrind/m_replacemalloc/Makefile 
    coregrind/m_sigframe/Makefile 
    coregrind/m_syscalls/Makefile 
    coregrind/amd64/Makefile
diff --git a/coregrind/Makefile.am b/coregrind/Makefile.am
index 5d4f753..4a9ddc9 100644
--- a/coregrind/Makefile.am
+++ b/coregrind/Makefile.am
@@ -4,6 +4,7 @@
 MODULES = \
 	demangle \
 	m_aspacemgr \
+	m_replacemalloc \
 	m_sigframe \
 	m_syscalls
 
@@ -33,8 +34,6 @@
 	stage2 \
 	vg_inject.so
 
-noinst_LIBRARIES = lib_replace_malloc.a
-
 noinst_HEADERS = \
 	core.h			\
 	core_asm.h		\
@@ -42,6 +41,8 @@
 	pub_core_debuglog.h	\
 	pub_core_errormgr.h	\
 	pub_core_execontext.h	\
+	pub_core_mallocfree.h	\
+	pub_core_replacemalloc.h\
 	pub_core_sigframe.h	\
 	pub_core_stacktrace.h	\
 	pub_core_syscalls.h	\
@@ -66,6 +67,7 @@
 stage2_SOURCES = \
 	m_errormgr.c \
 	m_execontext.c \
+	m_mallocfree.c \
 	m_stacktrace.c \
 	m_debuglog.c \
 	ume.c \
@@ -73,9 +75,7 @@
 	vg_scheduler.c \
 	vg_demangle.c \
 	vg_hashtable.c \
-	vg_replace_malloc.c \
 	vg_main.c \
-	vg_malloc2.c \
 	vg_messages.c \
 	vg_mylibc.c \
 	vg_needs.c \
@@ -103,28 +103,41 @@
 	${VG_OS}/libos.a \
 	@VEX_DIR@/libvex.a
 
-## Test repeated in both arms of the if-then-else because older versions of
-## automake don't seem to like having += within an if-then-else.
+## These ones must be linked in with the --whole-archive flag, because they
+## wouldn't get pulled into stage otherwise (because they contain symbols
+## only referred to by tool shared objects).
+stage2_extra2 = \
+	m_replacemalloc/libreplacemalloc_core.a
+	
+## Nb: older versions of automake don't seem to like having += within an
+## if-then-else, so we have to use these variables for the common parts.
+st2_DEPS_common = \
+	$(srcdir)/valgrind.vs \
+	$(stage2_extra) \
+	$(stage2_extra2)
+
+st2_LDFLAGS_common = \
+	-Wl,--export-dynamic -g \
+	-Wl,-version-script $(srcdir)/valgrind.vs
+
 if USE_PIE
 stage2_CFLAGS = $(AM_CFLAGS) -fpie
-stage2_DEPENDENCIES = \
-	$(srcdir)/valgrind.vs \
-	$(stage2_extra)
-stage2_LDFLAGS = -Wl,--export-dynamic -g \
-	-Wl,-version-script $(srcdir)/valgrind.vs \
+stage2_DEPENDENCIES = $(st2_DEPS_common)
+stage2_LDFLAGS = \
+	$(st2_LDFLAGS_common) \
+	-Wl,--whole-archive $(stage2_extra2) -Wl,--no-whole-archive \
 	-pie
 else
 stage2_CFLAGS = $(AM_CFLAGS)
-stage2_DEPENDENCIES = \
-	$(srcdir)/valgrind.vs ${VG_ARCH}/stage2.lds \
-	$(stage2_extra)
-stage2_LDFLAGS = -Wl,--export-dynamic -g \
-	-Wl,-version-script $(srcdir)/valgrind.vs \
+stage2_DEPENDENCIES = $(st2_DEPS_common) ${VG_ARCH}/stage2.lds
+stage2_LDFLAGS = \
+	$(st2_LDFLAGS_common) \
+	-Wl,--whole-archive $(stage2_extra2) -Wl,--no-whole-archive \
 	-Wl,-defsym,kickstart_base=@KICKSTART_BASE@ -Wl,-T,${VG_ARCH}/stage2.lds
 endif
 
-stage2_LDADD= $(stage2_extra) -ldl
-
+stage2_LDADD= $(stage2_extra) \
+	-ldl
 
 vg_inject_so_SOURCES = vg_intercept.c
 vg_inject_so_CFLAGS = $(AM_CFLAGS) -fpic
@@ -134,9 +147,6 @@
 	-Wl,--soname,vg_inject.so \
 	-Wl,-z,initfirst
 
-lib_replace_malloc_a_SOURCES = vg_replace_malloc.c
-lib_replace_malloc_a_CFLAGS  = $(AM_CFLAGS) -fpic -fno-omit-frame-pointer
-
 MANUAL_DEPS = $(noinst_HEADERS) $(include_HEADERS)
 
 all-local:
diff --git a/coregrind/README_MODULES.txt b/coregrind/README_MODULES.txt
index 9c6ee01..4f66de2 100644
--- a/coregrind/README_MODULES.txt
+++ b/coregrind/README_MODULES.txt
@@ -43,6 +43,8 @@
 pub_tool_foo.h, if it exists.  pub_tool_foo.h *must not* #include
 pub_core_foo.h, nor any other pub_core_ header for that matter.
 
+Module-private headers are named "priv_foo.h".
+
 No module may include the private headers of any other module.  If a
 type/enum/function/struct/whatever is stated in neither
 include/pub_tool_foo.h nor coregrind/pub_core_foo.h then module 'foo'
diff --git a/coregrind/core.h b/coregrind/core.h
index f52bf57..8c2aece 100644
--- a/coregrind/core.h
+++ b/coregrind/core.h
@@ -1,7 +1,6 @@
 
 /*--------------------------------------------------------------------*/
-/*--- A header file for all private parts of Valgrind's core.      ---*/
-/*--- Include no other! (more or less...)                          ---*/
+/*--- A header file for various private parts of Valgrind's core.  ---*/
 /*---                                                       core.h ---*/
 /*--------------------------------------------------------------------*/
 
@@ -97,6 +96,7 @@
                            //   eg. x86-linux/core_platform.h
 #include "core_os.h"       // OS-specific stuff,    eg. linux/core_os.h
 
+#include "pub_core_mallocfree.h"  // for type 'ArenaId'
 #include "pub_core_stacktrace.h"  // for type 'StackTrace'
 
 #include "valgrind.h"
@@ -458,57 +458,6 @@
 
 
 /* ---------------------------------------------------------------------
-   Exports of vg_malloc2.c
-   ------------------------------------------------------------------ */
-
-/* Allocation arenas.  
-
-      CORE      for the core's general use.
-      TOOL      for the tool to use (and the only one it uses).
-      SYMTAB    for Valgrind's symbol table storage.
-      CLIENT    for the client's mallocs/frees, if the tool replaces glibc's
-                    malloc() et al -- redzone size is chosen by the tool.
-      DEMANGLE  for the C++ demangler.
-      EXECTXT   for storing ExeContexts.
-      ERRORS    for storing CoreErrors.
-
-   When adding a new arena, remember also to add it to ensure_mm_init(). 
-*/
-typedef Int ArenaId;
-
-#define VG_N_ARENAS        7
-
-#define VG_AR_CORE         0
-#define VG_AR_TOOL         1
-#define VG_AR_SYMTAB       2
-#define VG_AR_CLIENT       3
-#define VG_AR_DEMANGLE     4
-#define VG_AR_EXECTXT      5
-#define VG_AR_ERRORS       6
-
-// This is both the minimum payload size of a malloc'd block, and its
-// minimum alignment.  Must be a power of 2 greater than 4, and should be
-// greater than 8.
-#define VG_MIN_MALLOC_SZB        8
-
-extern void* VG_(arena_malloc)  ( ArenaId arena, SizeT nbytes );
-extern void  VG_(arena_free)    ( ArenaId arena, void* ptr );
-extern void* VG_(arena_calloc)  ( ArenaId arena, 
-                                  SizeT nmemb, SizeT bytes_per_memb );
-extern void* VG_(arena_realloc) ( ArenaId arena, void* ptr, SizeT size );
-
-/* Sets the size of the redzones at the start and end of heap blocks.  This
-   must be called before any of VG_(malloc) and friends are called. */
-extern void  VG_(set_client_malloc_redzone_szB) ( SizeT rz_szB );
-
-extern SizeT VG_(arena_payload_szB) ( ArenaId aid, void* payload );
-
-extern void  VG_(sanity_check_malloc_all) ( void );
-
-extern void  VG_(print_all_arena_stats) ( void );
-
-
-/* ---------------------------------------------------------------------
    Exports of vg_intercept.c
    ------------------------------------------------------------------ */
 
@@ -575,10 +524,10 @@
    A synonym for exit. */
 #define VG_USERREQ__LIBC_FREERES_DONE       0x3029
 
-/* Intercept prefix stuff.  See coregrind/vg_replace_malloc.c for
-   details.  Unfortunately the "_vgi_" literal is also hardcoded in
-   that file, so if you change this one you must also change the other
-   one. */
+/* Intercept prefix stuff.  See
+   coregrind/m_replace_malloc/vg_replace_malloc.c for details.
+   Unfortunately the "_vgi_" literal is also hardcoded in that file, so if
+   you change this one you must also change the other one. */
 #define VG_INTERCEPT_PREFIX "_vgi_"
 #define VG_INTERCEPT_PREFIX_LEN 5
 
diff --git a/coregrind/vg_malloc2.c b/coregrind/m_mallocfree.c
similarity index 89%
rename from coregrind/vg_malloc2.c
rename to coregrind/m_mallocfree.c
index e7aebdd..f2908a6 100644
--- a/coregrind/vg_malloc2.c
+++ b/coregrind/m_mallocfree.c
@@ -1,7 +1,7 @@
 
 /*--------------------------------------------------------------------*/
 /*--- An implementation of malloc/free which doesn't use sbrk.     ---*/
-/*---                                                 vg_malloc2.c ---*/
+/*---                                               m_mallocfree.c ---*/
 /*--------------------------------------------------------------------*/
 
 /*
@@ -519,61 +519,6 @@
 
 
 /*------------------------------------------------------------*/
-/*--- Command line options                                 ---*/
-/*------------------------------------------------------------*/
-
-/* Nb: the allocator always rounds blocks up to a multiple of
-   VG_MIN_MALLOC_SZB.
-*/
-
-/* DEBUG: print malloc details?  default: NO */
-Bool VG_(clo_trace_malloc)  = False;
-
-/* Minimum alignment in functions that don't specify alignment explicitly.
-   default: 0, i.e. use VG_MIN_MALLOC_SZB. */
-UInt VG_(clo_alignment)     = VG_MIN_MALLOC_SZB;
-
-
-Bool VG_(replacement_malloc_process_cmd_line_option)(Char* arg)
-{
-   if (VG_CLO_STREQN(12, arg, "--alignment=")) {
-      VG_(clo_alignment) = (UInt)VG_(atoll)(&arg[12]);
-
-      if (VG_(clo_alignment) < VG_MIN_MALLOC_SZB
-          || VG_(clo_alignment) > 4096
-          || VG_(log2)( VG_(clo_alignment) ) == -1 /* not a power of 2 */) {
-         VG_(message)(Vg_UserMsg, "");
-         VG_(message)(Vg_UserMsg, 
-            "Invalid --alignment= setting.  "
-            "Should be a power of 2, >= %d, <= 4096.", VG_MIN_MALLOC_SZB);
-         VG_(bad_option)("--alignment");
-      }
-   }
-
-   else VG_BOOL_CLO(arg, "--trace-malloc",  VG_(clo_trace_malloc))
-   else 
-      return False;
-
-   return True;
-}
-
-void VG_(replacement_malloc_print_usage)(void)
-{
-   VG_(printf)(
-"    --alignment=<number>      set minimum alignment of allocations [%d]\n",
-   VG_MIN_MALLOC_SZB
-   );
-}
-
-void VG_(replacement_malloc_print_debug_usage)(void)
-{
-   VG_(printf)(
-"    --trace-malloc=no|yes     show client malloc details? [no]\n"
-   );
-}
-
-
-/*------------------------------------------------------------*/
 /*--- Functions for working with freelists.                ---*/
 /*------------------------------------------------------------*/
 
@@ -1150,8 +1095,7 @@
    .    .               .   .   .               .   .
 
 */
-static 
-void* arena_malloc_aligned ( ArenaId aid, SizeT req_alignB, SizeT req_pszB )
+void* VG_(arena_memalign) ( ArenaId aid, SizeT req_alignB, SizeT req_pszB )
 {
    SizeT  base_pszB_req, base_pszB_act, frag_bszB;
    Block  *base_b, *align_b;
@@ -1170,10 +1114,10 @@
    // a power of 2.
    if (req_alignB < VG_MIN_MALLOC_SZB
        || req_alignB > 1048576
-       || VG_(log2)( VG_(clo_alignment) ) == -1 /* not a power of 2 */) {
-      VG_(printf)("arena_malloc_aligned(%p, %d, %d)\nbad alignment", 
+       || VG_(log2)( req_alignB ) == -1 /* not a power of 2 */) {
+      VG_(printf)("VG_(arena_memalign)(%p, %d, %d)\nbad alignment", 
                   a, req_alignB, req_pszB );
-      VG_(core_panic)("arena_malloc_aligned");
+      VG_(core_panic)("VG_(arena_memalign)");
       /*NOTREACHED*/
    }
    // Paranoid
@@ -1346,103 +1290,6 @@
    return VG_(arena_realloc) ( VG_AR_TOOL, ptr, size );
 }
 
-void* VG_(cli_malloc) ( SizeT align, SizeT nbytes )                 
-{                                                                             
-   // 'align' should be valid (ie. big enough and a power of two) by now.
-   // arena_malloc_aligned() will abort if it's not.
-   if (VG_MIN_MALLOC_SZB == align)
-      return VG_(arena_malloc)    ( VG_AR_CLIENT, nbytes ); 
-   else                                                                       
-      return arena_malloc_aligned ( VG_AR_CLIENT, align, nbytes );
-}                                                                             
-
-void VG_(cli_free) ( void* p )                                   
-{                                                                             
-   VG_(arena_free) ( VG_AR_CLIENT, p );                          
-}
-
-
-Bool VG_(addr_is_in_block)( Addr a, Addr start, SizeT size )
-{  
-   return (start - client_malloc_redzone_szB <= a
-           && a < start + size + client_malloc_redzone_szB);
-}
-
-
-/*------------------------------------------------------------*/
-/*--- The original test driver machinery.                  ---*/
-/*------------------------------------------------------------*/
-
-#if 0
-
-#if 1
-#define N_TEST_TRANSACTIONS 100000000
-#define N_TEST_ARR 200000
-#define M_TEST_MALLOC 1000
-#else
-#define N_TEST_TRANSACTIONS 500000
-#define N_TEST_ARR 30000
-#define M_TEST_MALLOC 500
-#endif
-
-
-void* test_arr[N_TEST_ARR];
-
-int main ( int argc, char** argv )
-{
-   Int i, j, k, nbytes, qq;
-   unsigned char* chp;
-   Arena* a = &arena[VG_AR_CORE];
-   srandom(1);
-   for (i = 0; i < N_TEST_ARR; i++)
-      test_arr[i] = NULL;
-
-   for (i = 0; i < N_TEST_TRANSACTIONS; i++) {
-      if (i % 50000 == 0) mallocSanityCheck(a);
-      j = random() % N_TEST_ARR;
-      if (test_arr[j]) {
-         vg_free(a, test_arr[j]);
-         test_arr[j] = NULL;
-      } else {
-         nbytes = 1 + random() % M_TEST_MALLOC;
-         qq = random()%64;
-         if (qq == 32) 
-            nbytes *= 17;
-         else if (qq == 33)
-            nbytes = 0;
-         test_arr[j] 
-           = (i % 17) == 0
-                ? vg_memalign(a, nbytes, 1<< (3+(random()%10)))
-                : vg_malloc( a, nbytes );
-         chp = test_arr[j];
-         for (k = 0; k < nbytes; k++) 
-            chp[k] = (unsigned char)(k + 99);
-      }
-   }
-
-
-   for (i = 0; i < N_TEST_ARR; i++) {
-      if (test_arr[i]) {
-         vg_free(a, test_arr[i]);
-         test_arr[i] = NULL;
-      }
-   }
-   mallocSanityCheck(a);
-
-   fprintf(stderr, "ALL DONE\n");
-
-   show_arena_stats(a);
-   fprintf(stderr, "%d max useful, %d bytes mmap'd (%4.1f%%), %d useful\n",
-           a->bytes_on_loan_max, 
-           a->bytes_mmaped, 
-           100.0 * (double)a->bytes_on_loan_max / (double)a->bytes_mmaped,
-           a->bytes_on_loan );
-
-   return 0;
-}
-#endif /* 0 */
-
-
 /*--------------------------------------------------------------------*/
-/*--- end                                             vg_malloc2.c ---*/
+/*--- end                                                          ---*/
 /*--------------------------------------------------------------------*/
diff --git a/coregrind/m_replacemalloc/Makefile.am b/coregrind/m_replacemalloc/Makefile.am
new file mode 100644
index 0000000..096492c
--- /dev/null
+++ b/coregrind/m_replacemalloc/Makefile.am
@@ -0,0 +1,27 @@
+include $(top_srcdir)/Makefile.all.am
+include $(top_srcdir)/Makefile.core-AM_CPPFLAGS.am
+
+AM_CFLAGS = $(WERROR) -Wmissing-prototypes -Winline -Wall -Wshadow -O -g
+
+EXTRA_DIST = \
+	README_REPLACEMALLOC.txt
+
+noinst_LIBRARIES = \
+	libreplacemalloc_core.a \
+	libreplacemalloc_toolpreload.a
+
+libreplacemalloc_core_a_SOURCES = \
+	replacemalloc_core.c
+
+if USE_PIE
+libreplacemalloc_core_a_CFLAGS 	= $(AM_CFLAGS) -fpie
+else
+libreplacemalloc_core_a_CFLAGS	= $(AM_CFLAGS)
+endif
+
+libreplacemalloc_toolpreload_a_SOURCES = \
+	vg_replace_malloc.c
+libreplacemalloc_toolpreload_a_CFLAGS = \
+	$(AM_CFLAGS) -fpic -fno-omit-frame-pointer
+
+
diff --git a/coregrind/m_replacemalloc/README_REPLACEMALLOC.txt b/coregrind/m_replacemalloc/README_REPLACEMALLOC.txt
new file mode 100644
index 0000000..607e060
--- /dev/null
+++ b/coregrind/m_replacemalloc/README_REPLACEMALLOC.txt
@@ -0,0 +1,29 @@
+The structure of this module is worth noting.
+
+The main part is in vg_replace_malloc.c.  It gets compiled into the tool's
+'preload' shared object, which goes into the client's area of memory, and
+runs on the simulated CPU just like client code.  As a result, it cannot
+use any functions in the core directly;  it can only communicated with the
+core using client requests, just like any other client code.
+
+And yet it must call the tool's malloc wrappers.  How does it know where
+they are?  The init function uses a client request which asks for the list
+of all the core functions (and variables) that it needs to access.  It then
+uses a client request each time it needs to call one of these.
+
+This means that the following sequence occurs each time a tool that uses
+this module starts up:
+
+ - Tool does initialisation, including calling VG_(malloc_funcs)() to tell
+   the core the names of its malloc wrappers.  These are stored in
+   VG_(tdict).
+
+ - On the first allocation, vg_replace_malloc.c:init() calls the
+   GET_MALLOCFUNCS client request to get the names of the malloc wrappers
+   out of VG_(tdict), storing them in 'info'.
+
+ - All calls to these functions are done using 'info'.
+
+This is a bit complex, but it's hard to see how it can be done more simply. 
+
+
diff --git a/coregrind/m_replacemalloc/replacemalloc_core.c b/coregrind/m_replacemalloc/replacemalloc_core.c
new file mode 100644
index 0000000..9ef336e
--- /dev/null
+++ b/coregrind/m_replacemalloc/replacemalloc_core.c
@@ -0,0 +1,114 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Malloc replacement.                     replacemalloc_core.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+   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.
+*/
+
+#include "core.h"
+#include "pub_core_replacemalloc.h"
+
+/*------------------------------------------------------------*/
+/*--- Command line options                                 ---*/
+/*------------------------------------------------------------*/
+
+/* Nb: the allocator always rounds blocks up to a multiple of
+   VG_MIN_MALLOC_SZB.
+*/
+
+/* DEBUG: print malloc details?  default: NO */
+Bool VG_(clo_trace_malloc)  = False;
+
+/* Minimum alignment in functions that don't specify alignment explicitly.
+   default: 0, i.e. use VG_MIN_MALLOC_SZB. */
+UInt VG_(clo_alignment)     = VG_MIN_MALLOC_SZB;
+
+
+Bool VG_(replacement_malloc_process_cmd_line_option)(Char* arg)
+{
+   if (VG_CLO_STREQN(12, arg, "--alignment=")) {
+      VG_(clo_alignment) = (UInt)VG_(atoll)(&arg[12]);
+
+      if (VG_(clo_alignment) < VG_MIN_MALLOC_SZB
+          || VG_(clo_alignment) > 4096
+          || VG_(log2)( VG_(clo_alignment) ) == -1 /* not a power of 2 */) {
+         VG_(message)(Vg_UserMsg, "");
+         VG_(message)(Vg_UserMsg, 
+            "Invalid --alignment= setting.  "
+            "Should be a power of 2, >= %d, <= 4096.", VG_MIN_MALLOC_SZB);
+         VG_(bad_option)("--alignment");
+      }
+   }
+
+   else VG_BOOL_CLO(arg, "--trace-malloc",  VG_(clo_trace_malloc))
+   else 
+      return False;
+
+   return True;
+}
+
+void VG_(replacement_malloc_print_usage)(void)
+{
+   VG_(printf)(
+"    --alignment=<number>      set minimum alignment of allocations [%d]\n",
+   VG_MIN_MALLOC_SZB
+   );
+}
+
+void VG_(replacement_malloc_print_debug_usage)(void)
+{
+   VG_(printf)(
+"    --trace-malloc=no|yes     show client malloc details? [no]\n"
+   );
+}
+
+/*------------------------------------------------------------*/
+/*--- Useful functions                                     ---*/
+/*------------------------------------------------------------*/
+
+void* VG_(cli_malloc) ( SizeT align, SizeT nbytes )                 
+{                                                                             
+   // 'align' should be valid (ie. big enough and a power of two) by now.
+   // VG_(arena_memalign)() will abort if it's not.
+   if (VG_MIN_MALLOC_SZB == align)
+      return VG_(arena_malloc)   ( VG_AR_CLIENT, nbytes ); 
+   else                                                                       
+      return VG_(arena_memalign) ( VG_AR_CLIENT, align, nbytes );
+}                                                                             
+
+void VG_(cli_free) ( void* p )                                   
+{                                                                             
+   VG_(arena_free) ( VG_AR_CLIENT, p );                          
+}
+
+Bool VG_(addr_is_in_block)( Addr a, Addr start, SizeT size, SizeT rz_szB )
+{
+   return ( start - rz_szB <= a  &&  a < start + size + rz_szB );
+}
+
+/*--------------------------------------------------------------------*/
+/*--- end                                                          ---*/
+/*--------------------------------------------------------------------*/
diff --git a/coregrind/vg_replace_malloc.c b/coregrind/m_replacemalloc/vg_replace_malloc.c
similarity index 98%
rename from coregrind/vg_replace_malloc.c
rename to coregrind/m_replacemalloc/vg_replace_malloc.c
index 39ca3f3..39cb997 100644
--- a/coregrind/vg_replace_malloc.c
+++ b/coregrind/m_replacemalloc/vg_replace_malloc.c
@@ -39,6 +39,10 @@
    This file can be linked into the injected so file for any tool that
    wishes to know about calls to malloc().  The tool must define all
    the functions that will be called via 'info'.
+
+   It's called vg_replace_malloc.c because this filename appears in stack
+   traces, so we want it to be something that should be obvious what it
+   means to users.
    ------------------------------------------------------------------ */
 
 #include "valgrind.h"            /* for VALGRIND_NON_SIMD_CALL[12] */
diff --git a/coregrind/pub_core_mallocfree.h b/coregrind/pub_core_mallocfree.h
new file mode 100644
index 0000000..f6d0ea1
--- /dev/null
+++ b/coregrind/pub_core_mallocfree.h
@@ -0,0 +1,93 @@
+
+/*--------------------------------------------------------------------*/
+/*--- High-level memory management.          pub_core_mallocfree.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+   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.
+*/
+
+#ifndef __PUB_CORE_MALLOCFREE_H
+#define __PUB_CORE_MALLOCFREE_H
+
+#include "pub_tool_mallocfree.h"
+
+//--------------------------------------------------------------------
+// PURPOSE: high-level memory allocation (malloc/free), for the core and
+// tools.
+//--------------------------------------------------------------------
+
+/* Allocation arenas.  
+
+      CORE      for the core's general use.
+      TOOL      for the tool to use (and the only one it uses).
+      SYMTAB    for Valgrind's symbol table storage.
+      CLIENT    for the client's mallocs/frees, if the tool replaces glibc's
+                    malloc() et al -- redzone size is chosen by the tool.
+      DEMANGLE  for the C++ demangler.
+      EXECTXT   for storing ExeContexts.
+      ERRORS    for storing CoreErrors.
+
+   When adding a new arena, remember also to add it to ensure_mm_init(). 
+*/
+typedef Int ArenaId;
+
+#define VG_N_ARENAS        7
+
+#define VG_AR_CORE         0
+#define VG_AR_TOOL         1
+#define VG_AR_SYMTAB       2
+#define VG_AR_CLIENT       3
+#define VG_AR_DEMANGLE     4
+#define VG_AR_EXECTXT      5
+#define VG_AR_ERRORS       6
+
+// This is both the minimum payload size of a malloc'd block, and its
+// minimum alignment.  Must be a power of 2 greater than 4, and should be
+// greater than 8.
+#define VG_MIN_MALLOC_SZB        8
+
+extern void* VG_(arena_malloc)  ( ArenaId arena, SizeT nbytes );
+extern void  VG_(arena_free)    ( ArenaId arena, void* ptr );
+extern void* VG_(arena_calloc)  ( ArenaId arena, 
+                                  SizeT nmemb, SizeT bytes_per_memb );
+extern void* VG_(arena_realloc) ( ArenaId arena, void* ptr, SizeT size );
+extern void* VG_(arena_memalign)( ArenaId aid, SizeT req_alignB, 
+                                               SizeT req_pszB );
+
+/* Sets the size of the redzones at the start and end of heap blocks.  This
+   must be called before any of VG_(malloc) and friends are called. */
+extern void  VG_(set_client_malloc_redzone_szB) ( SizeT rz_szB );
+
+extern SizeT VG_(arena_payload_szB) ( ArenaId aid, void* payload );
+
+extern void  VG_(sanity_check_malloc_all) ( void );
+
+extern void  VG_(print_all_arena_stats) ( void );
+
+#endif   // __PUB_CORE_MALLOCFREE_H
+
+/*--------------------------------------------------------------------*/
+/*--- end                                                          ---*/
+/*--------------------------------------------------------------------*/
diff --git a/coregrind/pub_core_replacemalloc.h b/coregrind/pub_core_replacemalloc.h
new file mode 100644
index 0000000..20ec1bc
--- /dev/null
+++ b/coregrind/pub_core_replacemalloc.h
@@ -0,0 +1,48 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Replacing malloc.                   pub_core_replacemalloc.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+   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.
+*/
+
+#ifndef __PUB_CORE_REPLACEMALLOC_H
+#define __PUB_CORE_REPLACEMALLOC_H
+
+//--------------------------------------------------------------------
+// PURPOSE: This module provides a short-cut for tools that need to
+// replace malloc/free with their own versions.
+//--------------------------------------------------------------------
+
+// Nb: there are no exports in this header;  all exports for this module
+// are in include/pub_tool_replacemalloc.h
+
+#include "pub_tool_replacemalloc.h"
+
+#endif   // __PUB_CORE_REPLACEMALLOC_H
+
+/*--------------------------------------------------------------------*/
+/*--- end                                                          ---*/
+/*--------------------------------------------------------------------*/
diff --git a/coregrind/vg_pthreadmodel.c b/coregrind/vg_pthreadmodel.c
index 84f2dc5..a54c62b 100644
--- a/coregrind/vg_pthreadmodel.c
+++ b/coregrind/vg_pthreadmodel.c
@@ -207,9 +207,7 @@
    // TL_(malloc) being a weak symbol, and it just doesn't fit with the
    // VG_(tdict) approach that we've switched to.  The right way to do this
    // will be to provide a function in the core that checks if
-   // VG_(tdict).malloc_malloc has been set (or perhaps it would be better
-   // to check whether VG_USERREQ__GET_MALLOCFUNCS has been called, ie.
-   // whether replace_malloc.c:init() has been called);  if so, it should
+   // VG_(tdict).malloc_malloc has been set;  if so, it should
    // call it, if not, it should call VG_(cli_malloc)().
 //   VG_(tl_malloc_called_deliberately) = True;
 //   data = TL_(malloc)(sizeof(*data));
diff --git a/coregrind/vg_scheduler.c b/coregrind/vg_scheduler.c
index 5d7bf02..585086d 100644
--- a/coregrind/vg_scheduler.c
+++ b/coregrind/vg_scheduler.c
@@ -61,6 +61,7 @@
 #include "core.h"
 
 #include "pub_core_errormgr.h"
+#include "pub_core_replacemalloc.h"
 #include "pub_core_stacktrace.h"
 #include "pub_core_syscalls.h"
 
diff --git a/helgrind/Makefile.am b/helgrind/Makefile.am
index a959391..320e276 100644
--- a/helgrind/Makefile.am
+++ b/helgrind/Makefile.am
@@ -6,10 +6,11 @@
 vgtool_helgrind_so_LDFLAGS = -shared
 
 vgpreload_helgrind_so_SOURCES = 
-vgpreload_helgrind_so_DEPENDENCIES = $(top_builddir)/coregrind/lib_replace_malloc.a
+vgpreload_helgrind_so_DEPENDENCIES = \
+	$(LIBREPLACEMALLOC)
 vgpreload_helgrind_so_LDFLAGS = -shared -Wl,-z,interpose,-z,initfirst \
 	-Wl,--whole-archive \
-	$(top_builddir)/coregrind/lib_replace_malloc.a \
+	$(LIBREPLACEMALLOC) \
 	-Wl,--no-whole-archive
 
 hgincludedir = $(includedir)/valgrind
diff --git a/helgrind/hg_main.c b/helgrind/hg_main.c
index acb612c..0677c80 100644
--- a/helgrind/hg_main.c
+++ b/helgrind/hg_main.c
@@ -30,6 +30,9 @@
 */
 
 #include "tool.h"
+#include "pub_tool_mallocfree.h"
+#include "pub_tool_replacemalloc.h"
+
 #include "helgrind.h"
 
 static UInt n_hg_warnings = 0;
diff --git a/include/Makefile.am b/include/Makefile.am
index 503c5dd..75fdaea 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -14,6 +14,8 @@
 	tool_asm.h 		\
 	pub_tool_errormgr.h 	\
 	pub_tool_execontext.h 	\
+	pub_tool_mallocfree.h 	\
+	pub_tool_replacemalloc.h\
 	pub_tool_stacktrace.h 	\
 	valgrind.h
 
diff --git a/include/pub_tool_mallocfree.h b/include/pub_tool_mallocfree.h
new file mode 100644
index 0000000..d89edaf
--- /dev/null
+++ b/include/pub_tool_mallocfree.h
@@ -0,0 +1,46 @@
+
+/*--------------------------------------------------------------------*/
+/*--- MallocFree: high-level memory management.                    ---*/
+/*---                                        pub_tool_mallocfree.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+   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.
+*/
+
+#ifndef __PUB_TOOL_MALLOCFREE_H
+#define __PUB_TOOL_MALLOCFREE_H
+
+// These can be for allocating memory used by tools.
+extern void* VG_(malloc)         ( SizeT nbytes );
+extern void  VG_(free)           ( void* p );
+extern void* VG_(calloc)         ( SizeT n, SizeT bytes_per_elem );
+extern void* VG_(realloc)        ( void* p, SizeT size );
+
+#endif   // __PUB_TOOL_MALLOCFREE_H
+
+/*--------------------------------------------------------------------*/
+/*--- end                                                          ---*/
+/*--------------------------------------------------------------------*/
+
diff --git a/include/pub_tool_replacemalloc.h b/include/pub_tool_replacemalloc.h
new file mode 100644
index 0000000..250bba8
--- /dev/null
+++ b/include/pub_tool_replacemalloc.h
@@ -0,0 +1,67 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Malloc replacement.                 pub_tool_replacemalloc.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+   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.
+*/
+
+#ifndef __PUB_TOOL_REPLACEMALLOC_H
+#define __PUB_TOOL_REPLACEMALLOC_H
+
+/* If a tool replaces malloc() et al, the easiest way to do so is to
+   link libreplacemalloc_toolpreload.o into its vgpreload_*.so file, and
+   use the functions declared below.  You can do it from scratch,
+   though, if you enjoy that sort of thing. */
+
+/* Can be called from VG_(tdict).malloc_malloc et al to do the actual
+ * alloc/freeing. */
+extern void* VG_(cli_malloc) ( SizeT align, SizeT nbytes );
+extern void  VG_(cli_free)   ( void* p );
+
+/* Check if an address is within a range, allowing for redzones at edges */
+extern Bool VG_(addr_is_in_block)( Addr a, Addr start,
+                                   SizeT size, SizeT rz_szB );
+
+/* ------------------------------------------------------------------ */
+/* Some options that can be used by a tool if malloc() et al are replaced.
+   The tool should call the functions in the appropriate places to give
+   control over these aspects of Valgrind's version of malloc(). */
+
+/* DEBUG: print malloc details?  default: NO */
+extern Bool VG_(clo_trace_malloc);
+/* Minimum alignment in functions that don't specify alignment explicitly.
+   default: VG_MIN_MALLOC_SZB */
+extern UInt VG_(clo_alignment);
+
+extern Bool VG_(replacement_malloc_process_cmd_line_option) ( Char* arg );
+extern void VG_(replacement_malloc_print_usage)             ( void );
+extern void VG_(replacement_malloc_print_debug_usage)       ( void );
+
+#endif   // __PUB_TOOL_REPLACEMALLOC_H
+
+/*--------------------------------------------------------------------*/
+/*--- end                                                          ---*/
+/*--------------------------------------------------------------------*/
diff --git a/include/tool.h b/include/tool.h
index 3571fb2..39caa89 100644
--- a/include/tool.h
+++ b/include/tool.h
@@ -317,11 +317,6 @@
 /* ------------------------------------------------------------------ */
 /* stdlib.h */
 
-extern void* VG_(malloc)         ( SizeT nbytes );
-extern void  VG_(free)           ( void* p );
-extern void* VG_(calloc)         ( SizeT n, SizeT bytes_per_elem );
-extern void* VG_(realloc)        ( void* p, SizeT size );
-
 /* terminate everything */
 extern void VG_(exit)( Int status )
             __attribute__ ((__noreturn__));
@@ -782,39 +777,6 @@
                                         SizeT size, const UChar* area );
 
 /*====================================================================*/
-/*=== Specific stuff for replacing malloc() and friends            ===*/
-/*====================================================================*/
-
-/* If a tool replaces malloc() et al, the easiest way to do so is to
-   link with vg_replace_malloc.o into its vgpreload_*.so file, and
-   follow the following instructions.  You can do it from scratch,
-   though, if you enjoy that sort of thing. */
-
-/* Can be called from VG_(tdict).malloc_malloc et al to do the actual
- * alloc/freeing. */
-extern void* VG_(cli_malloc) ( SizeT align, SizeT nbytes );
-extern void  VG_(cli_free)   ( void* p );
-
-/* Check if an address is within a range, allowing for redzones at edges */
-extern Bool VG_(addr_is_in_block)( Addr a, Addr start, SizeT size );
-
-/* ------------------------------------------------------------------ */
-/* Some options that can be used by a tool if malloc() et al are replaced.
-   The tool should call the functions in the appropriate places to give
-   control over these aspects of Valgrind's version of malloc(). */
-
-/* DEBUG: print malloc details?  default: NO */
-extern Bool VG_(clo_trace_malloc);
-/* Minimum alignment in functions that don't specify alignment explicitly.
-   default: VG_MIN_MALLOC_SZB */
-extern UInt VG_(clo_alignment);
-
-extern Bool VG_(replacement_malloc_process_cmd_line_option) ( Char* arg );
-extern void VG_(replacement_malloc_print_usage)             ( void );
-extern void VG_(replacement_malloc_print_debug_usage)       ( void );
-
-
-/*====================================================================*/
 /*=== Tool-specific stuff                                          ===*/
 /*====================================================================*/
 
diff --git a/massif/Makefile.am b/massif/Makefile.am
index 468794d..ffe94d9 100644
--- a/massif/Makefile.am
+++ b/massif/Makefile.am
@@ -8,10 +8,11 @@
 vgtool_massif_so_LDFLAGS = -shared
 
 vgpreload_massif_so_SOURCES = 
-vgpreload_massif_so_DEPENDENCIES = $(top_builddir)/coregrind/lib_replace_malloc.a
+vgpreload_massif_so_DEPENDENCIES = \
+	$(LIBREPLACEMALLOC)
 vgpreload_massif_so_LDFLAGS = -shared -Wl,-z,interpose,-z,initfirst \
 	-Wl,--whole-archive \
-	$(top_builddir)/coregrind/lib_replace_malloc.a \
+	$(LIBREPLACEMALLOC) \
 	-Wl,--no-whole-archive
 
 
diff --git a/massif/ms_main.c b/massif/ms_main.c
index 530ef21..df2ca80 100644
--- a/massif/ms_main.c
+++ b/massif/ms_main.c
@@ -35,8 +35,9 @@
 // structures below for more info on how things work.
 
 #include "tool.h"
+#include "pub_tool_mallocfree.h"
+#include "pub_tool_replacemalloc.h"
 #include "pub_tool_stacktrace.h"
-//#include "vg_profile.c"
 
 #include "valgrind.h"           // For {MALLOC,FREE}LIKE_BLOCK
 
diff --git a/memcheck/Makefile.am b/memcheck/Makefile.am
index 6deade3..7c710a0 100644
--- a/memcheck/Makefile.am
+++ b/memcheck/Makefile.am
@@ -7,10 +7,11 @@
 
 vgpreload_memcheck_so_SOURCES = \
 	mac_replace_strmem.c
-vgpreload_memcheck_so_DEPENDENCIES = $(top_builddir)/coregrind/lib_replace_malloc.a
+vgpreload_memcheck_so_DEPENDENCIES = \
+	$(LIBREPLACEMALLOC)
 vgpreload_memcheck_so_LDFLAGS = -shared -Wl,-z,interpose,-z,initfirst \
 	-Wl,--whole-archive \
-	$(top_builddir)/coregrind/lib_replace_malloc.a \
+	$(LIBREPLACEMALLOC) \
 	-Wl,--no-whole-archive
 
 vgtool_memcheck_so_SOURCES = \
diff --git a/memcheck/mac_shared.c b/memcheck/mac_shared.c
index 55a2bec..9594474 100644
--- a/memcheck/mac_shared.c
+++ b/memcheck/mac_shared.c
@@ -379,7 +379,8 @@
 {
    Addr a = *(Addr *)ap;
   
-   return VG_(addr_is_in_block)( a, mc->data, mc->size );
+   return VG_(addr_is_in_block)( a, mc->data, mc->size,
+                                 MAC_MALLOC_REDZONE_SZB );
 }
 
 /* Callback for searching malloc'd lists */
diff --git a/memcheck/mac_shared.h b/memcheck/mac_shared.h
index c541fc9..82303e8 100644
--- a/memcheck/mac_shared.h
+++ b/memcheck/mac_shared.h
@@ -37,6 +37,8 @@
 #define __MAC_SHARED_H
 
 #include "tool.h"
+#include "pub_tool_mallocfree.h"
+#include "pub_tool_replacemalloc.h"
 
 #define MAC_(str)    VGAPPEND(vgMAC_,str)
 
diff --git a/memcheck/mc_main.c b/memcheck/mc_main.c
index 547c5a9..e169250 100644
--- a/memcheck/mc_main.c
+++ b/memcheck/mc_main.c
@@ -2156,7 +2156,7 @@
   MAC_Chunk *m = (MAC_Chunk*)sh_ch;
   Addr a = *(Addr*)ap;
 
-  return VG_(addr_is_in_block)(a, m->data, m->size);
+  return VG_(addr_is_in_block)(a, m->data, m->size, MAC_MALLOC_REDZONE_SZB);
 }
 
 static Bool client_perm_maybe_describe( Addr a, AddrInfo* ai )
@@ -2168,7 +2168,8 @@
    for (i = 0; i < cgb_used; i++) {
       if (cgbs[i].start == 0 && cgbs[i].size == 0) 
          continue;
-      if (VG_(addr_is_in_block)(a, cgbs[i].start, cgbs[i].size)) {
+      // Use zero as the redzone for client blocks.
+      if (VG_(addr_is_in_block)(a, cgbs[i].start, cgbs[i].size, 0)) {
          MAC_Mempool **d, *mp;
 
          /* OK - maybe it's a mempool, too? */