summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcsilvers <csilvers@6b5cf1ce-ec42-a296-1ba9-69fdba395a50>2009-09-11 18:42:32 +0000
committercsilvers <csilvers@6b5cf1ce-ec42-a296-1ba9-69fdba395a50>2009-09-11 18:42:32 +0000
commit19dfa9e3733155e57406fbd082273eb53cb2750e (patch)
tree8c000b5035acf1bd01cb7208972e128bbd98e4b2
parent2197cc670204c583bba3903b765c77620f349609 (diff)
downloadgperftools-19dfa9e3733155e57406fbd082273eb53cb2750e.tar.gz
Thu Sep 10 13:51:15 2009 Google Inc. <opensource@google.com>
* google-perftools: version 1.4 release * Add debugallocation library, to catch memory leaks, stomping, etc * Add --raw mode to allow for delayed processing of pprof files * Use less memory when reading CPU profiles * New environment variables to control kernel-allocs (sbrk, memfs, etc) * Add MarkThreadBusy(): performance improvement * Remove static thread-cache-size code; all is dynamic now * Add new HiddenPointer class to heap checker * BUGFIX: pvalloc(0) allocates now (found by new debugalloc library) * BUGFIX: valloc test (not implementation) no longer overruns memory * BUGFIX: GetHeapProfile no longer deadlocks * BUGFIX: Support unmapping memory regions before main * BUGFIX: Fix some malloc-stats formatting * BUGFIX: Don't crash as often when freeing libc-allocated memory * BUGFIX: Deal better with incorrect PPROF_PATH when symbolizing * BUGFIX: weaken new/delete/etc in addition to malloc/free/etc * BUGFIX: Fix return value of GetAllocatedSize * PORTING: Fix mmap-#define problem on some 64-bit systems * PORTING: Call ranlib again (some OS X versions need it) * PORTING: Fix a leak when building with LLVM * PORTING: Remove some unneeded bash-ishs from testing scripts * WINDOWS: Support library unloading as well as loading * WINDOWS/BUGFIX: Set page to 'xrw' instead of 'rw' when patching git-svn-id: http://gperftools.googlecode.com/svn/trunk@76 6b5cf1ce-ec42-a296-1ba9-69fdba395a50
-rw-r--r--ChangeLog26
-rw-r--r--Makefile.am199
-rw-r--r--Makefile.in1176
-rw-r--r--aclocal.m41
-rwxr-xr-xconfigure537
-rw-r--r--configure.ac64
-rw-r--r--doc/tcmalloc.html67
-rwxr-xr-xgoogle-perftools.sln1
-rw-r--r--m4/install_prefix.m42
-rw-r--r--m4/pc_from_ucontext.m456
-rw-r--r--packages/deb/changelog6
-rw-r--r--src/base/atomicops-internals-macosx.h15
-rw-r--r--src/base/atomicops-internals-x86.cc2
-rw-r--r--src/base/atomicops-internals-x86.h10
-rw-r--r--src/base/basictypes.h9
-rw-r--r--src/base/dynamic_annotations.cc3
-rw-r--r--src/base/dynamic_annotations.h80
-rw-r--r--src/base/logging.h14
-rw-r--r--src/base/low_level_alloc.cc3
-rw-r--r--src/base/low_level_alloc.h3
-rw-r--r--src/base/simple_mutex.h79
-rw-r--r--src/base/spinlock.cc78
-rw-r--r--src/base/spinlock.h11
-rw-r--r--src/base/spinlock_linux-inl.h84
-rw-r--r--src/base/spinlock_posix-inl.h52
-rw-r--r--src/base/spinlock_win32-inl.h47
-rw-r--r--src/base/sysinfo.cc3
-rw-r--r--src/base/sysinfo.h3
-rw-r--r--src/base/vdso_support.cc184
-rw-r--r--src/base/vdso_support.h14
-rw-r--r--src/common.cc26
-rw-r--r--src/common.h2
-rw-r--r--src/config.h.in6
-rw-r--r--src/debugallocation.cc1367
-rw-r--r--src/getpc.h7
-rw-r--r--src/google/heap-checker.h34
-rw-r--r--src/google/malloc_extension.h15
-rw-r--r--src/google/malloc_extension_c.h26
-rw-r--r--src/google/tcmalloc.h.in61
-rw-r--r--src/heap-checker.cc14
-rw-r--r--src/heap-profile-table.cc99
-rw-r--r--src/heap-profiler.cc4
-rw-r--r--src/malloc_extension.cc19
-rw-r--r--src/malloc_hook.cc8
-rw-r--r--src/memfs_malloc.cc68
-rw-r--r--src/memory_region_map.cc32
-rw-r--r--src/packed-cache-inl.h14
-rw-r--r--src/page_heap.h3
-rw-r--r--src/pagemap.h19
-rwxr-xr-xsrc/pprof445
-rw-r--r--src/profiler.cc21
-rwxr-xr-xsrc/sampler.h4
-rw-r--r--src/stacktrace_win32-inl.h12
-rw-r--r--src/stacktrace_with_context.cc4
-rw-r--r--src/stacktrace_x86-inl.h66
-rw-r--r--src/symbolize.cc162
-rw-r--r--src/symbolize.h38
-rw-r--r--src/system-alloc.cc5
-rw-r--r--src/tcmalloc.cc132
-rw-r--r--src/tests/addressmap_unittest.cc2
-rw-r--r--src/tests/debugallocation_test.cc223
-rwxr-xr-xsrc/tests/debugallocation_test.sh78
-rw-r--r--src/tests/heap-checker_unittest.cc29
-rw-r--r--src/tests/heap-profiler_unittest.cc22
-rwxr-xr-xsrc/tests/heap-profiler_unittest.sh4
-rw-r--r--src/tests/low_level_alloc_unittest.cc12
-rw-r--r--src/tests/malloc_extension_test.cc7
-rw-r--r--src/tests/markidle_unittest.cc1
-rw-r--r--src/tests/memalign_unittest.cc26
-rw-r--r--src/tests/pagemap_unittest.cc2
-rw-r--r--src/tests/profile-handler_unittest.cc9
-rw-r--r--src/tests/profiledata_unittest.cc10
-rw-r--r--src/tests/profiler_unittest.cc2
-rwxr-xr-xsrc/tests/profiler_unittest.sh150
-rwxr-xr-xsrc/tests/sampler_test.cc1
-rw-r--r--src/tests/stacktrace_unittest.cc123
-rw-r--r--src/tests/tcmalloc_unittest.cc27
-rw-r--r--src/thread_cache.cc129
-rw-r--r--src/thread_cache.h27
-rw-r--r--src/windows/config.h21
-rw-r--r--src/windows/google/tcmalloc.h62
-rw-r--r--src/windows/patch_functions.cc163
-rw-r--r--src/windows/port.h18
-rw-r--r--src/windows/preamble_patcher.cc7
-rwxr-xr-xvsprojects/addr2line-pdb/addr2line-pdb.vcproj2
-rwxr-xr-xvsprojects/addressmap_unittest/addressmap_unittest.vcproj2
-rwxr-xr-xvsprojects/frag_unittest/frag_unittest.vcproj2
-rwxr-xr-xvsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj24
-rwxr-xr-xvsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj2
-rwxr-xr-xvsprojects/malloc_extension_test/malloc_extension_test.vcproj2
-rwxr-xr-xvsprojects/markidle_unittest/markidle_unittest.vcproj2
-rwxr-xr-xvsprojects/nm-pdb/nm-pdb.vcproj2
-rwxr-xr-xvsprojects/packed-cache_test/packed-cache_test.vcproj89
-rwxr-xr-xvsprojects/pagemap_unittest/pagemap_unittest.vcproj2
-rwxr-xr-xvsprojects/realloc_unittest/realloc_unittest.vcproj2
-rwxr-xr-xvsprojects/sampler_test/sampler_test.vcproj2
-rwxr-xr-xvsprojects/stack_trace_table_test/stack_trace_table_test.vcproj2
-rwxr-xr-xvsprojects/tcmalloc_minimal_large/tcmalloc_minimal_large_unittest.vcproj2
-rwxr-xr-xvsprojects/tcmalloc_minimal_unittest/tcmalloc_minimal_unittest.vcproj2
-rwxr-xr-xvsprojects/thread_dealloc_unittest/thread_dealloc_unittest.vcproj2
-rwxr-xr-xvsprojects/tmu-static/tmu-static.vcproj24
101 files changed, 5519 insertions, 1343 deletions
diff --git a/ChangeLog b/ChangeLog
index 8c5267a..5d8c004 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,29 @@
+Thu Sep 10 13:51:15 2009 Google Inc. <opensource@google.com>
+
+ * google-perftools: version 1.4 release
+ * Add debugallocation library, to catch memory leaks, stomping, etc
+ * Add --raw mode to allow for delayed processing of pprof files
+ * Use less memory when reading CPU profiles
+ * New environment variables to control kernel-allocs (sbrk, memfs, etc)
+ * Add MarkThreadBusy(): performance improvement
+ * Remove static thread-cache-size code; all is dynamic now
+ * Add new HiddenPointer class to heap checker
+ * BUGFIX: pvalloc(0) allocates now (found by new debugalloc library)
+ * BUGFIX: valloc test (not implementation) no longer overruns memory
+ * BUGFIX: GetHeapProfile no longer deadlocks
+ * BUGFIX: Support unmapping memory regions before main
+ * BUGFIX: Fix some malloc-stats formatting
+ * BUGFIX: Don't crash as often when freeing libc-allocated memory
+ * BUGFIX: Deal better with incorrect PPROF_PATH when symbolizing
+ * BUGFIX: weaken new/delete/etc in addition to malloc/free/etc
+ * BUGFIX: Fix return value of GetAllocatedSize
+ * PORTING: Fix mmap-#define problem on some 64-bit systems
+ * PORTING: Call ranlib again (some OS X versions need it)
+ * PORTING: Fix a leak when building with LLVM
+ * PORTING: Remove some unneeded bash-ishs from testing scripts
+ * WINDOWS: Support library unloading as well as loading
+ * WINDOWS/BUGFIX: Set page to 'xrw' instead of 'rw' when patching
+
Tue Jun 9 18:19:06 2009 Google Inc. <opensource@google.com>
* google-perftools: version 1.3 release
diff --git a/Makefile.am b/Makefile.am
index 13a8ca7..1a4bac2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -60,8 +60,19 @@ endif MINGW
# If we have objcopy, make malloc/free/etc weak symbols. That way folks
# can override our malloc if they want to (they can still use tc_malloc).
+# Note: the weird-looking symbols are the c++ memory functions:
+# (in order) new, new(nothrow), new[], new[](nothrow), delete, delete[]
+# In theory this will break if mangling changes, but that seems pretty
+# unlikely at this point. Just in case, I throw in versions with an
+# extra underscore as well, which may help on OS X.
if HAVE_OBJCOPY_WEAKEN
-WEAKEN = $(OBJCOPY) -W malloc -W free -W realloc -W calloc -W cfree -W memalign -W posix_memalign -W valloc -W pvalloc -W malloc_stats -W mallopt -W mallinfo
+WEAKEN = $(OBJCOPY) -W malloc -W free -W realloc -W calloc -W cfree \
+ -W memalign -W posix_memalign -W valloc -W pvalloc \
+ -W malloc_stats -W mallopt -W mallinfo \
+ -W _Znwm -W _ZnwmRKSt9nothrow_t -W _Znam -W _ZnamRKSt9nothrow_t \
+ -W _ZdlPv -W _ZdaPv \
+ -W __Znwm -W __ZnwmRKSt9nothrow_t -W __Znam -W __ZnamRKSt9nothrow_t \
+ -W __ZdlPv -W __ZdaPv
else
WEAKEN = :
endif !HAVE_OBJCOPY_WEAKEN
@@ -169,7 +180,9 @@ libwindows_la_SOURCES = $(WINDOWS_INCLUDES) \
src/windows/preamble_patcher_with_stub.cc
SPINLOCK_INCLUDES = src/base/spinlock.h \
- src/base/atomicops.h \
+ src/base/spinlock_win32-inl.h \
+ src/base/spinlock_linux-inl.h \
+ src/base/spinlock_posix-inl.h \
src/base/atomicops-internals-macosx.h \
src/base/atomicops-internals-linuxppc.h \
src/base/atomicops-internals-x86-msvc.h \
@@ -331,6 +344,7 @@ S_TCMALLOC_MINIMAL_INCLUDES = src/common.h \
src/page_heap_allocator.h \
src/span.h \
src/static_vars.h \
+ src/symbolize.h \
src/thread_cache.h \
src/stack_trace_table.h \
src/base/thread_annotations.h \
@@ -361,6 +375,7 @@ libtcmalloc_minimal_internal_la_SOURCES = src/common.cc \
src/span.cc \
src/stack_trace_table.cc \
src/static_vars.cc \
+ src/symbolize.cc \
src/thread_cache.cc \
src/malloc_hook.cc \
src/malloc_extension.cc \
@@ -368,6 +383,7 @@ libtcmalloc_minimal_internal_la_SOURCES = src/common.cc \
$(TCMALLOC_MINIMAL_INCLUDES)
# We #define NO_TCMALLOC_SAMPLES, since sampling is turned off for _minimal.
libtcmalloc_minimal_internal_la_CXXFLAGS = -DNO_TCMALLOC_SAMPLES \
+ -DNO_HEAP_CHECK \
$(PTHREAD_CFLAGS) -DNDEBUG \
$(AM_CXXFLAGS) $(NO_EXCEPTIONS)
libtcmalloc_minimal_internal_la_LDFLAGS = $(PTHREAD_CFLAGS)
@@ -472,9 +488,10 @@ endif !MINGW
TESTS += packed_cache_test
WINDOWS_PROJECTS += vsprojects/packed-cache_test/packed-cache_test.vcproj
-packed_cache_test_SOURCES = src/tests/packed-cache_test.cc \
- src/packed-cache-inl.h \
- src/base/logging.h
+packed_cache_test_SOURCES = src/tests/packed-cache_test.cc
+packed_cache_test_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
+packed_cache_test_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS)
+packed_cache_test_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS)
TESTS += frag_unittest
WINDOWS_PROJECTS += vsprojects/frag_unittest/frag_unittest.vcproj
@@ -611,6 +628,69 @@ dist_doc_DATA += doc/overview.dot \
doc/spanmap.dot \
doc/threadheap.dot
+
+### ------- tcmalloc_minimal_debug (thread-caching malloc with debugallocation)
+
+# Like tcmalloc.cc, debugallocation.cc needs exceptions to fulfill its
+# API. Luckily, we can reuse everything else from tcmalloc_minimal.
+
+if WITH_DEBUGALLOC
+
+lib_LTLIBRARIES += libtcmalloc_minimal_debug.la
+libtcmalloc_minimal_debug_la_SOURCES = src/debugallocation.cc \
+ $(TCMALLOC_MINIMAL_INCLUDES)
+libtcmalloc_minimal_debug_la_CXXFLAGS = $(libtcmalloc_minimal_la_CXXFLAGS) \
+ -DTCMALLOC_FOR_DEBUGALLOCATION
+libtcmalloc_minimal_debug_la_LDFLAGS = $(libtcmalloc_minimal_la_LDFLAGS)
+libtcmalloc_minimal_debug_la_LIBADD = $(libtcmalloc_minimal_la_LIBADD)
+
+LIBS_TO_WEAKEN += libtcmalloc_minimal_debug.la
+
+### Unittests
+
+TESTS += tcmalloc_minimal_debug_unittest
+tcmalloc_minimal_debug_unittest_SOURCES = $(tcmalloc_minimal_unittest_SOURCES)
+tcmalloc_minimal_debug_unittest_CXXFLAGS = $(tcmalloc_minimal_unittest_CXXFLAGS) \
+ -DDEBUGALLOCATION
+tcmalloc_minimal_debug_unittest_LDFLAGS = $(tcmalloc_minimal_unittest_LDFLAGS)
+tcmalloc_minimal_debug_unittest_LDADD = libtcmalloc_minimal_debug.la $(PTHREAD_LIBS)
+
+TESTS += malloc_extension_debug_test
+malloc_extension_debug_test_SOURCES = $(malloc_extension_test_SOURCES)
+malloc_extension_debug_test_CXXFLAGS = $(malloc_extension_test_CXXFLAGS)
+malloc_extension_debug_test_LDFLAGS = $(malloc_extension_test_LDFLAGS)
+malloc_extension_debug_test_LDADD = libtcmalloc_minimal_debug.la $(PTHREAD_LIBS)
+
+TESTS += memalign_debug_unittest
+memalign_debug_unittest_SOURCES = $(memalign_unittest_SOURCES)
+memalign_debug_unittest_CXXFLAGS = $(memalign_unittest_CXXFLAGS)
+memalign_debug_unittest_LDFLAGS = $(memalign_unittest_LDFLAGS)
+memalign_debug_unittest_LDADD = libtcmalloc_minimal_debug.la $(PTHREAD_LIBS)
+
+TESTS += realloc_debug_unittest
+realloc_debug_unittest_SOURCES = $(realloc_unittest_SOURCES)
+realloc_debug_unittest_CXXFLAGS = $(realloc_unittest_CXXFLAGS)
+realloc_debug_unittest_LDFLAGS = $(realloc_unittest_LDFLAGS)
+realloc_debug_unittest_LDADD = libtcmalloc_minimal_debug.la $(PTHREAD_LIBS)
+
+TESTS += debugallocation_test.sh$(EXEEXT)
+debugallocation_test_sh_SOURCES = src/tests/debugallocation_test.sh
+noinst_SCRIPTS += $(debugallocation_test_sh_SOURCES)
+debugallocation_test.sh$(EXEEXT): $(top_srcdir)/$(debugallocation_test_sh_SOURCES) \
+ debugallocation_test
+ rm -f $@
+ cp -p $(top_srcdir)/$(debugallocation_test_sh_SOURCES) $@
+
+# This is the sub-program used by debugallocation_test.sh
+noinst_PROGRAMS += debugallocation_test
+debugallocation_test_SOURCES = src/tests/debugallocation_test.cc
+debugallocation_test_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
+debugallocation_test_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS)
+debugallocation_test_LDADD = libtcmalloc_minimal_debug.la $(PTHREAD_LIBS)
+
+endif WITH_DEBUGALLOC
+
+
### ------- tcmalloc (thread-caching malloc + heap profiler + heap checker)
if WITH_HEAP_PROFILER_OR_CHECKER
@@ -664,11 +744,16 @@ if WITH_HEAP_CHECKER
# (Note this is added to libtcmalloc.la, not libtcmalloc_internal.la,
# but that's ok; the internal/external distinction is only useful for
# cygwin, and cygwin doesn't use HEAP_CHECKER anyway.)
-libtcmalloc_la_SOURCES += src/base/thread_lister.c \
- src/base/linuxthreads.cc \
- src/heap-checker.cc \
- src/heap-checker-bcad.cc
-endif WITH_HEAP_CHECKER
+HEAP_CHECKER_SOURCES = src/base/thread_lister.c \
+ src/base/linuxthreads.cc \
+ src/heap-checker.cc \
+ src/heap-checker-bcad.cc
+libtcmalloc_la_SOURCES += $(HEAP_CHECKER_SOURCES)
+else !WITH_HEAP_CHECKER
+HEAP_CHECKER_SOURCES =
+libtcmalloc_internal_la_CXXFLAGS += -DNO_HEAP_CHECK
+libtcmalloc_la_CXXFLAGS += -DNO_HEAP_CHECK
+endif !WITH_HEAP_CHECKER
LIBTCMALLOC = libtcmalloc.la
@@ -739,7 +824,7 @@ sampling_test.sh$(EXEEXT): $(top_srcdir)/$(sampling_test_sh_SOURCES) \
rm -f $@
cp -p $(top_srcdir)/$(sampling_test_sh_SOURCES) $@
-# This is the sub-program using by sampling_test.sh
+# This is the sub-program used by sampling_test.sh
# The -g is so pprof can get symbol information.
noinst_PROGRAMS += sampling_test
SAMPLING_TEST_INCLUDES = src/config_for_unittests.h \
@@ -820,6 +905,93 @@ dist_doc_DATA += doc/heap_checker.html
endif WITH_HEAP_CHECKER
+### ------- tcmalloc with debugallocation
+
+if WITH_DEBUGALLOC
+if WITH_HEAP_PROFILER_OR_CHECKER
+
+lib_LTLIBRARIES += libtcmalloc_debug.la
+libtcmalloc_debug_la_SOURCES = src/debugallocation.cc $(HEAP_CHECKER_SOURCES) \
+ $(TCMALLOC_INCLUDES)
+libtcmalloc_debug_la_CXXFLAGS = $(libtcmalloc_la_CXXFLAGS) \
+ -DTCMALLOC_FOR_DEBUGALLOCATION
+libtcmalloc_debug_la_LDFLAGS = $(libtcmalloc_la_LDFLAGS)
+libtcmalloc_debug_la_LIBADD = $(libtcmalloc_la_LIBADD)
+
+LIBS_TO_WEAKEN += libtcmalloc_debug.la
+
+### Unittests
+
+TESTS += tcmalloc_debug_unittest
+tcmalloc_debug_unittest_SOURCES = $(tcmalloc_unittest_SOURCES)
+tcmalloc_debug_unittest_CXXFLAGS = $(tcmalloc_unittest_CXXFLAGS) \
+ -DDEBUGALLOCATION
+tcmalloc_debug_unittest_LDFLAGS = $(tcmalloc_unittest_LDFLAGS)
+tcmalloc_debug_unittest_LDADD = libtcmalloc_debug.la $(PTHREAD_LIBS)
+
+TESTS += sampler_debug_test
+sampler_debug_test_SOURCES = $(sampler_test_SOURCES)
+sampler_debug_test_CXXFLAGS = $(samples_test_CXXFLAGS)
+sampler_debug_test_LDFLAGS = $(sampler_test_LDFLAGS)
+sampler_debug_test_LDADD = libtcmalloc_debug.la $(PTHREAD_LIBS) -lm
+
+TESTS += sampling_debug_test.sh$(EXEEXT)
+sampling_debug_test_sh_SOURCES = src/tests/sampling_test.sh
+sampling_debug_test.sh$(EXEEXT): $(top_srcdir)/$(sampling_test_sh_SOURCES) \
+ sampling_debug_test
+ rm -f $@
+ cp -p $(top_srcdir)/$(sampling_test_sh_SOURCES) $@
+
+# This is the sub-program using by sampling_debug_test.sh
+# The -g is so pprof can get symbol information.
+noinst_PROGRAMS += sampling_debug_test
+sampling_debug_test_SOURCES = $(sampling_test_SOURCES)
+sampling_debug_test_CXXFLAGS = $(sampling_test_CXXFLAGS)
+sampling_debug_test_LDFLAGS = $(sampling_test_LDFLAGS)
+sampling_debug_test_LDADD = libtcmalloc_debug.la $(PTHREAD_LIBS)
+
+endif WITH_HEAP_PROFILER_OR_CHECKER
+
+if WITH_HEAP_PROFILER
+
+TESTS += heap-profiler_debug_unittest.sh$(EXEEXT)
+heap_profiler_debug_unittest_sh_SOURCES = src/tests/heap-profiler_unittest.sh
+heap-profiler_debug_unittest.sh$(EXEEXT): $(top_srcdir)/$(heap_profiler_unittest_sh_SOURCES) \
+ heap-profiler_debug_unittest
+ rm -f $@
+ cp -p $(top_srcdir)/$(heap_profiler_unittest_sh_SOURCES) $@
+
+# These are sub-programs used by heap-profiler_debug_unittest.sh
+noinst_PROGRAMS += heap-profiler_debug_unittest
+heap_profiler_debug_unittest_SOURCES = $(heap_profiler_unittest_SOURCES)
+heap_profiler_debug_unittest_CXXFLAGS = $(heap_profiler_unittest_CXXFLAGS)
+heap_profiler_debug_unittest_LDFLAGS = $(heap_profiler_unittest_LDFLAGS)
+heap_profiler_debug_unittest_LDADD = libtcmalloc_debug.la $(PTHREAD_LIBS)
+
+endif WITH_HEAP_PROFILER
+
+if WITH_HEAP_CHECKER
+
+TESTS += heap-checker_debug_unittest.sh$(EXEEXT)
+heap_checker_debug_unittest_sh_SOURCES = src/tests/heap-checker_unittest.sh
+heap-checker_debug_unittest.sh$(EXEEXT): $(top_srcdir)/$(heap_checker_unittest_sh_SOURCES) \
+ heap-checker_debug_unittest
+ rm -f $@
+ cp -p $(top_srcdir)/$(heap_checker_unittest_sh_SOURCES) $@
+
+# These are sub-programs used by heap-checker_debug_unittest.sh
+noinst_PROGRAMS += heap-checker_debug_unittest
+heap_checker_debug_unittest_SOURCES = $(heap_checker_unittest_SOURCES)
+heap_checker_debug_unittest_CXXFLAGS = $(heap_checker_unittest_CXXFLAGS)
+heap_checker_debug_unittest_LDFLAGS = $(heap_checker_unittest_LDFLAGS)
+# tcmalloc has to be specified last!
+heap_checker_debug_unittest_LDADD = $(PTHREAD_LIBS) liblogging.la \
+ libtcmalloc_debug.la
+
+endif WITH_HEAP_CHECKER
+endif WITH_DEBUGALLOC
+
+
### ------- CPU profiler
if WITH_CPU_PROFILER
@@ -924,6 +1096,7 @@ dist_doc_DATA += doc/cpuprofile.html \
endif WITH_CPU_PROFILER
+
### ------- CPU profiler and heap checker, in one!
# Ideally, folks who wanted to use both tcmalloc and libprofiler,
@@ -962,9 +1135,7 @@ endif WITH_HEAP_PROFILER_OR_CHECKER
# Do the weakening on some exported libtcmalloc symbols.
install-exec-local: all-local
all-local: $(LIBS_TO_WEAKEN)
- [ ! -f .libs/libtcmalloc_minimal.a ] || $(WEAKEN) .libs/libtcmalloc_minimal.a
- [ ! -f .libs/libtcmalloc.a ] || $(WEAKEN) .libs/libtcmalloc.a
- [ ! -f .libs/libtcmalloc_and_profiler.a ] || $(WEAKEN) .libs/libtcmalloc_and_profiler.a
+ for la in $(LIBS_TO_WEAKEN); do lib=".libs/`basename $$la .la`.a"; [ ! -f "$$lib" ] || $(WEAKEN) "$$lib"; done
# This should always include $(TESTS), but may also include other
diff --git a/Makefile.in b/Makefile.in
index 8ba85fb..232d2ec 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -54,7 +54,8 @@ host_triplet = @host@
@ENABLE_FRAME_POINTERS_FALSE@@X86_64_TRUE@am__append_4 = -DNO_FRAME_POINTER
@MINGW_TRUE@am__append_5 = -Wl,-u__tcmalloc
noinst_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
- $(am__EXEEXT_4) $(am__EXEEXT_14)
+ $(am__EXEEXT_4) $(am__EXEEXT_5) $(am__EXEEXT_6) \
+ $(am__EXEEXT_7) $(am__EXEEXT_8) $(am__EXEEXT_22)
bin_PROGRAMS =
@MINGW_TRUE@am__append_6 = libwindows.la libspinlock.la
@@ -95,7 +96,25 @@ bin_PROGRAMS =
@MINGW_FALSE@am__append_18 = memalign_unittest
EXTRA_PROGRAMS = ptmalloc_unittest1$(EXEEXT) \
ptmalloc_unittest2$(EXEEXT)
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_19 = $(SG_TCMALLOC_INCLUDES)
+
+### ------- tcmalloc_minimal_debug (thread-caching malloc with debugallocation)
+
+# Like tcmalloc.cc, debugallocation.cc needs exceptions to fulfill its
+# API. Luckily, we can reuse everything else from tcmalloc_minimal.
+@WITH_DEBUGALLOC_TRUE@am__append_19 = libtcmalloc_minimal_debug.la
+@WITH_DEBUGALLOC_TRUE@am__append_20 = libtcmalloc_minimal_debug.la
+
+### Unittests
+@WITH_DEBUGALLOC_TRUE@am__append_21 = tcmalloc_minimal_debug_unittest \
+@WITH_DEBUGALLOC_TRUE@ malloc_extension_debug_test \
+@WITH_DEBUGALLOC_TRUE@ memalign_debug_unittest \
+@WITH_DEBUGALLOC_TRUE@ realloc_debug_unittest \
+@WITH_DEBUGALLOC_TRUE@ debugallocation_test.sh$(EXEEXT)
+@WITH_DEBUGALLOC_TRUE@am__append_22 = $(debugallocation_test_sh_SOURCES)
+
+# This is the sub-program used by debugallocation_test.sh
+@WITH_DEBUGALLOC_TRUE@am__append_23 = debugallocation_test
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_24 = $(SG_TCMALLOC_INCLUDES)
### Making the library
@@ -103,19 +122,12 @@ EXTRA_PROGRAMS = ptmalloc_unittest1$(EXEEXT) \
# for all files in this library -- except tcmalloc.cc which needs them
# to fulfill its API. Automake doesn't allow per-file CXXFLAGS, so we need
# to separate into two libraries.
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_20 = libtcmalloc_internal.la
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_21 = libtcmalloc.la
-
-# heap-checker-bcad is last, in hopes its global ctor will run first.
-# (Note this is added to libtcmalloc.la, not libtcmalloc_internal.la,
-# but that's ok; the internal/external distinction is only useful for
-# cygwin, and cygwin doesn't use HEAP_CHECKER anyway.)
-@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_22 = src/base/thread_lister.c \
-@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/base/linuxthreads.cc \
-@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/heap-checker.cc \
-@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/heap-checker-bcad.cc
-
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_23 = libtcmalloc.la
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_25 = libtcmalloc_internal.la
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_26 = libtcmalloc.la
+@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_27 = $(HEAP_CHECKER_SOURCES)
+@WITH_HEAP_CHECKER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_28 = -DNO_HEAP_CHECK
+@WITH_HEAP_CHECKER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_29 = -DNO_HEAP_CHECK
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_30 = libtcmalloc.la
### Unittests
@@ -123,60 +135,81 @@ EXTRA_PROGRAMS = ptmalloc_unittest1$(EXEEXT) \
# tcmalloc_minimal. (One would never do this on purpose, but perhaps
# by accident...) When we can compile libprofiler, we also link it in
# to make sure that works too.
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_24 = tcmalloc_unittest \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_31 = tcmalloc_unittest \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ tcmalloc_both_unittest \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ tcmalloc_large_unittest \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ raw_printer_test \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampler_test \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampling_test.sh$(EXEEXT)
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_25 = vsprojects/sampler_test/sampler_test.vcproj
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_32 = vsprojects/sampler_test/sampler_test.vcproj
# These unittests often need to run binaries. They're in the current dir
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_26 = BINDIR=. \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_33 = BINDIR=. \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ TMPDIR=/tmp/perftools
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_27 = $(sampling_test_sh_SOURCES)
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_34 = $(sampling_test_sh_SOURCES)
-# This is the sub-program using by sampling_test.sh
+# This is the sub-program used by sampling_test.sh
# The -g is so pprof can get symbol information.
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_28 = sampling_test
-@WITH_HEAP_PROFILER_TRUE@am__append_29 = heap-profiler_unittest.sh$(EXEEXT)
-@WITH_HEAP_PROFILER_TRUE@am__append_30 = $(heap_profiler_unittest_sh_SOURCES)
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_35 = sampling_test
+@WITH_HEAP_PROFILER_TRUE@am__append_36 = heap-profiler_unittest.sh$(EXEEXT)
+@WITH_HEAP_PROFILER_TRUE@am__append_37 = $(heap_profiler_unittest_sh_SOURCES)
# These are sub-programs used by heap-profiler_unittest.sh
-@WITH_HEAP_PROFILER_TRUE@am__append_31 = heap-profiler_unittest
-@WITH_HEAP_CHECKER_TRUE@am__append_32 = \
+@WITH_HEAP_PROFILER_TRUE@am__append_38 = heap-profiler_unittest
+@WITH_HEAP_CHECKER_TRUE@am__append_39 = \
@WITH_HEAP_CHECKER_TRUE@ heap-checker_unittest.sh$(EXEEXT) \
@WITH_HEAP_CHECKER_TRUE@ heap-checker-death_unittest.sh$(EXEEXT)
-@WITH_HEAP_CHECKER_TRUE@am__append_33 = \
+@WITH_HEAP_CHECKER_TRUE@am__append_40 = \
@WITH_HEAP_CHECKER_TRUE@ $(heap_checker_unittest_sh_SOURCES) \
@WITH_HEAP_CHECKER_TRUE@ $(top_srcdir)/$(heap_checker_death_unittest_sh_SOURCES)
# These are sub-programs used by heap-checker_unittest.sh
-@WITH_HEAP_CHECKER_TRUE@am__append_34 = heap-checker_unittest
+@WITH_HEAP_CHECKER_TRUE@am__append_41 = heap-checker_unittest
### Documentation (above and beyond tcmalloc_minimal documentation)
-@WITH_HEAP_PROFILER_TRUE@am__append_35 = doc/heapprofile.html doc/heap-example1.png
-@WITH_HEAP_CHECKER_TRUE@am__append_36 = doc/heap_checker.html
-@WITH_CPU_PROFILER_TRUE@am__append_37 = $(SG_CPU_PROFILER_INCLUDES)
+@WITH_HEAP_PROFILER_TRUE@am__append_42 = doc/heapprofile.html doc/heap-example1.png
+@WITH_HEAP_CHECKER_TRUE@am__append_43 = doc/heap_checker.html
+
+### ------- tcmalloc with debugallocation
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_44 = libtcmalloc_debug.la
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_45 = libtcmalloc_debug.la
+
+### Unittests
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_46 = tcmalloc_debug_unittest \
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampler_debug_test \
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampling_debug_test.sh$(EXEEXT)
+
+# This is the sub-program using by sampling_debug_test.sh
+# The -g is so pprof can get symbol information.
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_47 = sampling_debug_test
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@am__append_48 = heap-profiler_debug_unittest.sh$(EXEEXT)
+
+# These are sub-programs used by heap-profiler_debug_unittest.sh
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@am__append_49 = heap-profiler_debug_unittest
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@am__append_50 = heap-checker_debug_unittest.sh$(EXEEXT)
+
+# These are sub-programs used by heap-checker_debug_unittest.sh
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@am__append_51 = heap-checker_debug_unittest
+@WITH_CPU_PROFILER_TRUE@am__append_52 = $(SG_CPU_PROFILER_INCLUDES)
### Making the library
-@WITH_CPU_PROFILER_TRUE@am__append_38 = libprofiler.la
+@WITH_CPU_PROFILER_TRUE@am__append_53 = libprofiler.la
### Unittests
-@WITH_CPU_PROFILER_TRUE@am__append_39 = getpc_test \
+@WITH_CPU_PROFILER_TRUE@am__append_54 = getpc_test \
@WITH_CPU_PROFILER_TRUE@ profiledata_unittest \
@WITH_CPU_PROFILER_TRUE@ profile_handler_unittest \
@WITH_CPU_PROFILER_TRUE@ profiler_unittest.sh$(EXEEXT)
-@WITH_CPU_PROFILER_TRUE@am__append_40 = $(profiler_unittest_sh_SOURCES)
+@WITH_CPU_PROFILER_TRUE@am__append_55 = $(profiler_unittest_sh_SOURCES)
# These are sub-programs used by profiler_unittest.sh
-@WITH_CPU_PROFILER_TRUE@am__append_41 = profiler1_unittest profiler2_unittest profiler3_unittest \
+@WITH_CPU_PROFILER_TRUE@am__append_56 = profiler1_unittest profiler2_unittest profiler3_unittest \
@WITH_CPU_PROFILER_TRUE@ profiler4_unittest
@WITH_CPU_PROFILER_FALSE@profiler2_unittest_DEPENDENCIES =
### Documentation
-@WITH_CPU_PROFILER_TRUE@am__append_42 = doc/cpuprofile.html \
+@WITH_CPU_PROFILER_TRUE@am__append_57 = doc/cpuprofile.html \
@WITH_CPU_PROFILER_TRUE@ doc/cpuprofile-fileformat.html \
@WITH_CPU_PROFILER_TRUE@ doc/pprof-test-big.gif \
@WITH_CPU_PROFILER_TRUE@ doc/pprof-test.gif \
@@ -191,9 +224,9 @@ EXTRA_PROGRAMS = ptmalloc_unittest1$(EXEEXT) \
# works fine for .so files, it does not for .a files. The easiest way
# around this -- and I've tried a bunch of the hard ways -- is to just
# to create another set of libraries that has both functionality in it.
-@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_43 = libtcmalloc_and_profiler.la
-@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_44 = tcmalloc_and_profiler_unittest
-@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_45 = libtcmalloc_and_profiler.la
+@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_58 = libtcmalloc_and_profiler.la
+@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_59 = tcmalloc_and_profiler_unittest
+@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__append_60 = libtcmalloc_and_profiler.la
DIST_COMMON = README $(am__configure_deps) $(am__dist_doc_DATA_DIST) \
$(am__googleinclude_HEADERS_DIST) $(dist_man_MANS) \
$(noinst_HEADERS) $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
@@ -209,6 +242,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ac_have_attribute.m4 \
$(top_srcdir)/m4/compiler_characteristics.m4 \
$(top_srcdir)/m4/install_prefix.m4 \
$(top_srcdir)/m4/namespaces.m4 \
+ $(top_srcdir)/m4/pc_from_ucontext.m4 \
$(top_srcdir)/m4/program_invocation_name.m4 \
$(top_srcdir)/m4/stl_namespace.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
@@ -247,8 +281,9 @@ am__libprofiler_la_SOURCES_DIST = src/profiler.cc \
src/base/atomicops-internals-linuxppc.h \
src/base/atomicops-internals-x86-msvc.h \
src/base/atomicops-internals-x86.h \
- src/base/dynamic_annotations.h src/google/profiler.h \
- src/google/stacktrace.h
+ src/base/spinlock_win32-inl.h src/base/spinlock_linux-inl.h \
+ src/base/spinlock_posix-inl.h src/base/dynamic_annotations.h \
+ src/google/profiler.h src/google/stacktrace.h
@WITH_CPU_PROFILER_TRUE@am__objects_2 = $(am__objects_1) \
@WITH_CPU_PROFILER_TRUE@ $(am__objects_1)
@WITH_CPU_PROFILER_TRUE@am__objects_3 = $(am__objects_2) \
@@ -265,7 +300,9 @@ am__libspinlock_la_SOURCES_DIST = src/base/spinlock.cc \
src/base/atomicops.h src/base/atomicops-internals-macosx.h \
src/base/atomicops-internals-linuxppc.h \
src/base/atomicops-internals-x86-msvc.h \
- src/base/atomicops-internals-x86.h
+ src/base/atomicops-internals-x86.h \
+ src/base/spinlock_win32-inl.h src/base/spinlock_linux-inl.h \
+ src/base/spinlock_posix-inl.h
@MINGW_FALSE@am_libspinlock_la_OBJECTS = spinlock.lo \
@MINGW_FALSE@ atomicops-internals-x86.lo $(am__objects_1)
@MINGW_TRUE@am_libspinlock_la_OBJECTS = spinlock.lo $(am__objects_1)
@@ -306,13 +343,16 @@ am__libtcmalloc_la_SOURCES_DIST = src/tcmalloc.cc src/common.h \
src/base/atomicops.h src/base/atomicops-internals-macosx.h \
src/base/atomicops-internals-linuxppc.h \
src/base/atomicops-internals-x86-msvc.h \
- src/base/atomicops-internals-x86.h src/tcmalloc_guard.h \
+ src/base/atomicops-internals-x86.h \
+ src/base/spinlock_win32-inl.h src/base/spinlock_linux-inl.h \
+ src/base/spinlock_posix-inl.h src/tcmalloc_guard.h \
src/base/commandlineflags.h src/base/basictypes.h \
src/pagemap.h src/sampler.h src/central_freelist.h \
src/linked_list.h src/page_heap.h src/page_heap_allocator.h \
- src/span.h src/static_vars.h src/thread_cache.h \
- src/stack_trace_table.h src/base/thread_annotations.h \
- src/malloc_hook-inl.h src/maybe_threads.h src/base/logging.h \
+ src/span.h src/static_vars.h src/symbolize.h \
+ src/thread_cache.h src/stack_trace_table.h \
+ src/base/thread_annotations.h src/malloc_hook-inl.h \
+ src/maybe_threads.h src/base/logging.h \
src/base/dynamic_annotations.h src/addressmap-inl.h \
src/raw_printer.h src/base/elfcore.h src/base/googleinit.h \
src/base/linux_syscall_support.h src/base/linuxthreads.h \
@@ -335,10 +375,11 @@ am__objects_6 = $(am__objects_1)
@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libtcmalloc_la-linuxthreads.lo \
@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libtcmalloc_la-heap-checker.lo \
@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libtcmalloc_la-heap-checker-bcad.lo
+@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_11 = $(am__objects_10)
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_libtcmalloc_la_OBJECTS = \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_5) \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_9) \
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_10)
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_11)
libtcmalloc_la_OBJECTS = $(am_libtcmalloc_la_OBJECTS)
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_libtcmalloc_la_rpath = -rpath \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(libdir)
@@ -352,13 +393,16 @@ am__libtcmalloc_and_profiler_la_SOURCES_DIST = src/tcmalloc.cc \
src/base/atomicops.h src/base/atomicops-internals-macosx.h \
src/base/atomicops-internals-linuxppc.h \
src/base/atomicops-internals-x86-msvc.h \
- src/base/atomicops-internals-x86.h src/tcmalloc_guard.h \
+ src/base/atomicops-internals-x86.h \
+ src/base/spinlock_win32-inl.h src/base/spinlock_linux-inl.h \
+ src/base/spinlock_posix-inl.h src/tcmalloc_guard.h \
src/base/commandlineflags.h src/base/basictypes.h \
src/pagemap.h src/sampler.h src/central_freelist.h \
src/linked_list.h src/page_heap.h src/page_heap_allocator.h \
- src/span.h src/static_vars.h src/thread_cache.h \
- src/stack_trace_table.h src/base/thread_annotations.h \
- src/malloc_hook-inl.h src/maybe_threads.h src/base/logging.h \
+ src/span.h src/static_vars.h src/symbolize.h \
+ src/thread_cache.h src/stack_trace_table.h \
+ src/base/thread_annotations.h src/malloc_hook-inl.h \
+ src/maybe_threads.h src/base/logging.h \
src/base/dynamic_annotations.h src/addressmap-inl.h \
src/raw_printer.h src/base/elfcore.h src/base/googleinit.h \
src/base/linux_syscall_support.h src/base/linuxthreads.h \
@@ -373,64 +417,105 @@ am__libtcmalloc_and_profiler_la_SOURCES_DIST = src/tcmalloc.cc \
src/profile-handler.cc src/profiledata.cc src/profiledata.h \
src/profile-handler.h src/getpc.h src/base/simple_mutex.h \
src/google/profiler.h
-@MINGW_FALSE@am__objects_11 = libtcmalloc_and_profiler_la-tcmalloc.lo
-@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_12 = thread_lister.lo \
+@MINGW_FALSE@am__objects_12 = libtcmalloc_and_profiler_la-tcmalloc.lo
+@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_13 = thread_lister.lo \
@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libtcmalloc_and_profiler_la-linuxthreads.lo \
@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libtcmalloc_and_profiler_la-heap-checker.lo \
@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libtcmalloc_and_profiler_la-heap-checker-bcad.lo
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_13 = \
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_11) \
+@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_14 = $(am__objects_13)
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_15 = \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_12) \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_9) \
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_12)
-@WITH_CPU_PROFILER_TRUE@am__objects_14 = libtcmalloc_and_profiler_la-profiler.lo \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_14)
+@WITH_CPU_PROFILER_TRUE@am__objects_16 = libtcmalloc_and_profiler_la-profiler.lo \
@WITH_CPU_PROFILER_TRUE@ libtcmalloc_and_profiler_la-profile-handler.lo \
@WITH_CPU_PROFILER_TRUE@ libtcmalloc_and_profiler_la-profiledata.lo \
@WITH_CPU_PROFILER_TRUE@ $(am__objects_3)
-@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_libtcmalloc_and_profiler_la_OBJECTS = $(am__objects_13) \
-@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_14)
+@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_libtcmalloc_and_profiler_la_OBJECTS = $(am__objects_15) \
+@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_16)
libtcmalloc_and_profiler_la_OBJECTS = \
$(am_libtcmalloc_and_profiler_la_OBJECTS)
@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_libtcmalloc_and_profiler_la_rpath = -rpath \
@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(libdir)
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_internal_la_DEPENDENCIES = \
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_1) \
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libstacktrace.la
-am__libtcmalloc_internal_la_SOURCES_DIST = src/common.cc \
- src/internal_logging.cc src/system-alloc.cc \
- src/memfs_malloc.cc src/central_freelist.cc src/page_heap.cc \
- src/sampler.cc src/span.cc src/stack_trace_table.cc \
- src/static_vars.cc src/thread_cache.cc src/malloc_hook.cc \
- src/malloc_extension.cc src/maybe_threads.cc src/common.h \
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_debug_la_DEPENDENCIES = $(am__DEPENDENCIES_3)
+am__libtcmalloc_debug_la_SOURCES_DIST = src/debugallocation.cc \
+ src/base/thread_lister.c src/base/linuxthreads.cc \
+ src/heap-checker.cc src/heap-checker-bcad.cc src/common.h \
src/internal_logging.h src/system-alloc.h \
src/packed-cache-inl.h src/base/spinlock.h \
src/base/atomicops.h src/base/atomicops-internals-macosx.h \
src/base/atomicops-internals-linuxppc.h \
src/base/atomicops-internals-x86-msvc.h \
- src/base/atomicops-internals-x86.h src/tcmalloc_guard.h \
+ src/base/atomicops-internals-x86.h \
+ src/base/spinlock_win32-inl.h src/base/spinlock_linux-inl.h \
+ src/base/spinlock_posix-inl.h src/tcmalloc_guard.h \
src/base/commandlineflags.h src/base/basictypes.h \
src/pagemap.h src/sampler.h src/central_freelist.h \
src/linked_list.h src/page_heap.h src/page_heap_allocator.h \
- src/span.h src/static_vars.h src/thread_cache.h \
- src/stack_trace_table.h src/base/thread_annotations.h \
- src/malloc_hook-inl.h src/maybe_threads.h \
- src/google/malloc_hook.h src/google/malloc_hook_c.h \
- src/google/malloc_extension.h src/google/malloc_extension_c.h \
- src/google/stacktrace.h src/base/logging.h \
+ src/span.h src/static_vars.h src/symbolize.h \
+ src/thread_cache.h src/stack_trace_table.h \
+ src/base/thread_annotations.h src/malloc_hook-inl.h \
+ src/maybe_threads.h src/base/logging.h \
src/base/dynamic_annotations.h src/addressmap-inl.h \
src/raw_printer.h src/base/elfcore.h src/base/googleinit.h \
src/base/linux_syscall_support.h src/base/linuxthreads.h \
src/base/stl_allocator.h src/base/sysinfo.h \
src/base/thread_lister.h src/heap-profile-table.h \
- src/google/heap-profiler.h src/google/heap-checker.h \
- src/base/low_level_alloc.cc src/heap-profile-table.cc \
- src/heap-profiler.cc src/raw_printer.cc \
- src/memory_region_map.cc
-@MINGW_FALSE@am__objects_15 = libtcmalloc_internal_la-system-alloc.lo
-@MINGW_FALSE@am__objects_16 = \
+ src/google/malloc_hook.h src/google/malloc_hook_c.h \
+ src/google/malloc_extension.h src/google/malloc_extension_c.h \
+ src/google/stacktrace.h src/google/heap-profiler.h \
+ src/google/heap-checker.h
+@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_17 = thread_lister.lo \
+@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libtcmalloc_debug_la-linuxthreads.lo \
+@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libtcmalloc_debug_la-heap-checker.lo \
+@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libtcmalloc_debug_la-heap-checker-bcad.lo
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_libtcmalloc_debug_la_OBJECTS = libtcmalloc_debug_la-debugallocation.lo \
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_17) \
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_9)
+libtcmalloc_debug_la_OBJECTS = $(am_libtcmalloc_debug_la_OBJECTS)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_libtcmalloc_debug_la_rpath = -rpath \
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(libdir)
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_internal_la_DEPENDENCIES = \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_1) \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libstacktrace.la
+am__libtcmalloc_internal_la_SOURCES_DIST = src/common.cc \
+ src/internal_logging.cc src/system-alloc.cc \
+ src/memfs_malloc.cc src/central_freelist.cc src/page_heap.cc \
+ src/sampler.cc src/span.cc src/stack_trace_table.cc \
+ src/static_vars.cc src/symbolize.cc src/thread_cache.cc \
+ src/malloc_hook.cc src/malloc_extension.cc \
+ src/maybe_threads.cc src/common.h src/internal_logging.h \
+ src/system-alloc.h src/packed-cache-inl.h src/base/spinlock.h \
+ src/base/atomicops.h src/base/atomicops-internals-macosx.h \
+ src/base/atomicops-internals-linuxppc.h \
+ src/base/atomicops-internals-x86-msvc.h \
+ src/base/atomicops-internals-x86.h \
+ src/base/spinlock_win32-inl.h src/base/spinlock_linux-inl.h \
+ src/base/spinlock_posix-inl.h src/tcmalloc_guard.h \
+ src/base/commandlineflags.h src/base/basictypes.h \
+ src/pagemap.h src/sampler.h src/central_freelist.h \
+ src/linked_list.h src/page_heap.h src/page_heap_allocator.h \
+ src/span.h src/static_vars.h src/symbolize.h \
+ src/thread_cache.h src/stack_trace_table.h \
+ src/base/thread_annotations.h src/malloc_hook-inl.h \
+ src/maybe_threads.h src/google/malloc_hook.h \
+ src/google/malloc_hook_c.h src/google/malloc_extension.h \
+ src/google/malloc_extension_c.h src/google/stacktrace.h \
+ src/base/logging.h src/base/dynamic_annotations.h \
+ src/addressmap-inl.h src/raw_printer.h src/base/elfcore.h \
+ src/base/googleinit.h src/base/linux_syscall_support.h \
+ src/base/linuxthreads.h src/base/stl_allocator.h \
+ src/base/sysinfo.h src/base/thread_lister.h \
+ src/heap-profile-table.h src/google/heap-profiler.h \
+ src/google/heap-checker.h src/base/low_level_alloc.cc \
+ src/heap-profile-table.cc src/heap-profiler.cc \
+ src/raw_printer.cc src/memory_region_map.cc
+@MINGW_FALSE@am__objects_18 = libtcmalloc_internal_la-system-alloc.lo
+@MINGW_FALSE@am__objects_19 = \
@MINGW_FALSE@ libtcmalloc_internal_la-maybe_threads.lo
-am__objects_17 = $(am__objects_6) $(am__objects_1)
-am__objects_18 = libtcmalloc_internal_la-common.lo \
- libtcmalloc_internal_la-internal_logging.lo $(am__objects_15) \
+am__objects_20 = $(am__objects_6) $(am__objects_1)
+am__objects_21 = libtcmalloc_internal_la-common.lo \
+ libtcmalloc_internal_la-internal_logging.lo $(am__objects_18) \
libtcmalloc_internal_la-memfs_malloc.lo \
libtcmalloc_internal_la-central_freelist.lo \
libtcmalloc_internal_la-page_heap.lo \
@@ -438,12 +523,13 @@ am__objects_18 = libtcmalloc_internal_la-common.lo \
libtcmalloc_internal_la-span.lo \
libtcmalloc_internal_la-stack_trace_table.lo \
libtcmalloc_internal_la-static_vars.lo \
+ libtcmalloc_internal_la-symbolize.lo \
libtcmalloc_internal_la-thread_cache.lo \
libtcmalloc_internal_la-malloc_hook.lo \
- libtcmalloc_internal_la-malloc_extension.lo $(am__objects_16) \
- $(am__objects_17)
+ libtcmalloc_internal_la-malloc_extension.lo $(am__objects_19) \
+ $(am__objects_20)
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_libtcmalloc_internal_la_OBJECTS = \
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_18) \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_21) \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_9) \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libtcmalloc_internal_la-low_level_alloc.lo \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libtcmalloc_internal_la-heap-profile-table.lo \
@@ -461,51 +547,83 @@ am__libtcmalloc_minimal_la_SOURCES_DIST = src/tcmalloc.cc src/common.h \
src/base/atomicops.h src/base/atomicops-internals-macosx.h \
src/base/atomicops-internals-linuxppc.h \
src/base/atomicops-internals-x86-msvc.h \
- src/base/atomicops-internals-x86.h src/tcmalloc_guard.h \
+ src/base/atomicops-internals-x86.h \
+ src/base/spinlock_win32-inl.h src/base/spinlock_linux-inl.h \
+ src/base/spinlock_posix-inl.h src/tcmalloc_guard.h \
src/base/commandlineflags.h src/base/basictypes.h \
src/pagemap.h src/sampler.h src/central_freelist.h \
src/linked_list.h src/page_heap.h src/page_heap_allocator.h \
- src/span.h src/static_vars.h src/thread_cache.h \
- src/stack_trace_table.h src/base/thread_annotations.h \
- src/malloc_hook-inl.h src/maybe_threads.h \
- src/google/malloc_hook.h src/google/malloc_hook_c.h \
- src/google/malloc_extension.h src/google/malloc_extension_c.h \
- src/google/stacktrace.h
-@MINGW_FALSE@am__objects_19 = libtcmalloc_minimal_la-tcmalloc.lo
-am_libtcmalloc_minimal_la_OBJECTS = $(am__objects_19) \
- $(am__objects_17)
+ src/span.h src/static_vars.h src/symbolize.h \
+ src/thread_cache.h src/stack_trace_table.h \
+ src/base/thread_annotations.h src/malloc_hook-inl.h \
+ src/maybe_threads.h src/google/malloc_hook.h \
+ src/google/malloc_hook_c.h src/google/malloc_extension.h \
+ src/google/malloc_extension_c.h src/google/stacktrace.h
+@MINGW_FALSE@am__objects_22 = libtcmalloc_minimal_la-tcmalloc.lo
+am_libtcmalloc_minimal_la_OBJECTS = $(am__objects_22) \
+ $(am__objects_20)
libtcmalloc_minimal_la_OBJECTS = $(am_libtcmalloc_minimal_la_OBJECTS)
+am__DEPENDENCIES_4 = $(am__DEPENDENCIES_1) \
+ libtcmalloc_minimal_internal.la
+@WITH_DEBUGALLOC_TRUE@libtcmalloc_minimal_debug_la_DEPENDENCIES = \
+@WITH_DEBUGALLOC_TRUE@ $(am__DEPENDENCIES_4)
+am__libtcmalloc_minimal_debug_la_SOURCES_DIST = \
+ src/debugallocation.cc src/common.h src/internal_logging.h \
+ src/system-alloc.h src/packed-cache-inl.h src/base/spinlock.h \
+ src/base/atomicops.h src/base/atomicops-internals-macosx.h \
+ src/base/atomicops-internals-linuxppc.h \
+ src/base/atomicops-internals-x86-msvc.h \
+ src/base/atomicops-internals-x86.h \
+ src/base/spinlock_win32-inl.h src/base/spinlock_linux-inl.h \
+ src/base/spinlock_posix-inl.h src/tcmalloc_guard.h \
+ src/base/commandlineflags.h src/base/basictypes.h \
+ src/pagemap.h src/sampler.h src/central_freelist.h \
+ src/linked_list.h src/page_heap.h src/page_heap_allocator.h \
+ src/span.h src/static_vars.h src/symbolize.h \
+ src/thread_cache.h src/stack_trace_table.h \
+ src/base/thread_annotations.h src/malloc_hook-inl.h \
+ src/maybe_threads.h src/google/malloc_hook.h \
+ src/google/malloc_hook_c.h src/google/malloc_extension.h \
+ src/google/malloc_extension_c.h src/google/stacktrace.h
+@WITH_DEBUGALLOC_TRUE@am_libtcmalloc_minimal_debug_la_OBJECTS = libtcmalloc_minimal_debug_la-debugallocation.lo \
+@WITH_DEBUGALLOC_TRUE@ $(am__objects_20)
+libtcmalloc_minimal_debug_la_OBJECTS = \
+ $(am_libtcmalloc_minimal_debug_la_OBJECTS)
+@WITH_DEBUGALLOC_TRUE@am_libtcmalloc_minimal_debug_la_rpath = -rpath \
+@WITH_DEBUGALLOC_TRUE@ $(libdir)
libtcmalloc_minimal_internal_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_2)
am__libtcmalloc_minimal_internal_la_SOURCES_DIST = src/common.cc \
src/internal_logging.cc src/system-alloc.cc \
src/memfs_malloc.cc src/central_freelist.cc src/page_heap.cc \
src/sampler.cc src/span.cc src/stack_trace_table.cc \
- src/static_vars.cc src/thread_cache.cc src/malloc_hook.cc \
- src/malloc_extension.cc src/maybe_threads.cc src/common.h \
- src/internal_logging.h src/system-alloc.h \
- src/packed-cache-inl.h src/base/spinlock.h \
+ src/static_vars.cc src/symbolize.cc src/thread_cache.cc \
+ src/malloc_hook.cc src/malloc_extension.cc \
+ src/maybe_threads.cc src/common.h src/internal_logging.h \
+ src/system-alloc.h src/packed-cache-inl.h src/base/spinlock.h \
src/base/atomicops.h src/base/atomicops-internals-macosx.h \
src/base/atomicops-internals-linuxppc.h \
src/base/atomicops-internals-x86-msvc.h \
- src/base/atomicops-internals-x86.h src/tcmalloc_guard.h \
+ src/base/atomicops-internals-x86.h \
+ src/base/spinlock_win32-inl.h src/base/spinlock_linux-inl.h \
+ src/base/spinlock_posix-inl.h src/tcmalloc_guard.h \
src/base/commandlineflags.h src/base/basictypes.h \
src/pagemap.h src/sampler.h src/central_freelist.h \
src/linked_list.h src/page_heap.h src/page_heap_allocator.h \
- src/span.h src/static_vars.h src/thread_cache.h \
- src/stack_trace_table.h src/base/thread_annotations.h \
- src/malloc_hook-inl.h src/maybe_threads.h \
- src/google/malloc_hook.h src/google/malloc_hook_c.h \
- src/google/malloc_extension.h src/google/malloc_extension_c.h \
- src/google/stacktrace.h
-@MINGW_FALSE@am__objects_20 = \
+ src/span.h src/static_vars.h src/symbolize.h \
+ src/thread_cache.h src/stack_trace_table.h \
+ src/base/thread_annotations.h src/malloc_hook-inl.h \
+ src/maybe_threads.h src/google/malloc_hook.h \
+ src/google/malloc_hook_c.h src/google/malloc_extension.h \
+ src/google/malloc_extension_c.h src/google/stacktrace.h
+@MINGW_FALSE@am__objects_23 = \
@MINGW_FALSE@ libtcmalloc_minimal_internal_la-system-alloc.lo
-@MINGW_FALSE@am__objects_21 = \
+@MINGW_FALSE@am__objects_24 = \
@MINGW_FALSE@ libtcmalloc_minimal_internal_la-maybe_threads.lo
am_libtcmalloc_minimal_internal_la_OBJECTS = \
libtcmalloc_minimal_internal_la-common.lo \
libtcmalloc_minimal_internal_la-internal_logging.lo \
- $(am__objects_20) \
+ $(am__objects_23) \
libtcmalloc_minimal_internal_la-memfs_malloc.lo \
libtcmalloc_minimal_internal_la-central_freelist.lo \
libtcmalloc_minimal_internal_la-page_heap.lo \
@@ -513,10 +631,11 @@ am_libtcmalloc_minimal_internal_la_OBJECTS = \
libtcmalloc_minimal_internal_la-span.lo \
libtcmalloc_minimal_internal_la-stack_trace_table.lo \
libtcmalloc_minimal_internal_la-static_vars.lo \
+ libtcmalloc_minimal_internal_la-symbolize.lo \
libtcmalloc_minimal_internal_la-thread_cache.lo \
libtcmalloc_minimal_internal_la-malloc_hook.lo \
libtcmalloc_minimal_internal_la-malloc_extension.lo \
- $(am__objects_21) $(am__objects_17)
+ $(am__objects_24) $(am__objects_20)
libtcmalloc_minimal_internal_la_OBJECTS = \
$(am_libtcmalloc_minimal_internal_la_OBJECTS)
libwindows_la_LIBADD =
@@ -535,47 +654,62 @@ am__libwindows_la_SOURCES_DIST = src/windows/port.h \
libwindows_la_OBJECTS = $(am_libwindows_la_OBJECTS)
@MINGW_TRUE@am_libwindows_la_rpath =
binPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__EXEEXT_1 = \
+@WITH_DEBUGALLOC_TRUE@am__EXEEXT_1 = debugallocation_test$(EXEEXT)
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__EXEEXT_2 = \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampling_test$(EXEEXT)
-@WITH_HEAP_PROFILER_TRUE@am__EXEEXT_2 = \
+@WITH_HEAP_PROFILER_TRUE@am__EXEEXT_3 = \
@WITH_HEAP_PROFILER_TRUE@ heap-profiler_unittest$(EXEEXT)
-@WITH_HEAP_CHECKER_TRUE@am__EXEEXT_3 = heap-checker_unittest$(EXEEXT)
-@WITH_CPU_PROFILER_TRUE@am__EXEEXT_4 = profiler1_unittest$(EXEEXT) \
+@WITH_HEAP_CHECKER_TRUE@am__EXEEXT_4 = heap-checker_unittest$(EXEEXT)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__EXEEXT_5 = sampling_debug_test$(EXEEXT)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@am__EXEEXT_6 = heap-profiler_debug_unittest$(EXEEXT)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@am__EXEEXT_7 = heap-checker_debug_unittest$(EXEEXT)
+@WITH_CPU_PROFILER_TRUE@am__EXEEXT_8 = profiler1_unittest$(EXEEXT) \
@WITH_CPU_PROFILER_TRUE@ profiler2_unittest$(EXEEXT) \
@WITH_CPU_PROFILER_TRUE@ profiler3_unittest$(EXEEXT) \
@WITH_CPU_PROFILER_TRUE@ profiler4_unittest$(EXEEXT)
-@WITH_STACK_TRACE_TRUE@am__EXEEXT_5 = stacktrace_unittest$(EXEEXT)
-@MINGW_FALSE@am__EXEEXT_6 = maybe_threads_unittest.sh$(EXEEXT)
-@MINGW_FALSE@am__EXEEXT_7 = system_alloc_unittest$(EXEEXT)
-@MINGW_FALSE@am__EXEEXT_8 = memalign_unittest$(EXEEXT)
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__EXEEXT_9 = tcmalloc_unittest$(EXEEXT) \
+@WITH_STACK_TRACE_TRUE@am__EXEEXT_9 = stacktrace_unittest$(EXEEXT)
+@MINGW_FALSE@am__EXEEXT_10 = maybe_threads_unittest.sh$(EXEEXT)
+@MINGW_FALSE@am__EXEEXT_11 = system_alloc_unittest$(EXEEXT)
+@MINGW_FALSE@am__EXEEXT_12 = memalign_unittest$(EXEEXT)
+@WITH_DEBUGALLOC_TRUE@am__EXEEXT_13 = tcmalloc_minimal_debug_unittest$(EXEEXT) \
+@WITH_DEBUGALLOC_TRUE@ malloc_extension_debug_test$(EXEEXT) \
+@WITH_DEBUGALLOC_TRUE@ memalign_debug_unittest$(EXEEXT) \
+@WITH_DEBUGALLOC_TRUE@ realloc_debug_unittest$(EXEEXT) \
+@WITH_DEBUGALLOC_TRUE@ debugallocation_test.sh$(EXEEXT)
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__EXEEXT_14 = tcmalloc_unittest$(EXEEXT) \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ tcmalloc_both_unittest$(EXEEXT) \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ tcmalloc_large_unittest$(EXEEXT) \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ raw_printer_test$(EXEEXT) \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampler_test$(EXEEXT) \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampling_test.sh$(EXEEXT)
-@WITH_HEAP_PROFILER_TRUE@am__EXEEXT_10 = \
+@WITH_HEAP_PROFILER_TRUE@am__EXEEXT_15 = \
@WITH_HEAP_PROFILER_TRUE@ heap-profiler_unittest.sh$(EXEEXT)
-@WITH_HEAP_CHECKER_TRUE@am__EXEEXT_11 = \
+@WITH_HEAP_CHECKER_TRUE@am__EXEEXT_16 = \
@WITH_HEAP_CHECKER_TRUE@ heap-checker_unittest.sh$(EXEEXT) \
@WITH_HEAP_CHECKER_TRUE@ heap-checker-death_unittest.sh$(EXEEXT)
-@WITH_CPU_PROFILER_TRUE@am__EXEEXT_12 = getpc_test$(EXEEXT) \
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__EXEEXT_17 = tcmalloc_debug_unittest$(EXEEXT) \
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampler_debug_test$(EXEEXT) \
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampling_debug_test.sh$(EXEEXT)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@am__EXEEXT_18 = heap-profiler_debug_unittest.sh$(EXEEXT)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@am__EXEEXT_19 = heap-checker_debug_unittest.sh$(EXEEXT)
+@WITH_CPU_PROFILER_TRUE@am__EXEEXT_20 = getpc_test$(EXEEXT) \
@WITH_CPU_PROFILER_TRUE@ profiledata_unittest$(EXEEXT) \
@WITH_CPU_PROFILER_TRUE@ profile_handler_unittest$(EXEEXT) \
@WITH_CPU_PROFILER_TRUE@ profiler_unittest.sh$(EXEEXT)
-@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__EXEEXT_13 = tcmalloc_and_profiler_unittest$(EXEEXT)
-am__EXEEXT_14 = low_level_alloc_unittest$(EXEEXT) \
- atomicops_unittest$(EXEEXT) $(am__EXEEXT_5) \
+@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__EXEEXT_21 = tcmalloc_and_profiler_unittest$(EXEEXT)
+am__EXEEXT_22 = low_level_alloc_unittest$(EXEEXT) \
+ atomicops_unittest$(EXEEXT) $(am__EXEEXT_9) \
tcmalloc_minimal_unittest$(EXEEXT) \
- tcmalloc_minimal_large_unittest$(EXEEXT) $(am__EXEEXT_6) \
- addressmap_unittest$(EXEEXT) $(am__EXEEXT_7) \
+ tcmalloc_minimal_large_unittest$(EXEEXT) $(am__EXEEXT_10) \
+ addressmap_unittest$(EXEEXT) $(am__EXEEXT_11) \
packed_cache_test$(EXEEXT) frag_unittest$(EXEEXT) \
markidle_unittest$(EXEEXT) malloc_extension_test$(EXEEXT) \
- $(am__EXEEXT_8) pagemap_unittest$(EXEEXT) \
+ $(am__EXEEXT_12) pagemap_unittest$(EXEEXT) \
realloc_unittest$(EXEEXT) stack_trace_table_test$(EXEEXT) \
- thread_dealloc_unittest$(EXEEXT) $(am__EXEEXT_9) \
- $(am__EXEEXT_10) $(am__EXEEXT_11) $(am__EXEEXT_12) \
- $(am__EXEEXT_13)
+ thread_dealloc_unittest$(EXEEXT) $(am__EXEEXT_13) \
+ $(am__EXEEXT_14) $(am__EXEEXT_15) $(am__EXEEXT_16) \
+ $(am__EXEEXT_17) $(am__EXEEXT_18) $(am__EXEEXT_19) \
+ $(am__EXEEXT_20) $(am__EXEEXT_21)
PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS)
am_addressmap_unittest_OBJECTS = \
addressmap_unittest-addressmap_unittest.$(OBJEXT) \
@@ -586,12 +720,25 @@ am_atomicops_unittest_OBJECTS = atomicops_unittest.$(OBJEXT) \
$(am__objects_6)
atomicops_unittest_OBJECTS = $(am_atomicops_unittest_OBJECTS)
atomicops_unittest_DEPENDENCIES = $(am__DEPENDENCIES_2)
+am__debugallocation_test_SOURCES_DIST = \
+ src/tests/debugallocation_test.cc
+@WITH_DEBUGALLOC_TRUE@am_debugallocation_test_OBJECTS = debugallocation_test-debugallocation_test.$(OBJEXT)
+debugallocation_test_OBJECTS = $(am_debugallocation_test_OBJECTS)
+@WITH_DEBUGALLOC_TRUE@debugallocation_test_DEPENDENCIES = \
+@WITH_DEBUGALLOC_TRUE@ libtcmalloc_minimal_debug.la \
+@WITH_DEBUGALLOC_TRUE@ $(am__DEPENDENCIES_1)
+am__debugallocation_test_sh_SOURCES_DIST = \
+ src/tests/debugallocation_test.sh
+am_debugallocation_test_sh_OBJECTS =
+debugallocation_test_sh_OBJECTS = \
+ $(am_debugallocation_test_sh_OBJECTS)
+debugallocation_test_sh_LDADD = $(LDADD)
am_frag_unittest_OBJECTS = frag_unittest-frag_unittest.$(OBJEXT)
frag_unittest_OBJECTS = $(am_frag_unittest_OBJECTS)
-@MINGW_FALSE@am__DEPENDENCIES_4 = libtcmalloc_minimal.la
-@MINGW_TRUE@am__DEPENDENCIES_4 = libtcmalloc_minimal.la \
+@MINGW_FALSE@am__DEPENDENCIES_5 = libtcmalloc_minimal.la
+@MINGW_TRUE@am__DEPENDENCIES_5 = libtcmalloc_minimal.la \
@MINGW_TRUE@ libstacktrace.la
-frag_unittest_DEPENDENCIES = $(am__DEPENDENCIES_4) \
+frag_unittest_DEPENDENCIES = $(am__DEPENDENCIES_5) \
$(am__DEPENDENCIES_1)
am__getpc_test_SOURCES_DIST = src/tests/getpc_test.cc src/getpc.h
@WITH_CPU_PROFILER_TRUE@am_getpc_test_OBJECTS = getpc_test.$(OBJEXT)
@@ -603,27 +750,63 @@ am_heap_checker_death_unittest_sh_OBJECTS =
heap_checker_death_unittest_sh_OBJECTS = \
$(am_heap_checker_death_unittest_sh_OBJECTS)
heap_checker_death_unittest_sh_LDADD = $(LDADD)
+am__heap_checker_debug_unittest_SOURCES_DIST = \
+ src/tests/heap-checker_unittest.cc src/config_for_unittests.h \
+ src/memory_region_map.h src/base/commandlineflags.h \
+ src/base/googleinit.h src/google/heap-checker.h \
+ src/base/logging.h src/base/basictypes.h \
+ src/base/dynamic_annotations.h
+@WITH_HEAP_CHECKER_TRUE@am__objects_25 = $(am__objects_1)
+@WITH_HEAP_CHECKER_TRUE@am__objects_26 = heap_checker_debug_unittest-heap-checker_unittest.$(OBJEXT) \
+@WITH_HEAP_CHECKER_TRUE@ $(am__objects_25)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@am_heap_checker_debug_unittest_OBJECTS = $(am__objects_26)
+heap_checker_debug_unittest_OBJECTS = \
+ $(am_heap_checker_debug_unittest_OBJECTS)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@heap_checker_debug_unittest_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@ liblogging.la \
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@ libtcmalloc_debug.la
+am__heap_checker_debug_unittest_sh_SOURCES_DIST = \
+ src/tests/heap-checker_unittest.sh
+am_heap_checker_debug_unittest_sh_OBJECTS =
+heap_checker_debug_unittest_sh_OBJECTS = \
+ $(am_heap_checker_debug_unittest_sh_OBJECTS)
+heap_checker_debug_unittest_sh_LDADD = $(LDADD)
am__heap_checker_unittest_SOURCES_DIST = \
src/tests/heap-checker_unittest.cc src/config_for_unittests.h \
src/memory_region_map.h src/base/commandlineflags.h \
src/base/googleinit.h src/google/heap-checker.h \
src/base/logging.h src/base/basictypes.h \
src/base/dynamic_annotations.h
-@WITH_HEAP_CHECKER_TRUE@am__objects_22 = $(am__objects_1)
@WITH_HEAP_CHECKER_TRUE@am_heap_checker_unittest_OBJECTS = heap_checker_unittest-heap-checker_unittest.$(OBJEXT) \
-@WITH_HEAP_CHECKER_TRUE@ $(am__objects_22)
+@WITH_HEAP_CHECKER_TRUE@ $(am__objects_25)
heap_checker_unittest_OBJECTS = $(am_heap_checker_unittest_OBJECTS)
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__DEPENDENCIES_5 = \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__DEPENDENCIES_6 = \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libtcmalloc.la
@WITH_HEAP_CHECKER_TRUE@heap_checker_unittest_DEPENDENCIES = \
@WITH_HEAP_CHECKER_TRUE@ $(am__DEPENDENCIES_1) liblogging.la \
-@WITH_HEAP_CHECKER_TRUE@ $(am__DEPENDENCIES_5)
+@WITH_HEAP_CHECKER_TRUE@ $(am__DEPENDENCIES_6)
am__heap_checker_unittest_sh_SOURCES_DIST = \
src/tests/heap-checker_unittest.sh
am_heap_checker_unittest_sh_OBJECTS =
heap_checker_unittest_sh_OBJECTS = \
$(am_heap_checker_unittest_sh_OBJECTS)
heap_checker_unittest_sh_LDADD = $(LDADD)
+am__heap_profiler_debug_unittest_SOURCES_DIST = \
+ src/tests/heap-profiler_unittest.cc src/config_for_unittests.h \
+ src/google/heap-profiler.h
+@WITH_HEAP_PROFILER_TRUE@am__objects_27 = heap_profiler_debug_unittest-heap-profiler_unittest.$(OBJEXT) \
+@WITH_HEAP_PROFILER_TRUE@ $(am__objects_1)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@am_heap_profiler_debug_unittest_OBJECTS = $(am__objects_27)
+heap_profiler_debug_unittest_OBJECTS = \
+ $(am_heap_profiler_debug_unittest_OBJECTS)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@heap_profiler_debug_unittest_DEPENDENCIES = libtcmalloc_debug.la \
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@ $(am__DEPENDENCIES_1)
+am__heap_profiler_debug_unittest_sh_SOURCES_DIST = \
+ src/tests/heap-profiler_unittest.sh
+am_heap_profiler_debug_unittest_sh_OBJECTS =
+heap_profiler_debug_unittest_sh_OBJECTS = \
+ $(am_heap_profiler_debug_unittest_sh_OBJECTS)
+heap_profiler_debug_unittest_sh_LDADD = $(LDADD)
am__heap_profiler_unittest_SOURCES_DIST = \
src/tests/heap-profiler_unittest.cc src/config_for_unittests.h \
src/google/heap-profiler.h
@@ -631,7 +814,7 @@ am__heap_profiler_unittest_SOURCES_DIST = \
@WITH_HEAP_PROFILER_TRUE@ $(am__objects_1)
heap_profiler_unittest_OBJECTS = $(am_heap_profiler_unittest_OBJECTS)
@WITH_HEAP_PROFILER_TRUE@heap_profiler_unittest_DEPENDENCIES = \
-@WITH_HEAP_PROFILER_TRUE@ $(am__DEPENDENCIES_5) \
+@WITH_HEAP_PROFILER_TRUE@ $(am__DEPENDENCIES_6) \
@WITH_HEAP_PROFILER_TRUE@ $(am__DEPENDENCIES_1)
am__heap_profiler_unittest_sh_SOURCES_DIST = \
src/tests/heap-profiler_unittest.sh
@@ -648,27 +831,42 @@ am__low_level_alloc_unittest_SOURCES_DIST = \
src/base/atomicops-internals-macosx.h \
src/base/atomicops-internals-linuxppc.h \
src/base/atomicops-internals-x86-msvc.h \
- src/base/atomicops-internals-x86.h src/base/logging.h \
+ src/base/atomicops-internals-x86.h \
+ src/base/spinlock_win32-inl.h src/base/spinlock_linux-inl.h \
+ src/base/spinlock_posix-inl.h src/base/logging.h \
src/base/commandlineflags.h src/base/dynamic_annotations.h
-am__objects_23 = $(am__objects_1) $(am__objects_1)
+am__objects_28 = $(am__objects_1) $(am__objects_1)
am_low_level_alloc_unittest_OBJECTS = \
low_level_alloc_unittest-low_level_alloc.$(OBJEXT) \
low_level_alloc_unittest-malloc_hook.$(OBJEXT) \
low_level_alloc_unittest-low_level_alloc_unittest.$(OBJEXT) \
- $(am__objects_23)
+ $(am__objects_28)
low_level_alloc_unittest_OBJECTS = \
$(am_low_level_alloc_unittest_OBJECTS)
low_level_alloc_unittest_DEPENDENCIES = $(am__DEPENDENCIES_2)
+am__malloc_extension_debug_test_SOURCES_DIST = \
+ src/tests/malloc_extension_test.cc src/config_for_unittests.h \
+ src/base/logging.h src/google/malloc_extension.h \
+ src/google/malloc_extension_c.h
+am__objects_29 = \
+ malloc_extension_debug_test-malloc_extension_test.$(OBJEXT)
+@WITH_DEBUGALLOC_TRUE@am_malloc_extension_debug_test_OBJECTS = \
+@WITH_DEBUGALLOC_TRUE@ $(am__objects_29)
+malloc_extension_debug_test_OBJECTS = \
+ $(am_malloc_extension_debug_test_OBJECTS)
+@WITH_DEBUGALLOC_TRUE@malloc_extension_debug_test_DEPENDENCIES = \
+@WITH_DEBUGALLOC_TRUE@ libtcmalloc_minimal_debug.la \
+@WITH_DEBUGALLOC_TRUE@ $(am__DEPENDENCIES_1)
am_malloc_extension_test_OBJECTS = \
malloc_extension_test-malloc_extension_test.$(OBJEXT)
malloc_extension_test_OBJECTS = $(am_malloc_extension_test_OBJECTS)
-malloc_extension_test_DEPENDENCIES = $(am__DEPENDENCIES_4) \
+malloc_extension_test_DEPENDENCIES = $(am__DEPENDENCIES_5) \
$(am__DEPENDENCIES_1)
am_markidle_unittest_OBJECTS = \
markidle_unittest-markidle_unittest.$(OBJEXT) \
markidle_unittest-testutil.$(OBJEXT)
markidle_unittest_OBJECTS = $(am_markidle_unittest_OBJECTS)
-markidle_unittest_DEPENDENCIES = $(am__DEPENDENCIES_4) \
+markidle_unittest_DEPENDENCIES = $(am__DEPENDENCIES_5) \
$(am__DEPENDENCIES_1)
am__maybe_threads_unittest_sh_SOURCES_DIST = \
src/tests/maybe_threads_unittest.sh
@@ -676,6 +874,19 @@ am_maybe_threads_unittest_sh_OBJECTS =
maybe_threads_unittest_sh_OBJECTS = \
$(am_maybe_threads_unittest_sh_OBJECTS)
maybe_threads_unittest_sh_LDADD = $(LDADD)
+am__memalign_debug_unittest_SOURCES_DIST = \
+ src/tests/memalign_unittest.cc src/tcmalloc.h \
+ src/config_for_unittests.h src/tests/testutil.h \
+ src/tests/testutil.cc
+@MINGW_FALSE@am__objects_30 = memalign_debug_unittest-memalign_unittest.$(OBJEXT) \
+@MINGW_FALSE@ memalign_debug_unittest-testutil.$(OBJEXT)
+@WITH_DEBUGALLOC_TRUE@am_memalign_debug_unittest_OBJECTS = \
+@WITH_DEBUGALLOC_TRUE@ $(am__objects_30)
+memalign_debug_unittest_OBJECTS = \
+ $(am_memalign_debug_unittest_OBJECTS)
+@WITH_DEBUGALLOC_TRUE@memalign_debug_unittest_DEPENDENCIES = \
+@WITH_DEBUGALLOC_TRUE@ libtcmalloc_minimal_debug.la \
+@WITH_DEBUGALLOC_TRUE@ $(am__DEPENDENCIES_1)
am__memalign_unittest_SOURCES_DIST = src/tests/memalign_unittest.cc \
src/tcmalloc.h src/config_for_unittests.h src/tests/testutil.h \
src/tests/testutil.cc
@@ -683,25 +894,27 @@ am__memalign_unittest_SOURCES_DIST = src/tests/memalign_unittest.cc \
@MINGW_FALSE@ memalign_unittest-memalign_unittest.$(OBJEXT) \
@MINGW_FALSE@ memalign_unittest-testutil.$(OBJEXT)
memalign_unittest_OBJECTS = $(am_memalign_unittest_OBJECTS)
-@MINGW_FALSE@memalign_unittest_DEPENDENCIES = $(am__DEPENDENCIES_4) \
+@MINGW_FALSE@memalign_unittest_DEPENDENCIES = $(am__DEPENDENCIES_5) \
@MINGW_FALSE@ $(am__DEPENDENCIES_1)
-am_packed_cache_test_OBJECTS = packed-cache_test.$(OBJEXT)
+am_packed_cache_test_OBJECTS = \
+ packed_cache_test-packed-cache_test.$(OBJEXT)
packed_cache_test_OBJECTS = $(am_packed_cache_test_OBJECTS)
-packed_cache_test_LDADD = $(LDADD)
+packed_cache_test_DEPENDENCIES = $(am__DEPENDENCIES_5) \
+ $(am__DEPENDENCIES_1)
am_pagemap_unittest_OBJECTS = \
pagemap_unittest-pagemap_unittest.$(OBJEXT)
pagemap_unittest_OBJECTS = $(am_pagemap_unittest_OBJECTS)
-pagemap_unittest_DEPENDENCIES = $(am__DEPENDENCIES_4) \
+pagemap_unittest_DEPENDENCIES = $(am__DEPENDENCIES_5) \
$(am__DEPENDENCIES_1)
am__profile_handler_unittest_SOURCES_DIST = \
src/tests/profile-handler_unittest.cc src/profile-handler.h
@WITH_CPU_PROFILER_TRUE@am_profile_handler_unittest_OBJECTS = profile_handler_unittest-profile-handler_unittest.$(OBJEXT)
profile_handler_unittest_OBJECTS = \
$(am_profile_handler_unittest_OBJECTS)
-@WITH_CPU_PROFILER_TRUE@am__DEPENDENCIES_6 = libstacktrace.la \
+@WITH_CPU_PROFILER_TRUE@am__DEPENDENCIES_7 = libstacktrace.la \
@WITH_CPU_PROFILER_TRUE@ libprofiler.la
@WITH_CPU_PROFILER_TRUE@profile_handler_unittest_DEPENDENCIES = \
-@WITH_CPU_PROFILER_TRUE@ $(am__DEPENDENCIES_6) \
+@WITH_CPU_PROFILER_TRUE@ $(am__DEPENDENCIES_7) \
@WITH_CPU_PROFILER_TRUE@ $(am__DEPENDENCIES_1)
am__profiledata_unittest_SOURCES_DIST = \
src/tests/profiledata_unittest.cc src/profiledata.h \
@@ -711,47 +924,47 @@ am__profiledata_unittest_SOURCES_DIST = \
@WITH_CPU_PROFILER_TRUE@ profiledata_unittest.$(OBJEXT)
profiledata_unittest_OBJECTS = $(am_profiledata_unittest_OBJECTS)
@WITH_CPU_PROFILER_TRUE@profiledata_unittest_DEPENDENCIES = \
-@WITH_CPU_PROFILER_TRUE@ $(am__DEPENDENCIES_6)
+@WITH_CPU_PROFILER_TRUE@ $(am__DEPENDENCIES_7)
am__profiler1_unittest_SOURCES_DIST = src/tests/profiler_unittest.cc \
src/tests/testutil.h src/tests/testutil.cc \
src/config_for_unittests.h src/google/profiler.h
-@WITH_CPU_PROFILER_TRUE@am__objects_24 = profiler1_unittest-profiler_unittest.$(OBJEXT) \
+@WITH_CPU_PROFILER_TRUE@am__objects_31 = profiler1_unittest-profiler_unittest.$(OBJEXT) \
@WITH_CPU_PROFILER_TRUE@ profiler1_unittest-testutil.$(OBJEXT) \
@WITH_CPU_PROFILER_TRUE@ $(am__objects_1)
@WITH_CPU_PROFILER_TRUE@am_profiler1_unittest_OBJECTS = \
-@WITH_CPU_PROFILER_TRUE@ $(am__objects_24)
+@WITH_CPU_PROFILER_TRUE@ $(am__objects_31)
profiler1_unittest_OBJECTS = $(am_profiler1_unittest_OBJECTS)
@WITH_CPU_PROFILER_TRUE@profiler1_unittest_DEPENDENCIES = \
-@WITH_CPU_PROFILER_TRUE@ $(am__DEPENDENCIES_6)
+@WITH_CPU_PROFILER_TRUE@ $(am__DEPENDENCIES_7)
am__profiler2_unittest_SOURCES_DIST = src/tests/profiler_unittest.cc \
src/tests/testutil.h src/tests/testutil.cc \
src/config_for_unittests.h src/google/profiler.h
-@WITH_CPU_PROFILER_TRUE@am__objects_25 = profiler2_unittest-profiler_unittest.$(OBJEXT) \
+@WITH_CPU_PROFILER_TRUE@am__objects_32 = profiler2_unittest-profiler_unittest.$(OBJEXT) \
@WITH_CPU_PROFILER_TRUE@ profiler2_unittest-testutil.$(OBJEXT) \
@WITH_CPU_PROFILER_TRUE@ $(am__objects_1)
@WITH_CPU_PROFILER_TRUE@am_profiler2_unittest_OBJECTS = \
-@WITH_CPU_PROFILER_TRUE@ $(am__objects_25)
+@WITH_CPU_PROFILER_TRUE@ $(am__objects_32)
profiler2_unittest_OBJECTS = $(am_profiler2_unittest_OBJECTS)
am__profiler3_unittest_SOURCES_DIST = src/tests/profiler_unittest.cc \
src/tests/testutil.h src/tests/testutil.cc \
src/config_for_unittests.h src/google/profiler.h
-@WITH_CPU_PROFILER_TRUE@am__objects_26 = profiler3_unittest-profiler_unittest.$(OBJEXT) \
+@WITH_CPU_PROFILER_TRUE@am__objects_33 = profiler3_unittest-profiler_unittest.$(OBJEXT) \
@WITH_CPU_PROFILER_TRUE@ profiler3_unittest-testutil.$(OBJEXT) \
@WITH_CPU_PROFILER_TRUE@ $(am__objects_1)
@WITH_CPU_PROFILER_TRUE@am_profiler3_unittest_OBJECTS = \
-@WITH_CPU_PROFILER_TRUE@ $(am__objects_26)
+@WITH_CPU_PROFILER_TRUE@ $(am__objects_33)
profiler3_unittest_OBJECTS = $(am_profiler3_unittest_OBJECTS)
@WITH_CPU_PROFILER_TRUE@profiler3_unittest_DEPENDENCIES = \
-@WITH_CPU_PROFILER_TRUE@ $(am__DEPENDENCIES_6) \
+@WITH_CPU_PROFILER_TRUE@ $(am__DEPENDENCIES_7) \
@WITH_CPU_PROFILER_TRUE@ $(am__DEPENDENCIES_1)
am__profiler4_unittest_SOURCES_DIST = src/tests/profiler_unittest.cc \
src/tests/testutil.h src/tests/testutil.cc \
src/config_for_unittests.h src/google/profiler.h
-@WITH_CPU_PROFILER_TRUE@am__objects_27 = profiler4_unittest-profiler_unittest.$(OBJEXT) \
+@WITH_CPU_PROFILER_TRUE@am__objects_34 = profiler4_unittest-profiler_unittest.$(OBJEXT) \
@WITH_CPU_PROFILER_TRUE@ profiler4_unittest-testutil.$(OBJEXT) \
@WITH_CPU_PROFILER_TRUE@ $(am__objects_1)
@WITH_CPU_PROFILER_TRUE@am_profiler4_unittest_OBJECTS = \
-@WITH_CPU_PROFILER_TRUE@ $(am__objects_27)
+@WITH_CPU_PROFILER_TRUE@ $(am__objects_34)
profiler4_unittest_OBJECTS = $(am_profiler4_unittest_OBJECTS)
am__profiler_unittest_sh_SOURCES_DIST = \
src/tests/profiler_unittest.sh
@@ -770,20 +983,50 @@ am__raw_printer_test_SOURCES_DIST = src/tests/raw_printer_test.cc
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_raw_printer_test_OBJECTS = raw_printer_test-raw_printer_test.$(OBJEXT)
raw_printer_test_OBJECTS = $(am_raw_printer_test_OBJECTS)
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@raw_printer_test_DEPENDENCIES = \
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_5) \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_6) \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_1)
+am__realloc_debug_unittest_SOURCES_DIST = \
+ src/tests/realloc_unittest.cc src/config_for_unittests.h \
+ src/base/logging.h
+am__objects_35 = realloc_debug_unittest-realloc_unittest.$(OBJEXT)
+@WITH_DEBUGALLOC_TRUE@am_realloc_debug_unittest_OBJECTS = \
+@WITH_DEBUGALLOC_TRUE@ $(am__objects_35)
+realloc_debug_unittest_OBJECTS = $(am_realloc_debug_unittest_OBJECTS)
+@WITH_DEBUGALLOC_TRUE@realloc_debug_unittest_DEPENDENCIES = \
+@WITH_DEBUGALLOC_TRUE@ libtcmalloc_minimal_debug.la \
+@WITH_DEBUGALLOC_TRUE@ $(am__DEPENDENCIES_1)
am_realloc_unittest_OBJECTS = \
realloc_unittest-realloc_unittest.$(OBJEXT)
realloc_unittest_OBJECTS = $(am_realloc_unittest_OBJECTS)
-realloc_unittest_DEPENDENCIES = $(am__DEPENDENCIES_4) \
+realloc_unittest_DEPENDENCIES = $(am__DEPENDENCIES_5) \
$(am__DEPENDENCIES_1)
+am__sampler_debug_test_SOURCES_DIST = src/tests/sampler_test.cc \
+ src/config_for_unittests.h
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_36 = sampler_debug_test-sampler_test.$(OBJEXT)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_sampler_debug_test_OBJECTS = $(am__objects_36)
+sampler_debug_test_OBJECTS = $(am_sampler_debug_test_OBJECTS)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampler_debug_test_DEPENDENCIES = libtcmalloc_debug.la \
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_1)
am__sampler_test_SOURCES_DIST = src/tests/sampler_test.cc \
src/config_for_unittests.h
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_sampler_test_OBJECTS = sampler_test-sampler_test.$(OBJEXT)
sampler_test_OBJECTS = $(am_sampler_test_OBJECTS)
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampler_test_DEPENDENCIES = \
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_5) \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_6) \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_1)
+am__sampling_debug_test_SOURCES_DIST = src/tests/sampling_test.cc \
+ src/config_for_unittests.h src/base/logging.h \
+ src/google/malloc_extension.h
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_37 = sampling_debug_test-sampling_test.$(OBJEXT) \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_1)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_sampling_debug_test_OBJECTS = $(am__objects_37)
+sampling_debug_test_OBJECTS = $(am_sampling_debug_test_OBJECTS)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampling_debug_test_DEPENDENCIES = libtcmalloc_debug.la \
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_1)
+am__sampling_debug_test_sh_SOURCES_DIST = src/tests/sampling_test.sh
+am_sampling_debug_test_sh_OBJECTS =
+sampling_debug_test_sh_OBJECTS = $(am_sampling_debug_test_sh_OBJECTS)
+sampling_debug_test_sh_LDADD = $(LDADD)
am__sampling_test_SOURCES_DIST = src/tests/sampling_test.cc \
src/config_for_unittests.h src/base/logging.h \
src/google/malloc_extension.h
@@ -791,7 +1034,7 @@ am__sampling_test_SOURCES_DIST = src/tests/sampling_test.cc \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_1)
sampling_test_OBJECTS = $(am_sampling_test_OBJECTS)
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampling_test_DEPENDENCIES = \
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_5) \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_6) \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_1)
am__sampling_test_sh_SOURCES_DIST = src/tests/sampling_test.sh
am_sampling_test_sh_OBJECTS =
@@ -800,7 +1043,7 @@ sampling_test_sh_LDADD = $(LDADD)
am_stack_trace_table_test_OBJECTS = \
stack_trace_table_test-stack_trace_table_test.$(OBJEXT)
stack_trace_table_test_OBJECTS = $(am_stack_trace_table_test_OBJECTS)
-stack_trace_table_test_DEPENDENCIES = $(am__DEPENDENCIES_4) \
+stack_trace_table_test_DEPENDENCIES = $(am__DEPENDENCIES_5) \
$(am__DEPENDENCIES_1)
am__stacktrace_unittest_SOURCES_DIST = \
src/tests/stacktrace_unittest.cc src/config_for_unittests.h \
@@ -811,11 +1054,11 @@ am__stacktrace_unittest_SOURCES_DIST = \
src/base/vdso_support.h src/google/stacktrace.h \
src/base/logging.h src/base/basictypes.h \
src/base/dynamic_annotations.h
-@WITH_STACK_TRACE_TRUE@am__objects_28 = $(am__objects_4) \
+@WITH_STACK_TRACE_TRUE@am__objects_38 = $(am__objects_4) \
@WITH_STACK_TRACE_TRUE@ $(am__objects_1)
@WITH_STACK_TRACE_TRUE@am_stacktrace_unittest_OBJECTS = \
@WITH_STACK_TRACE_TRUE@ stacktrace_unittest.$(OBJEXT) \
-@WITH_STACK_TRACE_TRUE@ $(am__objects_28)
+@WITH_STACK_TRACE_TRUE@ $(am__objects_38)
stacktrace_unittest_OBJECTS = $(am_stacktrace_unittest_OBJECTS)
@WITH_STACK_TRACE_TRUE@stacktrace_unittest_DEPENDENCIES = \
@WITH_STACK_TRACE_TRUE@ libstacktrace.la liblogging.la
@@ -824,15 +1067,15 @@ am__system_alloc_unittest_SOURCES_DIST = src/config_for_unittests.h \
@MINGW_FALSE@am_system_alloc_unittest_OBJECTS = system_alloc_unittest-system-alloc_unittest.$(OBJEXT)
system_alloc_unittest_OBJECTS = $(am_system_alloc_unittest_OBJECTS)
@MINGW_FALSE@system_alloc_unittest_DEPENDENCIES = \
-@MINGW_FALSE@ $(am__DEPENDENCIES_4) $(am__DEPENDENCIES_1)
+@MINGW_FALSE@ $(am__DEPENDENCIES_5) $(am__DEPENDENCIES_1)
am__tcmalloc_and_profiler_unittest_SOURCES_DIST = \
src/tests/tcmalloc_unittest.cc src/tests/testutil.h \
src/tests/testutil.cc src/config_for_unittests.h \
src/google/malloc_extension.h
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_29 = tcmalloc_and_profiler_unittest-tcmalloc_unittest.$(OBJEXT) \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_39 = tcmalloc_and_profiler_unittest-tcmalloc_unittest.$(OBJEXT) \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ tcmalloc_and_profiler_unittest-testutil.$(OBJEXT) \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_1)
-@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_tcmalloc_and_profiler_unittest_OBJECTS = $(am__objects_29)
+@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_tcmalloc_and_profiler_unittest_OBJECTS = $(am__objects_39)
tcmalloc_and_profiler_unittest_OBJECTS = \
$(am_tcmalloc_and_profiler_unittest_OBJECTS)
@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_and_profiler_unittest_DEPENDENCIES = libtcmalloc_and_profiler.la
@@ -844,27 +1087,54 @@ am__tcmalloc_both_unittest_SOURCES_DIST = \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ tcmalloc_both_unittest-testutil.$(OBJEXT) \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_1)
tcmalloc_both_unittest_OBJECTS = $(am_tcmalloc_both_unittest_OBJECTS)
-@WITH_CPU_PROFILER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_both_unittest_DEPENDENCIES = $(am__DEPENDENCIES_5) \
-@WITH_CPU_PROFILER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_4) \
+@WITH_CPU_PROFILER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_both_unittest_DEPENDENCIES = $(am__DEPENDENCIES_6) \
+@WITH_CPU_PROFILER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_5) \
@WITH_CPU_PROFILER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ liblogging.la \
@WITH_CPU_PROFILER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_1)
-@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_both_unittest_DEPENDENCIES = $(am__DEPENDENCIES_5) \
-@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_4) \
+@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_both_unittest_DEPENDENCIES = $(am__DEPENDENCIES_6) \
+@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_5) \
@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ libprofiler.la \
@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ liblogging.la \
@WITH_CPU_PROFILER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_1)
+am__tcmalloc_debug_unittest_SOURCES_DIST = \
+ src/tests/tcmalloc_unittest.cc src/tcmalloc.h \
+ src/tests/testutil.h src/tests/testutil.cc \
+ src/config_for_unittests.h src/google/malloc_extension.h
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am__objects_40 = tcmalloc_debug_unittest-tcmalloc_unittest.$(OBJEXT) \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ tcmalloc_debug_unittest-testutil.$(OBJEXT) \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_1)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_tcmalloc_debug_unittest_OBJECTS = $(am__objects_40)
+tcmalloc_debug_unittest_OBJECTS = \
+ $(am_tcmalloc_debug_unittest_OBJECTS)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_debug_unittest_DEPENDENCIES = libtcmalloc_debug.la \
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_1)
am__tcmalloc_large_unittest_SOURCES_DIST = \
src/tests/tcmalloc_large_unittest.cc
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@am_tcmalloc_large_unittest_OBJECTS = tcmalloc_large_unittest-tcmalloc_large_unittest.$(OBJEXT)
tcmalloc_large_unittest_OBJECTS = \
$(am_tcmalloc_large_unittest_OBJECTS)
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_large_unittest_DEPENDENCIES = \
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_5) \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_6) \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_1)
+am__tcmalloc_minimal_debug_unittest_SOURCES_DIST = \
+ src/tests/tcmalloc_unittest.cc src/tests/testutil.h \
+ src/tests/testutil.cc src/config_for_unittests.h \
+ src/google/malloc_extension.h
+am__objects_41 = \
+ tcmalloc_minimal_debug_unittest-tcmalloc_unittest.$(OBJEXT) \
+ tcmalloc_minimal_debug_unittest-testutil.$(OBJEXT) \
+ $(am__objects_1)
+@WITH_DEBUGALLOC_TRUE@am_tcmalloc_minimal_debug_unittest_OBJECTS = \
+@WITH_DEBUGALLOC_TRUE@ $(am__objects_41)
+tcmalloc_minimal_debug_unittest_OBJECTS = \
+ $(am_tcmalloc_minimal_debug_unittest_OBJECTS)
+@WITH_DEBUGALLOC_TRUE@tcmalloc_minimal_debug_unittest_DEPENDENCIES = \
+@WITH_DEBUGALLOC_TRUE@ libtcmalloc_minimal_debug.la \
+@WITH_DEBUGALLOC_TRUE@ $(am__DEPENDENCIES_1)
am_tcmalloc_minimal_large_unittest_OBJECTS = tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.$(OBJEXT)
tcmalloc_minimal_large_unittest_OBJECTS = \
$(am_tcmalloc_minimal_large_unittest_OBJECTS)
-tcmalloc_minimal_large_unittest_DEPENDENCIES = $(am__DEPENDENCIES_4) \
+tcmalloc_minimal_large_unittest_DEPENDENCIES = $(am__DEPENDENCIES_5) \
$(am__DEPENDENCIES_1)
am__tcmalloc_minimal_unittest_SOURCES_DIST = \
src/tests/tcmalloc_unittest.cc src/tests/testutil.h \
@@ -875,7 +1145,7 @@ am_tcmalloc_minimal_unittest_OBJECTS = \
tcmalloc_minimal_unittest-testutil.$(OBJEXT) $(am__objects_1)
tcmalloc_minimal_unittest_OBJECTS = \
$(am_tcmalloc_minimal_unittest_OBJECTS)
-tcmalloc_minimal_unittest_DEPENDENCIES = $(am__DEPENDENCIES_4) \
+tcmalloc_minimal_unittest_DEPENDENCIES = $(am__DEPENDENCIES_5) \
liblogging.la $(am__DEPENDENCIES_1)
am__tcmalloc_unittest_SOURCES_DIST = src/tests/tcmalloc_unittest.cc \
src/tcmalloc.h src/tests/testutil.h src/tests/testutil.cc \
@@ -885,7 +1155,7 @@ am__tcmalloc_unittest_SOURCES_DIST = src/tests/tcmalloc_unittest.cc \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__objects_1)
tcmalloc_unittest_OBJECTS = $(am_tcmalloc_unittest_OBJECTS)
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_unittest_DEPENDENCIES = \
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_5) \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_6) \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ liblogging.la \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__DEPENDENCIES_1)
am_thread_dealloc_unittest_OBJECTS = \
@@ -893,7 +1163,7 @@ am_thread_dealloc_unittest_OBJECTS = \
thread_dealloc_unittest-testutil.$(OBJEXT)
thread_dealloc_unittest_OBJECTS = \
$(am_thread_dealloc_unittest_OBJECTS)
-thread_dealloc_unittest_DEPENDENCIES = $(am__DEPENDENCIES_4) \
+thread_dealloc_unittest_DEPENDENCIES = $(am__DEPENDENCIES_5) \
$(am__DEPENDENCIES_1)
binSCRIPT_INSTALL = $(INSTALL_SCRIPT)
SCRIPTS = $(bin_SCRIPTS) $(noinst_SCRIPTS)
@@ -920,20 +1190,29 @@ SOURCES = $(liblogging_la_SOURCES) $(libprofiler_la_SOURCES) \
$(libspinlock_la_SOURCES) $(libstacktrace_la_SOURCES) \
$(libsysinfo_la_SOURCES) $(libtcmalloc_la_SOURCES) \
$(libtcmalloc_and_profiler_la_SOURCES) \
+ $(libtcmalloc_debug_la_SOURCES) \
$(libtcmalloc_internal_la_SOURCES) \
$(libtcmalloc_minimal_la_SOURCES) \
+ $(libtcmalloc_minimal_debug_la_SOURCES) \
$(libtcmalloc_minimal_internal_la_SOURCES) \
$(libwindows_la_SOURCES) $(addressmap_unittest_SOURCES) \
- $(atomicops_unittest_SOURCES) $(frag_unittest_SOURCES) \
+ $(atomicops_unittest_SOURCES) $(debugallocation_test_SOURCES) \
+ $(debugallocation_test_sh_SOURCES) $(frag_unittest_SOURCES) \
$(getpc_test_SOURCES) \
$(heap_checker_death_unittest_sh_SOURCES) \
+ $(heap_checker_debug_unittest_SOURCES) \
+ $(heap_checker_debug_unittest_sh_SOURCES) \
$(heap_checker_unittest_SOURCES) \
$(heap_checker_unittest_sh_SOURCES) \
+ $(heap_profiler_debug_unittest_SOURCES) \
+ $(heap_profiler_debug_unittest_sh_SOURCES) \
$(heap_profiler_unittest_SOURCES) \
$(heap_profiler_unittest_sh_SOURCES) \
$(low_level_alloc_unittest_SOURCES) \
+ $(malloc_extension_debug_test_SOURCES) \
$(malloc_extension_test_SOURCES) $(markidle_unittest_SOURCES) \
$(maybe_threads_unittest_sh_SOURCES) \
+ $(memalign_debug_unittest_SOURCES) \
$(memalign_unittest_SOURCES) $(packed_cache_test_SOURCES) \
$(pagemap_unittest_SOURCES) \
$(profile_handler_unittest_SOURCES) \
@@ -941,14 +1220,18 @@ SOURCES = $(liblogging_la_SOURCES) $(libprofiler_la_SOURCES) \
$(profiler2_unittest_SOURCES) $(profiler3_unittest_SOURCES) \
$(profiler4_unittest_SOURCES) $(profiler_unittest_sh_SOURCES) \
$(ptmalloc_unittest1_SOURCES) $(ptmalloc_unittest2_SOURCES) \
- $(raw_printer_test_SOURCES) $(realloc_unittest_SOURCES) \
- $(sampler_test_SOURCES) $(sampling_test_SOURCES) \
+ $(raw_printer_test_SOURCES) $(realloc_debug_unittest_SOURCES) \
+ $(realloc_unittest_SOURCES) $(sampler_debug_test_SOURCES) \
+ $(sampler_test_SOURCES) $(sampling_debug_test_SOURCES) \
+ $(sampling_debug_test_sh_SOURCES) $(sampling_test_SOURCES) \
$(sampling_test_sh_SOURCES) $(stack_trace_table_test_SOURCES) \
$(stacktrace_unittest_SOURCES) \
$(system_alloc_unittest_SOURCES) \
$(tcmalloc_and_profiler_unittest_SOURCES) \
$(tcmalloc_both_unittest_SOURCES) \
+ $(tcmalloc_debug_unittest_SOURCES) \
$(tcmalloc_large_unittest_SOURCES) \
+ $(tcmalloc_minimal_debug_unittest_SOURCES) \
$(tcmalloc_minimal_large_unittest_SOURCES) \
$(tcmalloc_minimal_unittest_SOURCES) \
$(tcmalloc_unittest_SOURCES) \
@@ -959,20 +1242,30 @@ DIST_SOURCES = $(liblogging_la_SOURCES) \
$(am__libstacktrace_la_SOURCES_DIST) $(libsysinfo_la_SOURCES) \
$(am__libtcmalloc_la_SOURCES_DIST) \
$(am__libtcmalloc_and_profiler_la_SOURCES_DIST) \
+ $(am__libtcmalloc_debug_la_SOURCES_DIST) \
$(am__libtcmalloc_internal_la_SOURCES_DIST) \
$(am__libtcmalloc_minimal_la_SOURCES_DIST) \
+ $(am__libtcmalloc_minimal_debug_la_SOURCES_DIST) \
$(am__libtcmalloc_minimal_internal_la_SOURCES_DIST) \
$(am__libwindows_la_SOURCES_DIST) \
$(addressmap_unittest_SOURCES) $(atomicops_unittest_SOURCES) \
+ $(am__debugallocation_test_SOURCES_DIST) \
+ $(am__debugallocation_test_sh_SOURCES_DIST) \
$(frag_unittest_SOURCES) $(am__getpc_test_SOURCES_DIST) \
$(am__heap_checker_death_unittest_sh_SOURCES_DIST) \
+ $(am__heap_checker_debug_unittest_SOURCES_DIST) \
+ $(am__heap_checker_debug_unittest_sh_SOURCES_DIST) \
$(am__heap_checker_unittest_SOURCES_DIST) \
$(am__heap_checker_unittest_sh_SOURCES_DIST) \
+ $(am__heap_profiler_debug_unittest_SOURCES_DIST) \
+ $(am__heap_profiler_debug_unittest_sh_SOURCES_DIST) \
$(am__heap_profiler_unittest_SOURCES_DIST) \
$(am__heap_profiler_unittest_sh_SOURCES_DIST) \
$(am__low_level_alloc_unittest_SOURCES_DIST) \
+ $(am__malloc_extension_debug_test_SOURCES_DIST) \
$(malloc_extension_test_SOURCES) $(markidle_unittest_SOURCES) \
$(am__maybe_threads_unittest_sh_SOURCES_DIST) \
+ $(am__memalign_debug_unittest_SOURCES_DIST) \
$(am__memalign_unittest_SOURCES_DIST) \
$(packed_cache_test_SOURCES) $(pagemap_unittest_SOURCES) \
$(am__profile_handler_unittest_SOURCES_DIST) \
@@ -984,7 +1277,12 @@ DIST_SOURCES = $(liblogging_la_SOURCES) \
$(am__profiler_unittest_sh_SOURCES_DIST) \
$(ptmalloc_unittest1_SOURCES) $(ptmalloc_unittest2_SOURCES) \
$(am__raw_printer_test_SOURCES_DIST) \
- $(realloc_unittest_SOURCES) $(am__sampler_test_SOURCES_DIST) \
+ $(am__realloc_debug_unittest_SOURCES_DIST) \
+ $(realloc_unittest_SOURCES) \
+ $(am__sampler_debug_test_SOURCES_DIST) \
+ $(am__sampler_test_SOURCES_DIST) \
+ $(am__sampling_debug_test_SOURCES_DIST) \
+ $(am__sampling_debug_test_sh_SOURCES_DIST) \
$(am__sampling_test_SOURCES_DIST) \
$(am__sampling_test_sh_SOURCES_DIST) \
$(stack_trace_table_test_SOURCES) \
@@ -992,7 +1290,9 @@ DIST_SOURCES = $(liblogging_la_SOURCES) \
$(am__system_alloc_unittest_SOURCES_DIST) \
$(am__tcmalloc_and_profiler_unittest_SOURCES_DIST) \
$(am__tcmalloc_both_unittest_SOURCES_DIST) \
+ $(am__tcmalloc_debug_unittest_SOURCES_DIST) \
$(am__tcmalloc_large_unittest_SOURCES_DIST) \
+ $(am__tcmalloc_minimal_debug_unittest_SOURCES_DIST) \
$(tcmalloc_minimal_large_unittest_SOURCES) \
$(am__tcmalloc_minimal_unittest_SOURCES_DIST) \
$(am__tcmalloc_unittest_SOURCES_DIST) \
@@ -1127,12 +1427,17 @@ SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
+TC_VERSION_MAJOR = @TC_VERSION_MAJOR@
+TC_VERSION_MINOR = @TC_VERSION_MINOR@
+TC_VERSION_PATCH = @TC_VERSION_PATCH@
UNWIND_LIBS = @UNWIND_LIBS@
USE_LIBTOOL_FALSE = @USE_LIBTOOL_FALSE@
USE_LIBTOOL_TRUE = @USE_LIBTOOL_TRUE@
VERSION = @VERSION@
WITH_CPU_PROFILER_FALSE = @WITH_CPU_PROFILER_FALSE@
WITH_CPU_PROFILER_TRUE = @WITH_CPU_PROFILER_TRUE@
+WITH_DEBUGALLOC_FALSE = @WITH_DEBUGALLOC_FALSE@
+WITH_DEBUGALLOC_TRUE = @WITH_DEBUGALLOC_TRUE@
WITH_HEAP_CHECKER_FALSE = @WITH_HEAP_CHECKER_FALSE@
WITH_HEAP_CHECKER_TRUE = @WITH_HEAP_CHECKER_TRUE@
WITH_HEAP_PROFILER_FALSE = @WITH_HEAP_PROFILER_FALSE@
@@ -1224,16 +1529,28 @@ TCMALLOC_FLAGS = $(am__append_5)
# If we have objcopy, make malloc/free/etc weak symbols. That way folks
# can override our malloc if they want to (they can still use tc_malloc).
-@HAVE_OBJCOPY_WEAKEN_TRUE@WEAKEN = $(OBJCOPY) -W malloc -W free -W realloc -W calloc -W cfree -W memalign -W posix_memalign -W valloc -W pvalloc -W malloc_stats -W mallopt -W mallinfo
-LIBS_TO_WEAKEN = libtcmalloc_minimal.la $(am__append_23) \
- $(am__append_45)
+# Note: the weird-looking symbols are the c++ memory functions:
+# (in order) new, new(nothrow), new[], new[](nothrow), delete, delete[]
+# In theory this will break if mangling changes, but that seems pretty
+# unlikely at this point. Just in case, I throw in versions with an
+# extra underscore as well, which may help on OS X.
+@HAVE_OBJCOPY_WEAKEN_TRUE@WEAKEN = $(OBJCOPY) -W malloc -W free -W realloc -W calloc -W cfree \
+@HAVE_OBJCOPY_WEAKEN_TRUE@ -W memalign -W posix_memalign -W valloc -W pvalloc \
+@HAVE_OBJCOPY_WEAKEN_TRUE@ -W malloc_stats -W mallopt -W mallinfo \
+@HAVE_OBJCOPY_WEAKEN_TRUE@ -W _Znwm -W _ZnwmRKSt9nothrow_t -W _Znam -W _ZnamRKSt9nothrow_t \
+@HAVE_OBJCOPY_WEAKEN_TRUE@ -W _ZdlPv -W _ZdaPv \
+@HAVE_OBJCOPY_WEAKEN_TRUE@ -W __Znwm -W __ZnwmRKSt9nothrow_t -W __Znam -W __ZnamRKSt9nothrow_t \
+@HAVE_OBJCOPY_WEAKEN_TRUE@ -W __ZdlPv -W __ZdaPv
+
+LIBS_TO_WEAKEN = libtcmalloc_minimal.la $(am__append_20) \
+ $(am__append_30) $(am__append_45) $(am__append_60)
googleincludedir = $(includedir)/google
# The .h files you want to install (that is, .h files that people
# who install this package can include in their own applications.)
# We'll add to this later, on a library-by-library basis
googleinclude_HEADERS = $(am__append_9) \
- $(SG_TCMALLOC_MINIMAL_INCLUDES) $(am__append_19) \
- $(am__append_37)
+ $(SG_TCMALLOC_MINIMAL_INCLUDES) $(am__append_24) \
+ $(am__append_52)
# tcmalloc.h is a special case, because it's a .h.in file
nodist_googleinclude_HEADERS = src/google/tcmalloc.h
noinst_HEADERS = src/google/tcmalloc.h.in
@@ -1275,12 +1592,13 @@ dist_doc_DATA = AUTHORS COPYING ChangeLog INSTALL NEWS README \
doc/tcmalloc-opspersec.vs.size.5.threads.png \
doc/tcmalloc-opspersec.vs.size.8.threads.png doc/overview.dot \
doc/pageheap.dot doc/spanmap.dot doc/threadheap.dot \
- $(am__append_35) $(am__append_36) $(am__append_42)
+ $(am__append_42) $(am__append_43) $(am__append_57)
# The libraries (.so's) you want to install
# We'll add to this later, on a library-by-library basis
-lib_LTLIBRARIES = libtcmalloc_minimal.la $(am__append_21) \
- $(am__append_38) $(am__append_43)
+lib_LTLIBRARIES = libtcmalloc_minimal.la $(am__append_19) \
+ $(am__append_26) $(am__append_44) $(am__append_53) \
+ $(am__append_58)
# This is for 'convenience libraries' -- basically just a container for sources
### Making the library
@@ -1291,7 +1609,7 @@ lib_LTLIBRARIES = libtcmalloc_minimal.la $(am__append_21) \
# to separate into two libraries.
noinst_LTLIBRARIES = liblogging.la libsysinfo.la $(am__append_6) \
$(am__append_8) $(am__append_10) \
- libtcmalloc_minimal_internal.la $(am__append_20)
+ libtcmalloc_minimal_internal.la $(am__append_25)
WINDOWS_PROJECTS = google-perftools.sln \
vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj \
$(am__append_14) \
@@ -1308,7 +1626,7 @@ WINDOWS_PROJECTS = google-perftools.sln \
vsprojects/realloc_unittest/realloc_unittest.vcproj \
vsprojects/stack_trace_table_test/stack_trace_table_test.vcproj \
vsprojects/thread_dealloc_unittest/thread_dealloc_unittest.vcproj \
- $(am__append_25)
+ $(am__append_32)
# unittests you want to run when people type 'make check'.
# Note: tests cannot take any arguments!
@@ -1333,15 +1651,17 @@ TESTS = low_level_alloc_unittest atomicops_unittest $(am__append_11) \
packed_cache_test frag_unittest markidle_unittest \
malloc_extension_test $(am__append_18) pagemap_unittest \
realloc_unittest stack_trace_table_test \
- thread_dealloc_unittest $(am__append_24) $(am__append_29) \
- $(am__append_32) $(am__append_39) $(am__append_44)
+ thread_dealloc_unittest $(am__append_21) $(am__append_31) \
+ $(am__append_36) $(am__append_39) $(am__append_46) \
+ $(am__append_48) $(am__append_50) $(am__append_54) \
+ $(am__append_59)
# TESTS_ENVIRONMENT sets environment variables for when you run unittest.
# We always get "srcdir" set for free.
# We'll add to this later, on a library-by-library basis.
-TESTS_ENVIRONMENT = $(am__append_13) $(am__append_26)
+TESTS_ENVIRONMENT = $(am__append_13) $(am__append_33)
# All script tests should be added here
-noinst_SCRIPTS = $(am__append_16) $(am__append_27) $(am__append_30) \
- $(am__append_33) $(am__append_40)
+noinst_SCRIPTS = $(am__append_16) $(am__append_22) $(am__append_34) \
+ $(am__append_37) $(am__append_40) $(am__append_55)
# This is my own var, used for extra libraries I make that I need installed
EXTRA_INSTALL =
@@ -1400,7 +1720,9 @@ libsysinfo_la_LIBADD = $(NANOSLEEP_LIBS) $(am__append_7)
@MINGW_FALSE@ src/base/atomicops-internals-x86.h
@MINGW_TRUE@SPINLOCK_INCLUDES = src/base/spinlock.h \
-@MINGW_TRUE@ src/base/atomicops.h \
+@MINGW_TRUE@ src/base/spinlock_win32-inl.h \
+@MINGW_TRUE@ src/base/spinlock_linux-inl.h \
+@MINGW_TRUE@ src/base/spinlock_posix-inl.h \
@MINGW_TRUE@ src/base/atomicops-internals-macosx.h \
@MINGW_TRUE@ src/base/atomicops-internals-linuxppc.h \
@MINGW_TRUE@ src/base/atomicops-internals-x86-msvc.h \
@@ -1516,6 +1838,7 @@ S_TCMALLOC_MINIMAL_INCLUDES = src/common.h \
src/page_heap_allocator.h \
src/span.h \
src/static_vars.h \
+ src/symbolize.h \
src/thread_cache.h \
src/stack_trace_table.h \
src/base/thread_annotations.h \
@@ -1539,6 +1862,7 @@ libtcmalloc_minimal_internal_la_SOURCES = src/common.cc \
src/span.cc \
src/stack_trace_table.cc \
src/static_vars.cc \
+ src/symbolize.cc \
src/thread_cache.cc \
src/malloc_hook.cc \
src/malloc_extension.cc \
@@ -1547,6 +1871,7 @@ libtcmalloc_minimal_internal_la_SOURCES = src/common.cc \
# We #define NO_TCMALLOC_SAMPLES, since sampling is turned off for _minimal.
libtcmalloc_minimal_internal_la_CXXFLAGS = -DNO_TCMALLOC_SAMPLES \
+ -DNO_HEAP_CHECK \
$(PTHREAD_CFLAGS) -DNDEBUG \
$(AM_CXXFLAGS) $(NO_EXCEPTIONS)
@@ -1594,10 +1919,10 @@ addressmap_unittest_LDADD = liblogging.la
@MINGW_FALSE@system_alloc_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
@MINGW_FALSE@system_alloc_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS)
@MINGW_FALSE@system_alloc_unittest_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS)
-packed_cache_test_SOURCES = src/tests/packed-cache_test.cc \
- src/packed-cache-inl.h \
- src/base/logging.h
-
+packed_cache_test_SOURCES = src/tests/packed-cache_test.cc
+packed_cache_test_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
+packed_cache_test_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS)
+packed_cache_test_LDADD = $(LIBTCMALLOC_MINIMAL) $(PTHREAD_LIBS)
frag_unittest_SOURCES = src/tests/frag_unittest.cc src/config_for_unittests.h
frag_unittest_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
frag_unittest_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS)
@@ -1672,6 +1997,37 @@ ptmalloc_unittest2_SOURCES = src/tests/ptmalloc/t-test2.c \
ptmalloc_unittest2_CFLAGS = $(PTHREAD_CFLAGS) -DUSE_PTHREADS
ptmalloc_unittest2_LDFLAGS = $(PTHREAD_CFLAGS)
ptmalloc_unittest2_LDADD = $(PTHREAD_LIBS)
+@WITH_DEBUGALLOC_TRUE@libtcmalloc_minimal_debug_la_SOURCES = src/debugallocation.cc \
+@WITH_DEBUGALLOC_TRUE@ $(TCMALLOC_MINIMAL_INCLUDES)
+
+@WITH_DEBUGALLOC_TRUE@libtcmalloc_minimal_debug_la_CXXFLAGS = $(libtcmalloc_minimal_la_CXXFLAGS) \
+@WITH_DEBUGALLOC_TRUE@ -DTCMALLOC_FOR_DEBUGALLOCATION
+
+@WITH_DEBUGALLOC_TRUE@libtcmalloc_minimal_debug_la_LDFLAGS = $(libtcmalloc_minimal_la_LDFLAGS)
+@WITH_DEBUGALLOC_TRUE@libtcmalloc_minimal_debug_la_LIBADD = $(libtcmalloc_minimal_la_LIBADD)
+@WITH_DEBUGALLOC_TRUE@tcmalloc_minimal_debug_unittest_SOURCES = $(tcmalloc_minimal_unittest_SOURCES)
+@WITH_DEBUGALLOC_TRUE@tcmalloc_minimal_debug_unittest_CXXFLAGS = $(tcmalloc_minimal_unittest_CXXFLAGS) \
+@WITH_DEBUGALLOC_TRUE@ -DDEBUGALLOCATION
+
+@WITH_DEBUGALLOC_TRUE@tcmalloc_minimal_debug_unittest_LDFLAGS = $(tcmalloc_minimal_unittest_LDFLAGS)
+@WITH_DEBUGALLOC_TRUE@tcmalloc_minimal_debug_unittest_LDADD = libtcmalloc_minimal_debug.la $(PTHREAD_LIBS)
+@WITH_DEBUGALLOC_TRUE@malloc_extension_debug_test_SOURCES = $(malloc_extension_test_SOURCES)
+@WITH_DEBUGALLOC_TRUE@malloc_extension_debug_test_CXXFLAGS = $(malloc_extension_test_CXXFLAGS)
+@WITH_DEBUGALLOC_TRUE@malloc_extension_debug_test_LDFLAGS = $(malloc_extension_test_LDFLAGS)
+@WITH_DEBUGALLOC_TRUE@malloc_extension_debug_test_LDADD = libtcmalloc_minimal_debug.la $(PTHREAD_LIBS)
+@WITH_DEBUGALLOC_TRUE@memalign_debug_unittest_SOURCES = $(memalign_unittest_SOURCES)
+@WITH_DEBUGALLOC_TRUE@memalign_debug_unittest_CXXFLAGS = $(memalign_unittest_CXXFLAGS)
+@WITH_DEBUGALLOC_TRUE@memalign_debug_unittest_LDFLAGS = $(memalign_unittest_LDFLAGS)
+@WITH_DEBUGALLOC_TRUE@memalign_debug_unittest_LDADD = libtcmalloc_minimal_debug.la $(PTHREAD_LIBS)
+@WITH_DEBUGALLOC_TRUE@realloc_debug_unittest_SOURCES = $(realloc_unittest_SOURCES)
+@WITH_DEBUGALLOC_TRUE@realloc_debug_unittest_CXXFLAGS = $(realloc_unittest_CXXFLAGS)
+@WITH_DEBUGALLOC_TRUE@realloc_debug_unittest_LDFLAGS = $(realloc_unittest_LDFLAGS)
+@WITH_DEBUGALLOC_TRUE@realloc_debug_unittest_LDADD = libtcmalloc_minimal_debug.la $(PTHREAD_LIBS)
+@WITH_DEBUGALLOC_TRUE@debugallocation_test_sh_SOURCES = src/tests/debugallocation_test.sh
+@WITH_DEBUGALLOC_TRUE@debugallocation_test_SOURCES = src/tests/debugallocation_test.cc
+@WITH_DEBUGALLOC_TRUE@debugallocation_test_CXXFLAGS = $(PTHREAD_CFLAGS) $(AM_CXXFLAGS)
+@WITH_DEBUGALLOC_TRUE@debugallocation_test_LDFLAGS = $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS)
+@WITH_DEBUGALLOC_TRUE@debugallocation_test_LDADD = libtcmalloc_minimal_debug.la $(PTHREAD_LIBS)
### ------- tcmalloc (thread-caching malloc + heap profiler + heap checker)
@@ -1702,18 +2058,34 @@ ptmalloc_unittest2_LDADD = $(PTHREAD_LIBS)
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/raw_printer.cc \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/memory_region_map.cc
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_internal_la_CXXFLAGS = $(PTHREAD_CFLAGS) -DNDEBUG \
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(AM_CXXFLAGS) $(NO_EXCEPTIONS)
-
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_internal_la_CXXFLAGS = \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(PTHREAD_CFLAGS) -DNDEBUG \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(AM_CXXFLAGS) \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(NO_EXCEPTIONS) \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__append_28)
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_internal_la_LDFLAGS = $(PTHREAD_CFLAGS)
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_internal_la_LIBADD = $(PTHREAD_LIBS) libstacktrace.la
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_la_SOURCES = \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(TCMALLOC_CC) \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(TCMALLOC_INCLUDES) \
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__append_22)
-@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_la_CXXFLAGS = $(PTHREAD_CFLAGS) -DNDEBUG $(AM_CXXFLAGS)
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__append_27)
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_la_CXXFLAGS = \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(PTHREAD_CFLAGS) -DNDEBUG \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(AM_CXXFLAGS) \
+@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(am__append_29)
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_la_LDFLAGS = $(PTHREAD_CFLAGS)
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_la_LIBADD = $(PTHREAD_LIBS) libtcmalloc_internal.la
+@WITH_HEAP_CHECKER_FALSE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@HEAP_CHECKER_SOURCES =
+
+# heap-checker-bcad is last, in hopes its global ctor will run first.
+# (Note this is added to libtcmalloc.la, not libtcmalloc_internal.la,
+# but that's ok; the internal/external distinction is only useful for
+# cygwin, and cygwin doesn't use HEAP_CHECKER anyway.)
+@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@HEAP_CHECKER_SOURCES = src/base/thread_lister.c \
+@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/base/linuxthreads.cc \
+@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/heap-checker.cc \
+@WITH_HEAP_CHECKER_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/heap-checker-bcad.cc
+
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@LIBTCMALLOC = libtcmalloc.la
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@TCMALLOC_UNITTEST_INCLUDES = src/config_for_unittests.h \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ src/google/malloc_extension.h
@@ -1789,6 +2161,42 @@ ptmalloc_unittest2_LDADD = $(PTHREAD_LIBS)
@WITH_HEAP_CHECKER_TRUE@heap_checker_unittest_LDFLAGS = -g $(PTHREAD_CFLAGS) $(TCMALLOC_FLAGS)
# tcmalloc has to be specified last!
@WITH_HEAP_CHECKER_TRUE@heap_checker_unittest_LDADD = $(PTHREAD_LIBS) liblogging.la $(LIBTCMALLOC)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_debug_la_SOURCES = src/debugallocation.cc $(HEAP_CHECKER_SOURCES) \
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ $(TCMALLOC_INCLUDES)
+
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_debug_la_CXXFLAGS = $(libtcmalloc_la_CXXFLAGS) \
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ -DTCMALLOC_FOR_DEBUGALLOCATION
+
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_debug_la_LDFLAGS = $(libtcmalloc_la_LDFLAGS)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@libtcmalloc_debug_la_LIBADD = $(libtcmalloc_la_LIBADD)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_debug_unittest_SOURCES = $(tcmalloc_unittest_SOURCES)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_debug_unittest_CXXFLAGS = $(tcmalloc_unittest_CXXFLAGS) \
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ -DDEBUGALLOCATION
+
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_debug_unittest_LDFLAGS = $(tcmalloc_unittest_LDFLAGS)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@tcmalloc_debug_unittest_LDADD = libtcmalloc_debug.la $(PTHREAD_LIBS)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampler_debug_test_SOURCES = $(sampler_test_SOURCES)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampler_debug_test_CXXFLAGS = $(samples_test_CXXFLAGS)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampler_debug_test_LDFLAGS = $(sampler_test_LDFLAGS)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampler_debug_test_LDADD = libtcmalloc_debug.la $(PTHREAD_LIBS) -lm
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampling_debug_test_sh_SOURCES = src/tests/sampling_test.sh
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampling_debug_test_SOURCES = $(sampling_test_SOURCES)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampling_debug_test_CXXFLAGS = $(sampling_test_CXXFLAGS)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampling_debug_test_LDFLAGS = $(sampling_test_LDFLAGS)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampling_debug_test_LDADD = libtcmalloc_debug.la $(PTHREAD_LIBS)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@heap_profiler_debug_unittest_sh_SOURCES = src/tests/heap-profiler_unittest.sh
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@heap_profiler_debug_unittest_SOURCES = $(heap_profiler_unittest_SOURCES)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@heap_profiler_debug_unittest_CXXFLAGS = $(heap_profiler_unittest_CXXFLAGS)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@heap_profiler_debug_unittest_LDFLAGS = $(heap_profiler_unittest_LDFLAGS)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@heap_profiler_debug_unittest_LDADD = libtcmalloc_debug.la $(PTHREAD_LIBS)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@heap_checker_debug_unittest_sh_SOURCES = src/tests/heap-checker_unittest.sh
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@heap_checker_debug_unittest_SOURCES = $(heap_checker_unittest_SOURCES)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@heap_checker_debug_unittest_CXXFLAGS = $(heap_checker_unittest_CXXFLAGS)
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@heap_checker_debug_unittest_LDFLAGS = $(heap_checker_unittest_LDFLAGS)
+# tcmalloc has to be specified last!
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@heap_checker_debug_unittest_LDADD = $(PTHREAD_LIBS) liblogging.la \
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@ libtcmalloc_debug.la
+
### ------- CPU profiler
@@ -1989,10 +2397,14 @@ libtcmalloc.la: $(libtcmalloc_la_OBJECTS) $(libtcmalloc_la_DEPENDENCIES)
$(CXXLINK) $(am_libtcmalloc_la_rpath) $(libtcmalloc_la_LDFLAGS) $(libtcmalloc_la_OBJECTS) $(libtcmalloc_la_LIBADD) $(LIBS)
libtcmalloc_and_profiler.la: $(libtcmalloc_and_profiler_la_OBJECTS) $(libtcmalloc_and_profiler_la_DEPENDENCIES)
$(CXXLINK) $(am_libtcmalloc_and_profiler_la_rpath) $(libtcmalloc_and_profiler_la_LDFLAGS) $(libtcmalloc_and_profiler_la_OBJECTS) $(libtcmalloc_and_profiler_la_LIBADD) $(LIBS)
+libtcmalloc_debug.la: $(libtcmalloc_debug_la_OBJECTS) $(libtcmalloc_debug_la_DEPENDENCIES)
+ $(CXXLINK) $(am_libtcmalloc_debug_la_rpath) $(libtcmalloc_debug_la_LDFLAGS) $(libtcmalloc_debug_la_OBJECTS) $(libtcmalloc_debug_la_LIBADD) $(LIBS)
libtcmalloc_internal.la: $(libtcmalloc_internal_la_OBJECTS) $(libtcmalloc_internal_la_DEPENDENCIES)
$(CXXLINK) $(am_libtcmalloc_internal_la_rpath) $(libtcmalloc_internal_la_LDFLAGS) $(libtcmalloc_internal_la_OBJECTS) $(libtcmalloc_internal_la_LIBADD) $(LIBS)
libtcmalloc_minimal.la: $(libtcmalloc_minimal_la_OBJECTS) $(libtcmalloc_minimal_la_DEPENDENCIES)
$(CXXLINK) -rpath $(libdir) $(libtcmalloc_minimal_la_LDFLAGS) $(libtcmalloc_minimal_la_OBJECTS) $(libtcmalloc_minimal_la_LIBADD) $(LIBS)
+libtcmalloc_minimal_debug.la: $(libtcmalloc_minimal_debug_la_OBJECTS) $(libtcmalloc_minimal_debug_la_DEPENDENCIES)
+ $(CXXLINK) $(am_libtcmalloc_minimal_debug_la_rpath) $(libtcmalloc_minimal_debug_la_LDFLAGS) $(libtcmalloc_minimal_debug_la_OBJECTS) $(libtcmalloc_minimal_debug_la_LIBADD) $(LIBS)
libtcmalloc_minimal_internal.la: $(libtcmalloc_minimal_internal_la_OBJECTS) $(libtcmalloc_minimal_internal_la_DEPENDENCIES)
$(CXXLINK) $(libtcmalloc_minimal_internal_la_LDFLAGS) $(libtcmalloc_minimal_internal_la_OBJECTS) $(libtcmalloc_minimal_internal_la_LIBADD) $(LIBS)
libwindows.la: $(libwindows_la_OBJECTS) $(libwindows_la_DEPENDENCIES)
@@ -2038,6 +2450,12 @@ addressmap_unittest$(EXEEXT): $(addressmap_unittest_OBJECTS) $(addressmap_unitte
atomicops_unittest$(EXEEXT): $(atomicops_unittest_OBJECTS) $(atomicops_unittest_DEPENDENCIES)
@rm -f atomicops_unittest$(EXEEXT)
$(CXXLINK) $(atomicops_unittest_LDFLAGS) $(atomicops_unittest_OBJECTS) $(atomicops_unittest_LDADD) $(LIBS)
+debugallocation_test$(EXEEXT): $(debugallocation_test_OBJECTS) $(debugallocation_test_DEPENDENCIES)
+ @rm -f debugallocation_test$(EXEEXT)
+ $(CXXLINK) $(debugallocation_test_LDFLAGS) $(debugallocation_test_OBJECTS) $(debugallocation_test_LDADD) $(LIBS)
+@WITH_DEBUGALLOC_FALSE@debugallocation_test.sh$(EXEEXT): $(debugallocation_test_sh_OBJECTS) $(debugallocation_test_sh_DEPENDENCIES)
+@WITH_DEBUGALLOC_FALSE@ @rm -f debugallocation_test.sh$(EXEEXT)
+@WITH_DEBUGALLOC_FALSE@ $(LINK) $(debugallocation_test_sh_LDFLAGS) $(debugallocation_test_sh_OBJECTS) $(debugallocation_test_sh_LDADD) $(LIBS)
frag_unittest$(EXEEXT): $(frag_unittest_OBJECTS) $(frag_unittest_DEPENDENCIES)
@rm -f frag_unittest$(EXEEXT)
$(CXXLINK) $(frag_unittest_LDFLAGS) $(frag_unittest_OBJECTS) $(frag_unittest_LDADD) $(LIBS)
@@ -2047,12 +2465,30 @@ getpc_test$(EXEEXT): $(getpc_test_OBJECTS) $(getpc_test_DEPENDENCIES)
@WITH_HEAP_CHECKER_FALSE@heap-checker-death_unittest.sh$(EXEEXT): $(heap_checker_death_unittest_sh_OBJECTS) $(heap_checker_death_unittest_sh_DEPENDENCIES)
@WITH_HEAP_CHECKER_FALSE@ @rm -f heap-checker-death_unittest.sh$(EXEEXT)
@WITH_HEAP_CHECKER_FALSE@ $(LINK) $(heap_checker_death_unittest_sh_LDFLAGS) $(heap_checker_death_unittest_sh_OBJECTS) $(heap_checker_death_unittest_sh_LDADD) $(LIBS)
+heap-checker_debug_unittest$(EXEEXT): $(heap_checker_debug_unittest_OBJECTS) $(heap_checker_debug_unittest_DEPENDENCIES)
+ @rm -f heap-checker_debug_unittest$(EXEEXT)
+ $(CXXLINK) $(heap_checker_debug_unittest_LDFLAGS) $(heap_checker_debug_unittest_OBJECTS) $(heap_checker_debug_unittest_LDADD) $(LIBS)
+@WITH_DEBUGALLOC_FALSE@heap-checker_debug_unittest.sh$(EXEEXT): $(heap_checker_debug_unittest_sh_OBJECTS) $(heap_checker_debug_unittest_sh_DEPENDENCIES)
+@WITH_DEBUGALLOC_FALSE@ @rm -f heap-checker_debug_unittest.sh$(EXEEXT)
+@WITH_DEBUGALLOC_FALSE@ $(LINK) $(heap_checker_debug_unittest_sh_LDFLAGS) $(heap_checker_debug_unittest_sh_OBJECTS) $(heap_checker_debug_unittest_sh_LDADD) $(LIBS)
+@WITH_HEAP_CHECKER_FALSE@heap-checker_debug_unittest.sh$(EXEEXT): $(heap_checker_debug_unittest_sh_OBJECTS) $(heap_checker_debug_unittest_sh_DEPENDENCIES)
+@WITH_HEAP_CHECKER_FALSE@ @rm -f heap-checker_debug_unittest.sh$(EXEEXT)
+@WITH_HEAP_CHECKER_FALSE@ $(LINK) $(heap_checker_debug_unittest_sh_LDFLAGS) $(heap_checker_debug_unittest_sh_OBJECTS) $(heap_checker_debug_unittest_sh_LDADD) $(LIBS)
heap-checker_unittest$(EXEEXT): $(heap_checker_unittest_OBJECTS) $(heap_checker_unittest_DEPENDENCIES)
@rm -f heap-checker_unittest$(EXEEXT)
$(CXXLINK) $(heap_checker_unittest_LDFLAGS) $(heap_checker_unittest_OBJECTS) $(heap_checker_unittest_LDADD) $(LIBS)
@WITH_HEAP_CHECKER_FALSE@heap-checker_unittest.sh$(EXEEXT): $(heap_checker_unittest_sh_OBJECTS) $(heap_checker_unittest_sh_DEPENDENCIES)
@WITH_HEAP_CHECKER_FALSE@ @rm -f heap-checker_unittest.sh$(EXEEXT)
@WITH_HEAP_CHECKER_FALSE@ $(LINK) $(heap_checker_unittest_sh_LDFLAGS) $(heap_checker_unittest_sh_OBJECTS) $(heap_checker_unittest_sh_LDADD) $(LIBS)
+heap-profiler_debug_unittest$(EXEEXT): $(heap_profiler_debug_unittest_OBJECTS) $(heap_profiler_debug_unittest_DEPENDENCIES)
+ @rm -f heap-profiler_debug_unittest$(EXEEXT)
+ $(CXXLINK) $(heap_profiler_debug_unittest_LDFLAGS) $(heap_profiler_debug_unittest_OBJECTS) $(heap_profiler_debug_unittest_LDADD) $(LIBS)
+@WITH_DEBUGALLOC_FALSE@heap-profiler_debug_unittest.sh$(EXEEXT): $(heap_profiler_debug_unittest_sh_OBJECTS) $(heap_profiler_debug_unittest_sh_DEPENDENCIES)
+@WITH_DEBUGALLOC_FALSE@ @rm -f heap-profiler_debug_unittest.sh$(EXEEXT)
+@WITH_DEBUGALLOC_FALSE@ $(LINK) $(heap_profiler_debug_unittest_sh_LDFLAGS) $(heap_profiler_debug_unittest_sh_OBJECTS) $(heap_profiler_debug_unittest_sh_LDADD) $(LIBS)
+@WITH_HEAP_PROFILER_FALSE@heap-profiler_debug_unittest.sh$(EXEEXT): $(heap_profiler_debug_unittest_sh_OBJECTS) $(heap_profiler_debug_unittest_sh_DEPENDENCIES)
+@WITH_HEAP_PROFILER_FALSE@ @rm -f heap-profiler_debug_unittest.sh$(EXEEXT)
+@WITH_HEAP_PROFILER_FALSE@ $(LINK) $(heap_profiler_debug_unittest_sh_LDFLAGS) $(heap_profiler_debug_unittest_sh_OBJECTS) $(heap_profiler_debug_unittest_sh_LDADD) $(LIBS)
heap-profiler_unittest$(EXEEXT): $(heap_profiler_unittest_OBJECTS) $(heap_profiler_unittest_DEPENDENCIES)
@rm -f heap-profiler_unittest$(EXEEXT)
$(CXXLINK) $(heap_profiler_unittest_LDFLAGS) $(heap_profiler_unittest_OBJECTS) $(heap_profiler_unittest_LDADD) $(LIBS)
@@ -2062,6 +2498,9 @@ heap-profiler_unittest$(EXEEXT): $(heap_profiler_unittest_OBJECTS) $(heap_profil
low_level_alloc_unittest$(EXEEXT): $(low_level_alloc_unittest_OBJECTS) $(low_level_alloc_unittest_DEPENDENCIES)
@rm -f low_level_alloc_unittest$(EXEEXT)
$(CXXLINK) $(low_level_alloc_unittest_LDFLAGS) $(low_level_alloc_unittest_OBJECTS) $(low_level_alloc_unittest_LDADD) $(LIBS)
+malloc_extension_debug_test$(EXEEXT): $(malloc_extension_debug_test_OBJECTS) $(malloc_extension_debug_test_DEPENDENCIES)
+ @rm -f malloc_extension_debug_test$(EXEEXT)
+ $(CXXLINK) $(malloc_extension_debug_test_LDFLAGS) $(malloc_extension_debug_test_OBJECTS) $(malloc_extension_debug_test_LDADD) $(LIBS)
malloc_extension_test$(EXEEXT): $(malloc_extension_test_OBJECTS) $(malloc_extension_test_DEPENDENCIES)
@rm -f malloc_extension_test$(EXEEXT)
$(CXXLINK) $(malloc_extension_test_LDFLAGS) $(malloc_extension_test_OBJECTS) $(malloc_extension_test_LDADD) $(LIBS)
@@ -2071,6 +2510,9 @@ markidle_unittest$(EXEEXT): $(markidle_unittest_OBJECTS) $(markidle_unittest_DEP
@MINGW_TRUE@maybe_threads_unittest.sh$(EXEEXT): $(maybe_threads_unittest_sh_OBJECTS) $(maybe_threads_unittest_sh_DEPENDENCIES)
@MINGW_TRUE@ @rm -f maybe_threads_unittest.sh$(EXEEXT)
@MINGW_TRUE@ $(LINK) $(maybe_threads_unittest_sh_LDFLAGS) $(maybe_threads_unittest_sh_OBJECTS) $(maybe_threads_unittest_sh_LDADD) $(LIBS)
+memalign_debug_unittest$(EXEEXT): $(memalign_debug_unittest_OBJECTS) $(memalign_debug_unittest_DEPENDENCIES)
+ @rm -f memalign_debug_unittest$(EXEEXT)
+ $(CXXLINK) $(memalign_debug_unittest_LDFLAGS) $(memalign_debug_unittest_OBJECTS) $(memalign_debug_unittest_LDADD) $(LIBS)
memalign_unittest$(EXEEXT): $(memalign_unittest_OBJECTS) $(memalign_unittest_DEPENDENCIES)
@rm -f memalign_unittest$(EXEEXT)
$(CXXLINK) $(memalign_unittest_LDFLAGS) $(memalign_unittest_OBJECTS) $(memalign_unittest_LDADD) $(LIBS)
@@ -2110,12 +2552,27 @@ ptmalloc_unittest2$(EXEEXT): $(ptmalloc_unittest2_OBJECTS) $(ptmalloc_unittest2_
raw_printer_test$(EXEEXT): $(raw_printer_test_OBJECTS) $(raw_printer_test_DEPENDENCIES)
@rm -f raw_printer_test$(EXEEXT)
$(CXXLINK) $(raw_printer_test_LDFLAGS) $(raw_printer_test_OBJECTS) $(raw_printer_test_LDADD) $(LIBS)
+realloc_debug_unittest$(EXEEXT): $(realloc_debug_unittest_OBJECTS) $(realloc_debug_unittest_DEPENDENCIES)
+ @rm -f realloc_debug_unittest$(EXEEXT)
+ $(CXXLINK) $(realloc_debug_unittest_LDFLAGS) $(realloc_debug_unittest_OBJECTS) $(realloc_debug_unittest_LDADD) $(LIBS)
realloc_unittest$(EXEEXT): $(realloc_unittest_OBJECTS) $(realloc_unittest_DEPENDENCIES)
@rm -f realloc_unittest$(EXEEXT)
$(CXXLINK) $(realloc_unittest_LDFLAGS) $(realloc_unittest_OBJECTS) $(realloc_unittest_LDADD) $(LIBS)
+sampler_debug_test$(EXEEXT): $(sampler_debug_test_OBJECTS) $(sampler_debug_test_DEPENDENCIES)
+ @rm -f sampler_debug_test$(EXEEXT)
+ $(CXXLINK) $(sampler_debug_test_LDFLAGS) $(sampler_debug_test_OBJECTS) $(sampler_debug_test_LDADD) $(LIBS)
sampler_test$(EXEEXT): $(sampler_test_OBJECTS) $(sampler_test_DEPENDENCIES)
@rm -f sampler_test$(EXEEXT)
$(CXXLINK) $(sampler_test_LDFLAGS) $(sampler_test_OBJECTS) $(sampler_test_LDADD) $(LIBS)
+sampling_debug_test$(EXEEXT): $(sampling_debug_test_OBJECTS) $(sampling_debug_test_DEPENDENCIES)
+ @rm -f sampling_debug_test$(EXEEXT)
+ $(CXXLINK) $(sampling_debug_test_LDFLAGS) $(sampling_debug_test_OBJECTS) $(sampling_debug_test_LDADD) $(LIBS)
+@WITH_DEBUGALLOC_FALSE@sampling_debug_test.sh$(EXEEXT): $(sampling_debug_test_sh_OBJECTS) $(sampling_debug_test_sh_DEPENDENCIES)
+@WITH_DEBUGALLOC_FALSE@ @rm -f sampling_debug_test.sh$(EXEEXT)
+@WITH_DEBUGALLOC_FALSE@ $(LINK) $(sampling_debug_test_sh_LDFLAGS) $(sampling_debug_test_sh_OBJECTS) $(sampling_debug_test_sh_LDADD) $(LIBS)
+@WITH_HEAP_PROFILER_OR_CHECKER_FALSE@sampling_debug_test.sh$(EXEEXT): $(sampling_debug_test_sh_OBJECTS) $(sampling_debug_test_sh_DEPENDENCIES)
+@WITH_HEAP_PROFILER_OR_CHECKER_FALSE@ @rm -f sampling_debug_test.sh$(EXEEXT)
+@WITH_HEAP_PROFILER_OR_CHECKER_FALSE@ $(LINK) $(sampling_debug_test_sh_LDFLAGS) $(sampling_debug_test_sh_OBJECTS) $(sampling_debug_test_sh_LDADD) $(LIBS)
sampling_test$(EXEEXT): $(sampling_test_OBJECTS) $(sampling_test_DEPENDENCIES)
@rm -f sampling_test$(EXEEXT)
$(CXXLINK) $(sampling_test_LDFLAGS) $(sampling_test_OBJECTS) $(sampling_test_LDADD) $(LIBS)
@@ -2137,9 +2594,15 @@ tcmalloc_and_profiler_unittest$(EXEEXT): $(tcmalloc_and_profiler_unittest_OBJECT
tcmalloc_both_unittest$(EXEEXT): $(tcmalloc_both_unittest_OBJECTS) $(tcmalloc_both_unittest_DEPENDENCIES)
@rm -f tcmalloc_both_unittest$(EXEEXT)
$(CXXLINK) $(tcmalloc_both_unittest_LDFLAGS) $(tcmalloc_both_unittest_OBJECTS) $(tcmalloc_both_unittest_LDADD) $(LIBS)
+tcmalloc_debug_unittest$(EXEEXT): $(tcmalloc_debug_unittest_OBJECTS) $(tcmalloc_debug_unittest_DEPENDENCIES)
+ @rm -f tcmalloc_debug_unittest$(EXEEXT)
+ $(CXXLINK) $(tcmalloc_debug_unittest_LDFLAGS) $(tcmalloc_debug_unittest_OBJECTS) $(tcmalloc_debug_unittest_LDADD) $(LIBS)
tcmalloc_large_unittest$(EXEEXT): $(tcmalloc_large_unittest_OBJECTS) $(tcmalloc_large_unittest_DEPENDENCIES)
@rm -f tcmalloc_large_unittest$(EXEEXT)
$(CXXLINK) $(tcmalloc_large_unittest_LDFLAGS) $(tcmalloc_large_unittest_OBJECTS) $(tcmalloc_large_unittest_LDADD) $(LIBS)
+tcmalloc_minimal_debug_unittest$(EXEEXT): $(tcmalloc_minimal_debug_unittest_OBJECTS) $(tcmalloc_minimal_debug_unittest_DEPENDENCIES)
+ @rm -f tcmalloc_minimal_debug_unittest$(EXEEXT)
+ $(CXXLINK) $(tcmalloc_minimal_debug_unittest_LDFLAGS) $(tcmalloc_minimal_debug_unittest_OBJECTS) $(tcmalloc_minimal_debug_unittest_LDADD) $(LIBS)
tcmalloc_minimal_large_unittest$(EXEEXT): $(tcmalloc_minimal_large_unittest_OBJECTS) $(tcmalloc_minimal_large_unittest_DEPENDENCIES)
@rm -f tcmalloc_minimal_large_unittest$(EXEEXT)
$(CXXLINK) $(tcmalloc_minimal_large_unittest_LDFLAGS) $(tcmalloc_minimal_large_unittest_OBJECTS) $(tcmalloc_minimal_large_unittest_LDADD) $(LIBS)
@@ -2181,10 +2644,13 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/addressmap_unittest-addressmap_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atomicops-internals-x86.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atomicops_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debugallocation_test-debugallocation_test.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dynamic_annotations.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/frag_unittest-frag_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getpc_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/heap_checker_debug_unittest-heap-checker_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/heap_checker_unittest-heap-checker_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/heap_profiler_debug_unittest-heap-profiler_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/heap_profiler_unittest-heap-profiler_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ia32_modrm_map.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ia32_opcode_map.Plo@am__quote@
@@ -2195,6 +2661,10 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_and_profiler_la-profiledata.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_and_profiler_la-profiler.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_and_profiler_la-tcmalloc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_debug_la-debugallocation.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_debug_la-heap-checker-bcad.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_debug_la-heap-checker.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_debug_la-linuxthreads.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_internal_la-central_freelist.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_internal_la-common.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_internal_la-heap-profile-table.Plo@am__quote@
@@ -2212,12 +2682,14 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_internal_la-span.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_internal_la-stack_trace_table.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_internal_la-static_vars.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_internal_la-symbolize.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_internal_la-system-alloc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_internal_la-thread_cache.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_la-heap-checker-bcad.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_la-heap-checker.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_la-linuxthreads.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_la-tcmalloc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_minimal_debug_la-debugallocation.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_minimal_internal_la-central_freelist.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_minimal_internal_la-common.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_minimal_internal_la-internal_logging.Plo@am__quote@
@@ -2230,6 +2702,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_minimal_internal_la-span.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_minimal_internal_la-stack_trace_table.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_minimal_internal_la-static_vars.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_minimal_internal_la-symbolize.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_minimal_internal_la-system-alloc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_minimal_internal_la-thread_cache.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtcmalloc_minimal_la-tcmalloc.Plo@am__quote@
@@ -2237,13 +2710,16 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/low_level_alloc_unittest-low_level_alloc.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/low_level_alloc_unittest-low_level_alloc_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/low_level_alloc_unittest-malloc_hook.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/malloc_extension_debug_test-malloc_extension_test.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/malloc_extension_test-malloc_extension_test.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/markidle_unittest-markidle_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/markidle_unittest-testutil.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memalign_debug_unittest-memalign_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memalign_debug_unittest-testutil.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memalign_unittest-memalign_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memalign_unittest-testutil.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mini_disassembler.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/packed-cache_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/packed_cache_test-packed-cache_test.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pagemap_unittest-pagemap_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/patch_functions.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/port.Plo@am__quote@
@@ -2265,8 +2741,11 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ptmalloc_unittest1-t-test1.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ptmalloc_unittest2-t-test2.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/raw_printer_test-raw_printer_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/realloc_debug_unittest-realloc_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/realloc_unittest-realloc_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sampler_debug_test-sampler_test.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sampler_test-sampler_test.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sampling_debug_test-sampling_test.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sampling_test-sampling_test.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spinlock.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stack_trace_table_test-stack_trace_table_test.Po@am__quote@
@@ -2279,7 +2758,11 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcmalloc_and_profiler_unittest-testutil.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcmalloc_both_unittest-tcmalloc_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcmalloc_both_unittest-testutil.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcmalloc_debug_unittest-tcmalloc_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcmalloc_debug_unittest-testutil.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcmalloc_large_unittest-tcmalloc_large_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcmalloc_minimal_debug_unittest-tcmalloc_unittest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcmalloc_minimal_debug_unittest-testutil.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcmalloc_minimal_unittest-tcmalloc_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcmalloc_minimal_unittest-testutil.Po@am__quote@
@@ -2521,6 +3004,34 @@ libtcmalloc_and_profiler_la-profiledata.lo: src/profiledata.cc
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_and_profiler_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_and_profiler_la-profiledata.lo `test -f 'src/profiledata.cc' || echo '$(srcdir)/'`src/profiledata.cc
+libtcmalloc_debug_la-debugallocation.lo: src/debugallocation.cc
+@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_debug_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_debug_la-debugallocation.lo -MD -MP -MF "$(DEPDIR)/libtcmalloc_debug_la-debugallocation.Tpo" -c -o libtcmalloc_debug_la-debugallocation.lo `test -f 'src/debugallocation.cc' || echo '$(srcdir)/'`src/debugallocation.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libtcmalloc_debug_la-debugallocation.Tpo" "$(DEPDIR)/libtcmalloc_debug_la-debugallocation.Plo"; else rm -f "$(DEPDIR)/libtcmalloc_debug_la-debugallocation.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/debugallocation.cc' object='libtcmalloc_debug_la-debugallocation.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_debug_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_debug_la-debugallocation.lo `test -f 'src/debugallocation.cc' || echo '$(srcdir)/'`src/debugallocation.cc
+
+libtcmalloc_debug_la-linuxthreads.lo: src/base/linuxthreads.cc
+@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_debug_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_debug_la-linuxthreads.lo -MD -MP -MF "$(DEPDIR)/libtcmalloc_debug_la-linuxthreads.Tpo" -c -o libtcmalloc_debug_la-linuxthreads.lo `test -f 'src/base/linuxthreads.cc' || echo '$(srcdir)/'`src/base/linuxthreads.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libtcmalloc_debug_la-linuxthreads.Tpo" "$(DEPDIR)/libtcmalloc_debug_la-linuxthreads.Plo"; else rm -f "$(DEPDIR)/libtcmalloc_debug_la-linuxthreads.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/base/linuxthreads.cc' object='libtcmalloc_debug_la-linuxthreads.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_debug_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_debug_la-linuxthreads.lo `test -f 'src/base/linuxthreads.cc' || echo '$(srcdir)/'`src/base/linuxthreads.cc
+
+libtcmalloc_debug_la-heap-checker.lo: src/heap-checker.cc
+@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_debug_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_debug_la-heap-checker.lo -MD -MP -MF "$(DEPDIR)/libtcmalloc_debug_la-heap-checker.Tpo" -c -o libtcmalloc_debug_la-heap-checker.lo `test -f 'src/heap-checker.cc' || echo '$(srcdir)/'`src/heap-checker.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libtcmalloc_debug_la-heap-checker.Tpo" "$(DEPDIR)/libtcmalloc_debug_la-heap-checker.Plo"; else rm -f "$(DEPDIR)/libtcmalloc_debug_la-heap-checker.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/heap-checker.cc' object='libtcmalloc_debug_la-heap-checker.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_debug_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_debug_la-heap-checker.lo `test -f 'src/heap-checker.cc' || echo '$(srcdir)/'`src/heap-checker.cc
+
+libtcmalloc_debug_la-heap-checker-bcad.lo: src/heap-checker-bcad.cc
+@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_debug_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_debug_la-heap-checker-bcad.lo -MD -MP -MF "$(DEPDIR)/libtcmalloc_debug_la-heap-checker-bcad.Tpo" -c -o libtcmalloc_debug_la-heap-checker-bcad.lo `test -f 'src/heap-checker-bcad.cc' || echo '$(srcdir)/'`src/heap-checker-bcad.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libtcmalloc_debug_la-heap-checker-bcad.Tpo" "$(DEPDIR)/libtcmalloc_debug_la-heap-checker-bcad.Plo"; else rm -f "$(DEPDIR)/libtcmalloc_debug_la-heap-checker-bcad.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/heap-checker-bcad.cc' object='libtcmalloc_debug_la-heap-checker-bcad.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_debug_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_debug_la-heap-checker-bcad.lo `test -f 'src/heap-checker-bcad.cc' || echo '$(srcdir)/'`src/heap-checker-bcad.cc
+
libtcmalloc_internal_la-common.lo: src/common.cc
@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_internal_la-common.lo -MD -MP -MF "$(DEPDIR)/libtcmalloc_internal_la-common.Tpo" -c -o libtcmalloc_internal_la-common.lo `test -f 'src/common.cc' || echo '$(srcdir)/'`src/common.cc; \
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libtcmalloc_internal_la-common.Tpo" "$(DEPDIR)/libtcmalloc_internal_la-common.Plo"; else rm -f "$(DEPDIR)/libtcmalloc_internal_la-common.Tpo"; exit 1; fi
@@ -2591,6 +3102,13 @@ libtcmalloc_internal_la-static_vars.lo: src/static_vars.cc
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_internal_la-static_vars.lo `test -f 'src/static_vars.cc' || echo '$(srcdir)/'`src/static_vars.cc
+libtcmalloc_internal_la-symbolize.lo: src/symbolize.cc
+@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_internal_la-symbolize.lo -MD -MP -MF "$(DEPDIR)/libtcmalloc_internal_la-symbolize.Tpo" -c -o libtcmalloc_internal_la-symbolize.lo `test -f 'src/symbolize.cc' || echo '$(srcdir)/'`src/symbolize.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libtcmalloc_internal_la-symbolize.Tpo" "$(DEPDIR)/libtcmalloc_internal_la-symbolize.Plo"; else rm -f "$(DEPDIR)/libtcmalloc_internal_la-symbolize.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/symbolize.cc' object='libtcmalloc_internal_la-symbolize.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_internal_la-symbolize.lo `test -f 'src/symbolize.cc' || echo '$(srcdir)/'`src/symbolize.cc
+
libtcmalloc_internal_la-thread_cache.lo: src/thread_cache.cc
@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_internal_la-thread_cache.lo -MD -MP -MF "$(DEPDIR)/libtcmalloc_internal_la-thread_cache.Tpo" -c -o libtcmalloc_internal_la-thread_cache.lo `test -f 'src/thread_cache.cc' || echo '$(srcdir)/'`src/thread_cache.cc; \
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libtcmalloc_internal_la-thread_cache.Tpo" "$(DEPDIR)/libtcmalloc_internal_la-thread_cache.Plo"; else rm -f "$(DEPDIR)/libtcmalloc_internal_la-thread_cache.Tpo"; exit 1; fi
@@ -2661,6 +3179,13 @@ libtcmalloc_minimal_la-tcmalloc.lo: src/tcmalloc.cc
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_minimal_la-tcmalloc.lo `test -f 'src/tcmalloc.cc' || echo '$(srcdir)/'`src/tcmalloc.cc
+libtcmalloc_minimal_debug_la-debugallocation.lo: src/debugallocation.cc
+@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_debug_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_minimal_debug_la-debugallocation.lo -MD -MP -MF "$(DEPDIR)/libtcmalloc_minimal_debug_la-debugallocation.Tpo" -c -o libtcmalloc_minimal_debug_la-debugallocation.lo `test -f 'src/debugallocation.cc' || echo '$(srcdir)/'`src/debugallocation.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libtcmalloc_minimal_debug_la-debugallocation.Tpo" "$(DEPDIR)/libtcmalloc_minimal_debug_la-debugallocation.Plo"; else rm -f "$(DEPDIR)/libtcmalloc_minimal_debug_la-debugallocation.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/debugallocation.cc' object='libtcmalloc_minimal_debug_la-debugallocation.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_debug_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_minimal_debug_la-debugallocation.lo `test -f 'src/debugallocation.cc' || echo '$(srcdir)/'`src/debugallocation.cc
+
libtcmalloc_minimal_internal_la-common.lo: src/common.cc
@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_minimal_internal_la-common.lo -MD -MP -MF "$(DEPDIR)/libtcmalloc_minimal_internal_la-common.Tpo" -c -o libtcmalloc_minimal_internal_la-common.lo `test -f 'src/common.cc' || echo '$(srcdir)/'`src/common.cc; \
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libtcmalloc_minimal_internal_la-common.Tpo" "$(DEPDIR)/libtcmalloc_minimal_internal_la-common.Plo"; else rm -f "$(DEPDIR)/libtcmalloc_minimal_internal_la-common.Tpo"; exit 1; fi
@@ -2731,6 +3256,13 @@ libtcmalloc_minimal_internal_la-static_vars.lo: src/static_vars.cc
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_minimal_internal_la-static_vars.lo `test -f 'src/static_vars.cc' || echo '$(srcdir)/'`src/static_vars.cc
+libtcmalloc_minimal_internal_la-symbolize.lo: src/symbolize.cc
+@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_minimal_internal_la-symbolize.lo -MD -MP -MF "$(DEPDIR)/libtcmalloc_minimal_internal_la-symbolize.Tpo" -c -o libtcmalloc_minimal_internal_la-symbolize.lo `test -f 'src/symbolize.cc' || echo '$(srcdir)/'`src/symbolize.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libtcmalloc_minimal_internal_la-symbolize.Tpo" "$(DEPDIR)/libtcmalloc_minimal_internal_la-symbolize.Plo"; else rm -f "$(DEPDIR)/libtcmalloc_minimal_internal_la-symbolize.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/symbolize.cc' object='libtcmalloc_minimal_internal_la-symbolize.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -c -o libtcmalloc_minimal_internal_la-symbolize.lo `test -f 'src/symbolize.cc' || echo '$(srcdir)/'`src/symbolize.cc
+
libtcmalloc_minimal_internal_la-thread_cache.lo: src/thread_cache.cc
@am__fastdepCXX_TRUE@ if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtcmalloc_minimal_internal_la_CXXFLAGS) $(CXXFLAGS) -MT libtcmalloc_minimal_internal_la-thread_cache.lo -MD -MP -MF "$(DEPDIR)/libtcmalloc_minimal_internal_la-thread_cache.Tpo" -c -o libtcmalloc_minimal_internal_la-thread_cache.lo `test -f 'src/thread_cache.cc' || echo '$(srcdir)/'`src/thread_cache.cc; \
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/libtcmalloc_minimal_internal_la-thread_cache.Tpo" "$(DEPDIR)/libtcmalloc_minimal_internal_la-thread_cache.Plo"; else rm -f "$(DEPDIR)/libtcmalloc_minimal_internal_la-thread_cache.Tpo"; exit 1; fi
@@ -2836,6 +3368,20 @@ atomicops_unittest.obj: src/tests/atomicops_unittest.cc
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o atomicops_unittest.obj `if test -f 'src/tests/atomicops_unittest.cc'; then $(CYGPATH_W) 'src/tests/atomicops_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/atomicops_unittest.cc'; fi`
+debugallocation_test-debugallocation_test.o: src/tests/debugallocation_test.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(debugallocation_test_CXXFLAGS) $(CXXFLAGS) -MT debugallocation_test-debugallocation_test.o -MD -MP -MF "$(DEPDIR)/debugallocation_test-debugallocation_test.Tpo" -c -o debugallocation_test-debugallocation_test.o `test -f 'src/tests/debugallocation_test.cc' || echo '$(srcdir)/'`src/tests/debugallocation_test.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/debugallocation_test-debugallocation_test.Tpo" "$(DEPDIR)/debugallocation_test-debugallocation_test.Po"; else rm -f "$(DEPDIR)/debugallocation_test-debugallocation_test.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/debugallocation_test.cc' object='debugallocation_test-debugallocation_test.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(debugallocation_test_CXXFLAGS) $(CXXFLAGS) -c -o debugallocation_test-debugallocation_test.o `test -f 'src/tests/debugallocation_test.cc' || echo '$(srcdir)/'`src/tests/debugallocation_test.cc
+
+debugallocation_test-debugallocation_test.obj: src/tests/debugallocation_test.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(debugallocation_test_CXXFLAGS) $(CXXFLAGS) -MT debugallocation_test-debugallocation_test.obj -MD -MP -MF "$(DEPDIR)/debugallocation_test-debugallocation_test.Tpo" -c -o debugallocation_test-debugallocation_test.obj `if test -f 'src/tests/debugallocation_test.cc'; then $(CYGPATH_W) 'src/tests/debugallocation_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/debugallocation_test.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/debugallocation_test-debugallocation_test.Tpo" "$(DEPDIR)/debugallocation_test-debugallocation_test.Po"; else rm -f "$(DEPDIR)/debugallocation_test-debugallocation_test.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/debugallocation_test.cc' object='debugallocation_test-debugallocation_test.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(debugallocation_test_CXXFLAGS) $(CXXFLAGS) -c -o debugallocation_test-debugallocation_test.obj `if test -f 'src/tests/debugallocation_test.cc'; then $(CYGPATH_W) 'src/tests/debugallocation_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/debugallocation_test.cc'; fi`
+
frag_unittest-frag_unittest.o: src/tests/frag_unittest.cc
@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(frag_unittest_CXXFLAGS) $(CXXFLAGS) -MT frag_unittest-frag_unittest.o -MD -MP -MF "$(DEPDIR)/frag_unittest-frag_unittest.Tpo" -c -o frag_unittest-frag_unittest.o `test -f 'src/tests/frag_unittest.cc' || echo '$(srcdir)/'`src/tests/frag_unittest.cc; \
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/frag_unittest-frag_unittest.Tpo" "$(DEPDIR)/frag_unittest-frag_unittest.Po"; else rm -f "$(DEPDIR)/frag_unittest-frag_unittest.Tpo"; exit 1; fi
@@ -2864,6 +3410,20 @@ getpc_test.obj: src/tests/getpc_test.cc
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o getpc_test.obj `if test -f 'src/tests/getpc_test.cc'; then $(CYGPATH_W) 'src/tests/getpc_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/getpc_test.cc'; fi`
+heap_checker_debug_unittest-heap-checker_unittest.o: src/tests/heap-checker_unittest.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_checker_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT heap_checker_debug_unittest-heap-checker_unittest.o -MD -MP -MF "$(DEPDIR)/heap_checker_debug_unittest-heap-checker_unittest.Tpo" -c -o heap_checker_debug_unittest-heap-checker_unittest.o `test -f 'src/tests/heap-checker_unittest.cc' || echo '$(srcdir)/'`src/tests/heap-checker_unittest.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/heap_checker_debug_unittest-heap-checker_unittest.Tpo" "$(DEPDIR)/heap_checker_debug_unittest-heap-checker_unittest.Po"; else rm -f "$(DEPDIR)/heap_checker_debug_unittest-heap-checker_unittest.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/heap-checker_unittest.cc' object='heap_checker_debug_unittest-heap-checker_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_checker_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o heap_checker_debug_unittest-heap-checker_unittest.o `test -f 'src/tests/heap-checker_unittest.cc' || echo '$(srcdir)/'`src/tests/heap-checker_unittest.cc
+
+heap_checker_debug_unittest-heap-checker_unittest.obj: src/tests/heap-checker_unittest.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_checker_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT heap_checker_debug_unittest-heap-checker_unittest.obj -MD -MP -MF "$(DEPDIR)/heap_checker_debug_unittest-heap-checker_unittest.Tpo" -c -o heap_checker_debug_unittest-heap-checker_unittest.obj `if test -f 'src/tests/heap-checker_unittest.cc'; then $(CYGPATH_W) 'src/tests/heap-checker_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/heap-checker_unittest.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/heap_checker_debug_unittest-heap-checker_unittest.Tpo" "$(DEPDIR)/heap_checker_debug_unittest-heap-checker_unittest.Po"; else rm -f "$(DEPDIR)/heap_checker_debug_unittest-heap-checker_unittest.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/heap-checker_unittest.cc' object='heap_checker_debug_unittest-heap-checker_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_checker_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o heap_checker_debug_unittest-heap-checker_unittest.obj `if test -f 'src/tests/heap-checker_unittest.cc'; then $(CYGPATH_W) 'src/tests/heap-checker_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/heap-checker_unittest.cc'; fi`
+
heap_checker_unittest-heap-checker_unittest.o: src/tests/heap-checker_unittest.cc
@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_checker_unittest_CXXFLAGS) $(CXXFLAGS) -MT heap_checker_unittest-heap-checker_unittest.o -MD -MP -MF "$(DEPDIR)/heap_checker_unittest-heap-checker_unittest.Tpo" -c -o heap_checker_unittest-heap-checker_unittest.o `test -f 'src/tests/heap-checker_unittest.cc' || echo '$(srcdir)/'`src/tests/heap-checker_unittest.cc; \
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/heap_checker_unittest-heap-checker_unittest.Tpo" "$(DEPDIR)/heap_checker_unittest-heap-checker_unittest.Po"; else rm -f "$(DEPDIR)/heap_checker_unittest-heap-checker_unittest.Tpo"; exit 1; fi
@@ -2878,6 +3438,20 @@ heap_checker_unittest-heap-checker_unittest.obj: src/tests/heap-checker_unittest
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_checker_unittest_CXXFLAGS) $(CXXFLAGS) -c -o heap_checker_unittest-heap-checker_unittest.obj `if test -f 'src/tests/heap-checker_unittest.cc'; then $(CYGPATH_W) 'src/tests/heap-checker_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/heap-checker_unittest.cc'; fi`
+heap_profiler_debug_unittest-heap-profiler_unittest.o: src/tests/heap-profiler_unittest.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_profiler_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT heap_profiler_debug_unittest-heap-profiler_unittest.o -MD -MP -MF "$(DEPDIR)/heap_profiler_debug_unittest-heap-profiler_unittest.Tpo" -c -o heap_profiler_debug_unittest-heap-profiler_unittest.o `test -f 'src/tests/heap-profiler_unittest.cc' || echo '$(srcdir)/'`src/tests/heap-profiler_unittest.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/heap_profiler_debug_unittest-heap-profiler_unittest.Tpo" "$(DEPDIR)/heap_profiler_debug_unittest-heap-profiler_unittest.Po"; else rm -f "$(DEPDIR)/heap_profiler_debug_unittest-heap-profiler_unittest.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/heap-profiler_unittest.cc' object='heap_profiler_debug_unittest-heap-profiler_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_profiler_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o heap_profiler_debug_unittest-heap-profiler_unittest.o `test -f 'src/tests/heap-profiler_unittest.cc' || echo '$(srcdir)/'`src/tests/heap-profiler_unittest.cc
+
+heap_profiler_debug_unittest-heap-profiler_unittest.obj: src/tests/heap-profiler_unittest.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_profiler_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT heap_profiler_debug_unittest-heap-profiler_unittest.obj -MD -MP -MF "$(DEPDIR)/heap_profiler_debug_unittest-heap-profiler_unittest.Tpo" -c -o heap_profiler_debug_unittest-heap-profiler_unittest.obj `if test -f 'src/tests/heap-profiler_unittest.cc'; then $(CYGPATH_W) 'src/tests/heap-profiler_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/heap-profiler_unittest.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/heap_profiler_debug_unittest-heap-profiler_unittest.Tpo" "$(DEPDIR)/heap_profiler_debug_unittest-heap-profiler_unittest.Po"; else rm -f "$(DEPDIR)/heap_profiler_debug_unittest-heap-profiler_unittest.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/heap-profiler_unittest.cc' object='heap_profiler_debug_unittest-heap-profiler_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_profiler_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o heap_profiler_debug_unittest-heap-profiler_unittest.obj `if test -f 'src/tests/heap-profiler_unittest.cc'; then $(CYGPATH_W) 'src/tests/heap-profiler_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/heap-profiler_unittest.cc'; fi`
+
heap_profiler_unittest-heap-profiler_unittest.o: src/tests/heap-profiler_unittest.cc
@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(heap_profiler_unittest_CXXFLAGS) $(CXXFLAGS) -MT heap_profiler_unittest-heap-profiler_unittest.o -MD -MP -MF "$(DEPDIR)/heap_profiler_unittest-heap-profiler_unittest.Tpo" -c -o heap_profiler_unittest-heap-profiler_unittest.o `test -f 'src/tests/heap-profiler_unittest.cc' || echo '$(srcdir)/'`src/tests/heap-profiler_unittest.cc; \
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/heap_profiler_unittest-heap-profiler_unittest.Tpo" "$(DEPDIR)/heap_profiler_unittest-heap-profiler_unittest.Po"; else rm -f "$(DEPDIR)/heap_profiler_unittest-heap-profiler_unittest.Tpo"; exit 1; fi
@@ -2934,6 +3508,20 @@ low_level_alloc_unittest-low_level_alloc_unittest.obj: src/tests/low_level_alloc
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(low_level_alloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o low_level_alloc_unittest-low_level_alloc_unittest.obj `if test -f 'src/tests/low_level_alloc_unittest.cc'; then $(CYGPATH_W) 'src/tests/low_level_alloc_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/low_level_alloc_unittest.cc'; fi`
+malloc_extension_debug_test-malloc_extension_test.o: src/tests/malloc_extension_test.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_extension_debug_test_CXXFLAGS) $(CXXFLAGS) -MT malloc_extension_debug_test-malloc_extension_test.o -MD -MP -MF "$(DEPDIR)/malloc_extension_debug_test-malloc_extension_test.Tpo" -c -o malloc_extension_debug_test-malloc_extension_test.o `test -f 'src/tests/malloc_extension_test.cc' || echo '$(srcdir)/'`src/tests/malloc_extension_test.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/malloc_extension_debug_test-malloc_extension_test.Tpo" "$(DEPDIR)/malloc_extension_debug_test-malloc_extension_test.Po"; else rm -f "$(DEPDIR)/malloc_extension_debug_test-malloc_extension_test.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/malloc_extension_test.cc' object='malloc_extension_debug_test-malloc_extension_test.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_extension_debug_test_CXXFLAGS) $(CXXFLAGS) -c -o malloc_extension_debug_test-malloc_extension_test.o `test -f 'src/tests/malloc_extension_test.cc' || echo '$(srcdir)/'`src/tests/malloc_extension_test.cc
+
+malloc_extension_debug_test-malloc_extension_test.obj: src/tests/malloc_extension_test.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_extension_debug_test_CXXFLAGS) $(CXXFLAGS) -MT malloc_extension_debug_test-malloc_extension_test.obj -MD -MP -MF "$(DEPDIR)/malloc_extension_debug_test-malloc_extension_test.Tpo" -c -o malloc_extension_debug_test-malloc_extension_test.obj `if test -f 'src/tests/malloc_extension_test.cc'; then $(CYGPATH_W) 'src/tests/malloc_extension_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/malloc_extension_test.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/malloc_extension_debug_test-malloc_extension_test.Tpo" "$(DEPDIR)/malloc_extension_debug_test-malloc_extension_test.Po"; else rm -f "$(DEPDIR)/malloc_extension_debug_test-malloc_extension_test.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/malloc_extension_test.cc' object='malloc_extension_debug_test-malloc_extension_test.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_extension_debug_test_CXXFLAGS) $(CXXFLAGS) -c -o malloc_extension_debug_test-malloc_extension_test.obj `if test -f 'src/tests/malloc_extension_test.cc'; then $(CYGPATH_W) 'src/tests/malloc_extension_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/malloc_extension_test.cc'; fi`
+
malloc_extension_test-malloc_extension_test.o: src/tests/malloc_extension_test.cc
@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(malloc_extension_test_CXXFLAGS) $(CXXFLAGS) -MT malloc_extension_test-malloc_extension_test.o -MD -MP -MF "$(DEPDIR)/malloc_extension_test-malloc_extension_test.Tpo" -c -o malloc_extension_test-malloc_extension_test.o `test -f 'src/tests/malloc_extension_test.cc' || echo '$(srcdir)/'`src/tests/malloc_extension_test.cc; \
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/malloc_extension_test-malloc_extension_test.Tpo" "$(DEPDIR)/malloc_extension_test-malloc_extension_test.Po"; else rm -f "$(DEPDIR)/malloc_extension_test-malloc_extension_test.Tpo"; exit 1; fi
@@ -2976,6 +3564,34 @@ markidle_unittest-testutil.obj: src/tests/testutil.cc
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(markidle_unittest_CXXFLAGS) $(CXXFLAGS) -c -o markidle_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi`
+memalign_debug_unittest-memalign_unittest.o: src/tests/memalign_unittest.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT memalign_debug_unittest-memalign_unittest.o -MD -MP -MF "$(DEPDIR)/memalign_debug_unittest-memalign_unittest.Tpo" -c -o memalign_debug_unittest-memalign_unittest.o `test -f 'src/tests/memalign_unittest.cc' || echo '$(srcdir)/'`src/tests/memalign_unittest.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/memalign_debug_unittest-memalign_unittest.Tpo" "$(DEPDIR)/memalign_debug_unittest-memalign_unittest.Po"; else rm -f "$(DEPDIR)/memalign_debug_unittest-memalign_unittest.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/memalign_unittest.cc' object='memalign_debug_unittest-memalign_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o memalign_debug_unittest-memalign_unittest.o `test -f 'src/tests/memalign_unittest.cc' || echo '$(srcdir)/'`src/tests/memalign_unittest.cc
+
+memalign_debug_unittest-memalign_unittest.obj: src/tests/memalign_unittest.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT memalign_debug_unittest-memalign_unittest.obj -MD -MP -MF "$(DEPDIR)/memalign_debug_unittest-memalign_unittest.Tpo" -c -o memalign_debug_unittest-memalign_unittest.obj `if test -f 'src/tests/memalign_unittest.cc'; then $(CYGPATH_W) 'src/tests/memalign_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/memalign_unittest.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/memalign_debug_unittest-memalign_unittest.Tpo" "$(DEPDIR)/memalign_debug_unittest-memalign_unittest.Po"; else rm -f "$(DEPDIR)/memalign_debug_unittest-memalign_unittest.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/memalign_unittest.cc' object='memalign_debug_unittest-memalign_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o memalign_debug_unittest-memalign_unittest.obj `if test -f 'src/tests/memalign_unittest.cc'; then $(CYGPATH_W) 'src/tests/memalign_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/memalign_unittest.cc'; fi`
+
+memalign_debug_unittest-testutil.o: src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT memalign_debug_unittest-testutil.o -MD -MP -MF "$(DEPDIR)/memalign_debug_unittest-testutil.Tpo" -c -o memalign_debug_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/memalign_debug_unittest-testutil.Tpo" "$(DEPDIR)/memalign_debug_unittest-testutil.Po"; else rm -f "$(DEPDIR)/memalign_debug_unittest-testutil.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/testutil.cc' object='memalign_debug_unittest-testutil.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o memalign_debug_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc
+
+memalign_debug_unittest-testutil.obj: src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT memalign_debug_unittest-testutil.obj -MD -MP -MF "$(DEPDIR)/memalign_debug_unittest-testutil.Tpo" -c -o memalign_debug_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/memalign_debug_unittest-testutil.Tpo" "$(DEPDIR)/memalign_debug_unittest-testutil.Po"; else rm -f "$(DEPDIR)/memalign_debug_unittest-testutil.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/testutil.cc' object='memalign_debug_unittest-testutil.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o memalign_debug_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi`
+
memalign_unittest-memalign_unittest.o: src/tests/memalign_unittest.cc
@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_unittest_CXXFLAGS) $(CXXFLAGS) -MT memalign_unittest-memalign_unittest.o -MD -MP -MF "$(DEPDIR)/memalign_unittest-memalign_unittest.Tpo" -c -o memalign_unittest-memalign_unittest.o `test -f 'src/tests/memalign_unittest.cc' || echo '$(srcdir)/'`src/tests/memalign_unittest.cc; \
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/memalign_unittest-memalign_unittest.Tpo" "$(DEPDIR)/memalign_unittest-memalign_unittest.Po"; else rm -f "$(DEPDIR)/memalign_unittest-memalign_unittest.Tpo"; exit 1; fi
@@ -3004,19 +3620,19 @@ memalign_unittest-testutil.obj: src/tests/testutil.cc
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(memalign_unittest_CXXFLAGS) $(CXXFLAGS) -c -o memalign_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi`
-packed-cache_test.o: src/tests/packed-cache_test.cc
-@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT packed-cache_test.o -MD -MP -MF "$(DEPDIR)/packed-cache_test.Tpo" -c -o packed-cache_test.o `test -f 'src/tests/packed-cache_test.cc' || echo '$(srcdir)/'`src/tests/packed-cache_test.cc; \
-@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/packed-cache_test.Tpo" "$(DEPDIR)/packed-cache_test.Po"; else rm -f "$(DEPDIR)/packed-cache_test.Tpo"; exit 1; fi
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/packed-cache_test.cc' object='packed-cache_test.o' libtool=no @AMDEPBACKSLASH@
+packed_cache_test-packed-cache_test.o: src/tests/packed-cache_test.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(packed_cache_test_CXXFLAGS) $(CXXFLAGS) -MT packed_cache_test-packed-cache_test.o -MD -MP -MF "$(DEPDIR)/packed_cache_test-packed-cache_test.Tpo" -c -o packed_cache_test-packed-cache_test.o `test -f 'src/tests/packed-cache_test.cc' || echo '$(srcdir)/'`src/tests/packed-cache_test.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/packed_cache_test-packed-cache_test.Tpo" "$(DEPDIR)/packed_cache_test-packed-cache_test.Po"; else rm -f "$(DEPDIR)/packed_cache_test-packed-cache_test.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/packed-cache_test.cc' object='packed_cache_test-packed-cache_test.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o packed-cache_test.o `test -f 'src/tests/packed-cache_test.cc' || echo '$(srcdir)/'`src/tests/packed-cache_test.cc
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(packed_cache_test_CXXFLAGS) $(CXXFLAGS) -c -o packed_cache_test-packed-cache_test.o `test -f 'src/tests/packed-cache_test.cc' || echo '$(srcdir)/'`src/tests/packed-cache_test.cc
-packed-cache_test.obj: src/tests/packed-cache_test.cc
-@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT packed-cache_test.obj -MD -MP -MF "$(DEPDIR)/packed-cache_test.Tpo" -c -o packed-cache_test.obj `if test -f 'src/tests/packed-cache_test.cc'; then $(CYGPATH_W) 'src/tests/packed-cache_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/packed-cache_test.cc'; fi`; \
-@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/packed-cache_test.Tpo" "$(DEPDIR)/packed-cache_test.Po"; else rm -f "$(DEPDIR)/packed-cache_test.Tpo"; exit 1; fi
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/packed-cache_test.cc' object='packed-cache_test.obj' libtool=no @AMDEPBACKSLASH@
+packed_cache_test-packed-cache_test.obj: src/tests/packed-cache_test.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(packed_cache_test_CXXFLAGS) $(CXXFLAGS) -MT packed_cache_test-packed-cache_test.obj -MD -MP -MF "$(DEPDIR)/packed_cache_test-packed-cache_test.Tpo" -c -o packed_cache_test-packed-cache_test.obj `if test -f 'src/tests/packed-cache_test.cc'; then $(CYGPATH_W) 'src/tests/packed-cache_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/packed-cache_test.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/packed_cache_test-packed-cache_test.Tpo" "$(DEPDIR)/packed_cache_test-packed-cache_test.Po"; else rm -f "$(DEPDIR)/packed_cache_test-packed-cache_test.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/packed-cache_test.cc' object='packed_cache_test-packed-cache_test.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o packed-cache_test.obj `if test -f 'src/tests/packed-cache_test.cc'; then $(CYGPATH_W) 'src/tests/packed-cache_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/packed-cache_test.cc'; fi`
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(packed_cache_test_CXXFLAGS) $(CXXFLAGS) -c -o packed_cache_test-packed-cache_test.obj `if test -f 'src/tests/packed-cache_test.cc'; then $(CYGPATH_W) 'src/tests/packed-cache_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/packed-cache_test.cc'; fi`
pagemap_unittest-pagemap_unittest.o: src/tests/pagemap_unittest.cc
@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pagemap_unittest_CXXFLAGS) $(CXXFLAGS) -MT pagemap_unittest-pagemap_unittest.o -MD -MP -MF "$(DEPDIR)/pagemap_unittest-pagemap_unittest.Tpo" -c -o pagemap_unittest-pagemap_unittest.o `test -f 'src/tests/pagemap_unittest.cc' || echo '$(srcdir)/'`src/tests/pagemap_unittest.cc; \
@@ -3186,6 +3802,20 @@ raw_printer_test-raw_printer_test.obj: src/tests/raw_printer_test.cc
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(raw_printer_test_CXXFLAGS) $(CXXFLAGS) -c -o raw_printer_test-raw_printer_test.obj `if test -f 'src/tests/raw_printer_test.cc'; then $(CYGPATH_W) 'src/tests/raw_printer_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/raw_printer_test.cc'; fi`
+realloc_debug_unittest-realloc_unittest.o: src/tests/realloc_unittest.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(realloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT realloc_debug_unittest-realloc_unittest.o -MD -MP -MF "$(DEPDIR)/realloc_debug_unittest-realloc_unittest.Tpo" -c -o realloc_debug_unittest-realloc_unittest.o `test -f 'src/tests/realloc_unittest.cc' || echo '$(srcdir)/'`src/tests/realloc_unittest.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/realloc_debug_unittest-realloc_unittest.Tpo" "$(DEPDIR)/realloc_debug_unittest-realloc_unittest.Po"; else rm -f "$(DEPDIR)/realloc_debug_unittest-realloc_unittest.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/realloc_unittest.cc' object='realloc_debug_unittest-realloc_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(realloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o realloc_debug_unittest-realloc_unittest.o `test -f 'src/tests/realloc_unittest.cc' || echo '$(srcdir)/'`src/tests/realloc_unittest.cc
+
+realloc_debug_unittest-realloc_unittest.obj: src/tests/realloc_unittest.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(realloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT realloc_debug_unittest-realloc_unittest.obj -MD -MP -MF "$(DEPDIR)/realloc_debug_unittest-realloc_unittest.Tpo" -c -o realloc_debug_unittest-realloc_unittest.obj `if test -f 'src/tests/realloc_unittest.cc'; then $(CYGPATH_W) 'src/tests/realloc_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/realloc_unittest.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/realloc_debug_unittest-realloc_unittest.Tpo" "$(DEPDIR)/realloc_debug_unittest-realloc_unittest.Po"; else rm -f "$(DEPDIR)/realloc_debug_unittest-realloc_unittest.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/realloc_unittest.cc' object='realloc_debug_unittest-realloc_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(realloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o realloc_debug_unittest-realloc_unittest.obj `if test -f 'src/tests/realloc_unittest.cc'; then $(CYGPATH_W) 'src/tests/realloc_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/realloc_unittest.cc'; fi`
+
realloc_unittest-realloc_unittest.o: src/tests/realloc_unittest.cc
@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(realloc_unittest_CXXFLAGS) $(CXXFLAGS) -MT realloc_unittest-realloc_unittest.o -MD -MP -MF "$(DEPDIR)/realloc_unittest-realloc_unittest.Tpo" -c -o realloc_unittest-realloc_unittest.o `test -f 'src/tests/realloc_unittest.cc' || echo '$(srcdir)/'`src/tests/realloc_unittest.cc; \
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/realloc_unittest-realloc_unittest.Tpo" "$(DEPDIR)/realloc_unittest-realloc_unittest.Po"; else rm -f "$(DEPDIR)/realloc_unittest-realloc_unittest.Tpo"; exit 1; fi
@@ -3200,6 +3830,20 @@ realloc_unittest-realloc_unittest.obj: src/tests/realloc_unittest.cc
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(realloc_unittest_CXXFLAGS) $(CXXFLAGS) -c -o realloc_unittest-realloc_unittest.obj `if test -f 'src/tests/realloc_unittest.cc'; then $(CYGPATH_W) 'src/tests/realloc_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/realloc_unittest.cc'; fi`
+sampler_debug_test-sampler_test.o: src/tests/sampler_test.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampler_debug_test_CXXFLAGS) $(CXXFLAGS) -MT sampler_debug_test-sampler_test.o -MD -MP -MF "$(DEPDIR)/sampler_debug_test-sampler_test.Tpo" -c -o sampler_debug_test-sampler_test.o `test -f 'src/tests/sampler_test.cc' || echo '$(srcdir)/'`src/tests/sampler_test.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/sampler_debug_test-sampler_test.Tpo" "$(DEPDIR)/sampler_debug_test-sampler_test.Po"; else rm -f "$(DEPDIR)/sampler_debug_test-sampler_test.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/sampler_test.cc' object='sampler_debug_test-sampler_test.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampler_debug_test_CXXFLAGS) $(CXXFLAGS) -c -o sampler_debug_test-sampler_test.o `test -f 'src/tests/sampler_test.cc' || echo '$(srcdir)/'`src/tests/sampler_test.cc
+
+sampler_debug_test-sampler_test.obj: src/tests/sampler_test.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampler_debug_test_CXXFLAGS) $(CXXFLAGS) -MT sampler_debug_test-sampler_test.obj -MD -MP -MF "$(DEPDIR)/sampler_debug_test-sampler_test.Tpo" -c -o sampler_debug_test-sampler_test.obj `if test -f 'src/tests/sampler_test.cc'; then $(CYGPATH_W) 'src/tests/sampler_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/sampler_test.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/sampler_debug_test-sampler_test.Tpo" "$(DEPDIR)/sampler_debug_test-sampler_test.Po"; else rm -f "$(DEPDIR)/sampler_debug_test-sampler_test.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/sampler_test.cc' object='sampler_debug_test-sampler_test.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampler_debug_test_CXXFLAGS) $(CXXFLAGS) -c -o sampler_debug_test-sampler_test.obj `if test -f 'src/tests/sampler_test.cc'; then $(CYGPATH_W) 'src/tests/sampler_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/sampler_test.cc'; fi`
+
sampler_test-sampler_test.o: src/tests/sampler_test.cc
@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampler_test_CXXFLAGS) $(CXXFLAGS) -MT sampler_test-sampler_test.o -MD -MP -MF "$(DEPDIR)/sampler_test-sampler_test.Tpo" -c -o sampler_test-sampler_test.o `test -f 'src/tests/sampler_test.cc' || echo '$(srcdir)/'`src/tests/sampler_test.cc; \
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/sampler_test-sampler_test.Tpo" "$(DEPDIR)/sampler_test-sampler_test.Po"; else rm -f "$(DEPDIR)/sampler_test-sampler_test.Tpo"; exit 1; fi
@@ -3214,6 +3858,20 @@ sampler_test-sampler_test.obj: src/tests/sampler_test.cc
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampler_test_CXXFLAGS) $(CXXFLAGS) -c -o sampler_test-sampler_test.obj `if test -f 'src/tests/sampler_test.cc'; then $(CYGPATH_W) 'src/tests/sampler_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/sampler_test.cc'; fi`
+sampling_debug_test-sampling_test.o: src/tests/sampling_test.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampling_debug_test_CXXFLAGS) $(CXXFLAGS) -MT sampling_debug_test-sampling_test.o -MD -MP -MF "$(DEPDIR)/sampling_debug_test-sampling_test.Tpo" -c -o sampling_debug_test-sampling_test.o `test -f 'src/tests/sampling_test.cc' || echo '$(srcdir)/'`src/tests/sampling_test.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/sampling_debug_test-sampling_test.Tpo" "$(DEPDIR)/sampling_debug_test-sampling_test.Po"; else rm -f "$(DEPDIR)/sampling_debug_test-sampling_test.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/sampling_test.cc' object='sampling_debug_test-sampling_test.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampling_debug_test_CXXFLAGS) $(CXXFLAGS) -c -o sampling_debug_test-sampling_test.o `test -f 'src/tests/sampling_test.cc' || echo '$(srcdir)/'`src/tests/sampling_test.cc
+
+sampling_debug_test-sampling_test.obj: src/tests/sampling_test.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampling_debug_test_CXXFLAGS) $(CXXFLAGS) -MT sampling_debug_test-sampling_test.obj -MD -MP -MF "$(DEPDIR)/sampling_debug_test-sampling_test.Tpo" -c -o sampling_debug_test-sampling_test.obj `if test -f 'src/tests/sampling_test.cc'; then $(CYGPATH_W) 'src/tests/sampling_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/sampling_test.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/sampling_debug_test-sampling_test.Tpo" "$(DEPDIR)/sampling_debug_test-sampling_test.Po"; else rm -f "$(DEPDIR)/sampling_debug_test-sampling_test.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/sampling_test.cc' object='sampling_debug_test-sampling_test.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampling_debug_test_CXXFLAGS) $(CXXFLAGS) -c -o sampling_debug_test-sampling_test.obj `if test -f 'src/tests/sampling_test.cc'; then $(CYGPATH_W) 'src/tests/sampling_test.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/sampling_test.cc'; fi`
+
sampling_test-sampling_test.o: src/tests/sampling_test.cc
@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(sampling_test_CXXFLAGS) $(CXXFLAGS) -MT sampling_test-sampling_test.o -MD -MP -MF "$(DEPDIR)/sampling_test-sampling_test.Tpo" -c -o sampling_test-sampling_test.o `test -f 'src/tests/sampling_test.cc' || echo '$(srcdir)/'`src/tests/sampling_test.cc; \
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/sampling_test-sampling_test.Tpo" "$(DEPDIR)/sampling_test-sampling_test.Po"; else rm -f "$(DEPDIR)/sampling_test-sampling_test.Tpo"; exit 1; fi
@@ -3326,6 +3984,34 @@ tcmalloc_both_unittest-testutil.obj: src/tests/testutil.cc
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_both_unittest_CXXFLAGS) $(CXXFLAGS) -c -o tcmalloc_both_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi`
+tcmalloc_debug_unittest-tcmalloc_unittest.o: src/tests/tcmalloc_unittest.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT tcmalloc_debug_unittest-tcmalloc_unittest.o -MD -MP -MF "$(DEPDIR)/tcmalloc_debug_unittest-tcmalloc_unittest.Tpo" -c -o tcmalloc_debug_unittest-tcmalloc_unittest.o `test -f 'src/tests/tcmalloc_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_unittest.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/tcmalloc_debug_unittest-tcmalloc_unittest.Tpo" "$(DEPDIR)/tcmalloc_debug_unittest-tcmalloc_unittest.Po"; else rm -f "$(DEPDIR)/tcmalloc_debug_unittest-tcmalloc_unittest.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/tcmalloc_unittest.cc' object='tcmalloc_debug_unittest-tcmalloc_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o tcmalloc_debug_unittest-tcmalloc_unittest.o `test -f 'src/tests/tcmalloc_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_unittest.cc
+
+tcmalloc_debug_unittest-tcmalloc_unittest.obj: src/tests/tcmalloc_unittest.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT tcmalloc_debug_unittest-tcmalloc_unittest.obj -MD -MP -MF "$(DEPDIR)/tcmalloc_debug_unittest-tcmalloc_unittest.Tpo" -c -o tcmalloc_debug_unittest-tcmalloc_unittest.obj `if test -f 'src/tests/tcmalloc_unittest.cc'; then $(CYGPATH_W) 'src/tests/tcmalloc_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/tcmalloc_unittest.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/tcmalloc_debug_unittest-tcmalloc_unittest.Tpo" "$(DEPDIR)/tcmalloc_debug_unittest-tcmalloc_unittest.Po"; else rm -f "$(DEPDIR)/tcmalloc_debug_unittest-tcmalloc_unittest.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/tcmalloc_unittest.cc' object='tcmalloc_debug_unittest-tcmalloc_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o tcmalloc_debug_unittest-tcmalloc_unittest.obj `if test -f 'src/tests/tcmalloc_unittest.cc'; then $(CYGPATH_W) 'src/tests/tcmalloc_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/tcmalloc_unittest.cc'; fi`
+
+tcmalloc_debug_unittest-testutil.o: src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT tcmalloc_debug_unittest-testutil.o -MD -MP -MF "$(DEPDIR)/tcmalloc_debug_unittest-testutil.Tpo" -c -o tcmalloc_debug_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/tcmalloc_debug_unittest-testutil.Tpo" "$(DEPDIR)/tcmalloc_debug_unittest-testutil.Po"; else rm -f "$(DEPDIR)/tcmalloc_debug_unittest-testutil.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/testutil.cc' object='tcmalloc_debug_unittest-testutil.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o tcmalloc_debug_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc
+
+tcmalloc_debug_unittest-testutil.obj: src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT tcmalloc_debug_unittest-testutil.obj -MD -MP -MF "$(DEPDIR)/tcmalloc_debug_unittest-testutil.Tpo" -c -o tcmalloc_debug_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/tcmalloc_debug_unittest-testutil.Tpo" "$(DEPDIR)/tcmalloc_debug_unittest-testutil.Po"; else rm -f "$(DEPDIR)/tcmalloc_debug_unittest-testutil.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/testutil.cc' object='tcmalloc_debug_unittest-testutil.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o tcmalloc_debug_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi`
+
tcmalloc_large_unittest-tcmalloc_large_unittest.o: src/tests/tcmalloc_large_unittest.cc
@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_large_unittest_CXXFLAGS) $(CXXFLAGS) -MT tcmalloc_large_unittest-tcmalloc_large_unittest.o -MD -MP -MF "$(DEPDIR)/tcmalloc_large_unittest-tcmalloc_large_unittest.Tpo" -c -o tcmalloc_large_unittest-tcmalloc_large_unittest.o `test -f 'src/tests/tcmalloc_large_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_large_unittest.cc; \
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/tcmalloc_large_unittest-tcmalloc_large_unittest.Tpo" "$(DEPDIR)/tcmalloc_large_unittest-tcmalloc_large_unittest.Po"; else rm -f "$(DEPDIR)/tcmalloc_large_unittest-tcmalloc_large_unittest.Tpo"; exit 1; fi
@@ -3340,6 +4026,34 @@ tcmalloc_large_unittest-tcmalloc_large_unittest.obj: src/tests/tcmalloc_large_un
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_large_unittest_CXXFLAGS) $(CXXFLAGS) -c -o tcmalloc_large_unittest-tcmalloc_large_unittest.obj `if test -f 'src/tests/tcmalloc_large_unittest.cc'; then $(CYGPATH_W) 'src/tests/tcmalloc_large_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/tcmalloc_large_unittest.cc'; fi`
+tcmalloc_minimal_debug_unittest-tcmalloc_unittest.o: src/tests/tcmalloc_unittest.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT tcmalloc_minimal_debug_unittest-tcmalloc_unittest.o -MD -MP -MF "$(DEPDIR)/tcmalloc_minimal_debug_unittest-tcmalloc_unittest.Tpo" -c -o tcmalloc_minimal_debug_unittest-tcmalloc_unittest.o `test -f 'src/tests/tcmalloc_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_unittest.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/tcmalloc_minimal_debug_unittest-tcmalloc_unittest.Tpo" "$(DEPDIR)/tcmalloc_minimal_debug_unittest-tcmalloc_unittest.Po"; else rm -f "$(DEPDIR)/tcmalloc_minimal_debug_unittest-tcmalloc_unittest.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/tcmalloc_unittest.cc' object='tcmalloc_minimal_debug_unittest-tcmalloc_unittest.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o tcmalloc_minimal_debug_unittest-tcmalloc_unittest.o `test -f 'src/tests/tcmalloc_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_unittest.cc
+
+tcmalloc_minimal_debug_unittest-tcmalloc_unittest.obj: src/tests/tcmalloc_unittest.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT tcmalloc_minimal_debug_unittest-tcmalloc_unittest.obj -MD -MP -MF "$(DEPDIR)/tcmalloc_minimal_debug_unittest-tcmalloc_unittest.Tpo" -c -o tcmalloc_minimal_debug_unittest-tcmalloc_unittest.obj `if test -f 'src/tests/tcmalloc_unittest.cc'; then $(CYGPATH_W) 'src/tests/tcmalloc_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/tcmalloc_unittest.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/tcmalloc_minimal_debug_unittest-tcmalloc_unittest.Tpo" "$(DEPDIR)/tcmalloc_minimal_debug_unittest-tcmalloc_unittest.Po"; else rm -f "$(DEPDIR)/tcmalloc_minimal_debug_unittest-tcmalloc_unittest.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/tcmalloc_unittest.cc' object='tcmalloc_minimal_debug_unittest-tcmalloc_unittest.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o tcmalloc_minimal_debug_unittest-tcmalloc_unittest.obj `if test -f 'src/tests/tcmalloc_unittest.cc'; then $(CYGPATH_W) 'src/tests/tcmalloc_unittest.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/tcmalloc_unittest.cc'; fi`
+
+tcmalloc_minimal_debug_unittest-testutil.o: src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT tcmalloc_minimal_debug_unittest-testutil.o -MD -MP -MF "$(DEPDIR)/tcmalloc_minimal_debug_unittest-testutil.Tpo" -c -o tcmalloc_minimal_debug_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/tcmalloc_minimal_debug_unittest-testutil.Tpo" "$(DEPDIR)/tcmalloc_minimal_debug_unittest-testutil.Po"; else rm -f "$(DEPDIR)/tcmalloc_minimal_debug_unittest-testutil.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/testutil.cc' object='tcmalloc_minimal_debug_unittest-testutil.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o tcmalloc_minimal_debug_unittest-testutil.o `test -f 'src/tests/testutil.cc' || echo '$(srcdir)/'`src/tests/testutil.cc
+
+tcmalloc_minimal_debug_unittest-testutil.obj: src/tests/testutil.cc
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_debug_unittest_CXXFLAGS) $(CXXFLAGS) -MT tcmalloc_minimal_debug_unittest-testutil.obj -MD -MP -MF "$(DEPDIR)/tcmalloc_minimal_debug_unittest-testutil.Tpo" -c -o tcmalloc_minimal_debug_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/tcmalloc_minimal_debug_unittest-testutil.Tpo" "$(DEPDIR)/tcmalloc_minimal_debug_unittest-testutil.Po"; else rm -f "$(DEPDIR)/tcmalloc_minimal_debug_unittest-testutil.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='src/tests/testutil.cc' object='tcmalloc_minimal_debug_unittest-testutil.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_debug_unittest_CXXFLAGS) $(CXXFLAGS) -c -o tcmalloc_minimal_debug_unittest-testutil.obj `if test -f 'src/tests/testutil.cc'; then $(CYGPATH_W) 'src/tests/testutil.cc'; else $(CYGPATH_W) '$(srcdir)/src/tests/testutil.cc'; fi`
+
tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.o: src/tests/tcmalloc_large_unittest.cc
@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(tcmalloc_minimal_large_unittest_CXXFLAGS) $(CXXFLAGS) -MT tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.o -MD -MP -MF "$(DEPDIR)/tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.Tpo" -c -o tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.o `test -f 'src/tests/tcmalloc_large_unittest.cc' || echo '$(srcdir)/'`src/tests/tcmalloc_large_unittest.cc; \
@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.Tpo" "$(DEPDIR)/tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.Po"; else rm -f "$(DEPDIR)/tcmalloc_minimal_large_unittest-tcmalloc_large_unittest.Tpo"; exit 1; fi
@@ -3928,6 +4642,10 @@ uninstall-man: uninstall-man1
@MINGW_FALSE@ low_level_alloc_unittest
@MINGW_FALSE@ rm -f $@
@MINGW_FALSE@ cp -p $(top_srcdir)/$(maybe_threads_unittest_sh_SOURCES) $@
+@WITH_DEBUGALLOC_TRUE@debugallocation_test.sh$(EXEEXT): $(top_srcdir)/$(debugallocation_test_sh_SOURCES) \
+@WITH_DEBUGALLOC_TRUE@ debugallocation_test
+@WITH_DEBUGALLOC_TRUE@ rm -f $@
+@WITH_DEBUGALLOC_TRUE@ cp -p $(top_srcdir)/$(debugallocation_test_sh_SOURCES) $@
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampling_test.sh$(EXEEXT): $(top_srcdir)/$(sampling_test_sh_SOURCES) \
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampling_test
@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ rm -f $@
@@ -3944,6 +4662,18 @@ uninstall-man: uninstall-man1
@WITH_HEAP_CHECKER_TRUE@ heap-checker_unittest
@WITH_HEAP_CHECKER_TRUE@ rm -f $@
@WITH_HEAP_CHECKER_TRUE@ cp -p $(top_srcdir)/$(heap_checker_death_unittest_sh_SOURCES) $@
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@sampling_debug_test.sh$(EXEEXT): $(top_srcdir)/$(sampling_test_sh_SOURCES) \
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ sampling_debug_test
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ rm -f $@
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_OR_CHECKER_TRUE@ cp -p $(top_srcdir)/$(sampling_test_sh_SOURCES) $@
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@heap-profiler_debug_unittest.sh$(EXEEXT): $(top_srcdir)/$(heap_profiler_unittest_sh_SOURCES) \
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@ heap-profiler_debug_unittest
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@ rm -f $@
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_PROFILER_TRUE@ cp -p $(top_srcdir)/$(heap_profiler_unittest_sh_SOURCES) $@
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@heap-checker_debug_unittest.sh$(EXEEXT): $(top_srcdir)/$(heap_checker_unittest_sh_SOURCES) \
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@ heap-checker_debug_unittest
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@ rm -f $@
+@WITH_DEBUGALLOC_TRUE@@WITH_HEAP_CHECKER_TRUE@ cp -p $(top_srcdir)/$(heap_checker_unittest_sh_SOURCES) $@
@WITH_CPU_PROFILER_TRUE@profiler_unittest.sh$(EXEEXT): $(top_srcdir)/$(profiler_unittest_sh_SOURCES) \
@WITH_CPU_PROFILER_TRUE@ profiler1_unittest profiler2_unittest \
@WITH_CPU_PROFILER_TRUE@ profiler3_unittest profiler4_unittest
@@ -3953,9 +4683,7 @@ uninstall-man: uninstall-man1
# Do the weakening on some exported libtcmalloc symbols.
install-exec-local: all-local
all-local: $(LIBS_TO_WEAKEN)
- [ ! -f .libs/libtcmalloc_minimal.a ] || $(WEAKEN) .libs/libtcmalloc_minimal.a
- [ ! -f .libs/libtcmalloc.a ] || $(WEAKEN) .libs/libtcmalloc.a
- [ ! -f .libs/libtcmalloc_and_profiler.a ] || $(WEAKEN) .libs/libtcmalloc_and_profiler.a
+ for la in $(LIBS_TO_WEAKEN); do lib=".libs/`basename $$la .la`.a"; [ ! -f "$$lib" ] || $(WEAKEN) "$$lib"; done
rpm: dist-gzip packages/rpm.sh packages/rpm/rpm.spec
@cd packages && ./rpm.sh ${PACKAGE} ${VERSION}
diff --git a/aclocal.m4 b/aclocal.m4
index ccab98d..02d7762 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -7546,5 +7546,6 @@ m4_include([m4/acx_pthread.m4])
m4_include([m4/compiler_characteristics.m4])
m4_include([m4/install_prefix.m4])
m4_include([m4/namespaces.m4])
+m4_include([m4/pc_from_ucontext.m4])
m4_include([m4/program_invocation_name.m4])
m4_include([m4/stl_namespace.m4])
diff --git a/configure b/configure
index 72af618..1555ea7 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.61 for google-perftools 1.3.
+# Generated by GNU Autoconf 2.61 for google-perftools 1.4.
#
# Report bugs to <opensource@google.com>.
#
@@ -728,8 +728,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package.
PACKAGE_NAME='google-perftools'
PACKAGE_TARNAME='google-perftools'
-PACKAGE_VERSION='1.3'
-PACKAGE_STRING='google-perftools 1.3'
+PACKAGE_VERSION='1.4'
+PACKAGE_STRING='google-perftools 1.4'
PACKAGE_BUGREPORT='opensource@google.com'
ac_unique_file="README"
@@ -835,6 +835,9 @@ am__leading_dot
AMTAR
am__tar
am__untar
+TC_VERSION_MAJOR
+TC_VERSION_MINOR
+TC_VERSION_PATCH
CC
CFLAGS
LDFLAGS
@@ -900,6 +903,8 @@ WITH_HEAP_PROFILER_TRUE
WITH_HEAP_PROFILER_FALSE
WITH_HEAP_CHECKER_TRUE
WITH_HEAP_CHECKER_FALSE
+WITH_DEBUGALLOC_TRUE
+WITH_DEBUGALLOC_FALSE
WITH_HEAP_PROFILER_OR_CHECKER_TRUE
WITH_HEAP_PROFILER_OR_CHECKER_FALSE
WITH_STACK_TRACE_TRUE
@@ -1424,7 +1429,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures google-perftools 1.3 to adapt to many kinds of systems.
+\`configure' configures google-perftools 1.4 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1494,7 +1499,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of google-perftools 1.3:";;
+ short | recursive ) echo "Configuration of google-perftools 1.4:";;
esac
cat <<\_ACEOF
@@ -1504,7 +1509,9 @@ Optional Features:
--disable-cpu-profiler do not build the cpu profiler
--disable-heap-profiler do not build the heap profiler
--disable-heap-checker do not build the heap checker
- --enable-minimal build only tcmalloc-minimal
+ --disable-debugalloc do not build versions of libs with debugalloc
+ --enable-minimal build only tcmalloc-minimal (and maybe
+ tcmalloc-minimal-debug)
--disable-dependency-tracking speeds up one-time build
--enable-dependency-tracking do not reject slow dependency extractors
--enable-fast-install[=PKGS]
@@ -1602,7 +1609,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-google-perftools configure 1.3
+google-perftools configure 1.4
generated by GNU Autoconf 2.61
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -1616,7 +1623,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by google-perftools $as_me 1.3, which was
+It was created by google-perftools $as_me 1.4, which was
generated by GNU Autoconf 2.61. Invocation command line was
$ $0 $@
@@ -2372,7 +2379,7 @@ fi
# Define the identity of the package.
PACKAGE='google-perftools'
- VERSION='1.3'
+ VERSION='1.4'
cat >>confdefs.h <<_ACEOF
@@ -2521,6 +2528,15 @@ am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
ac_config_headers="$ac_config_headers src/config.h"
+# Export the version information (for tc_version and friends)
+TC_VERSION_MAJOR=`expr "$PACKAGE_VERSION" : '\([0-9]*\)'`
+TC_VERSION_MINOR=`expr "$PACKAGE_VERSION" : '[^.]*\.\([0-9]*\)'`
+TC_VERSION_PATCH=`expr "$PACKAGE_VERSION" : '[^.0-9]*\([^0-9]*\)$'`
+
+
+
+
+
# The user can choose not to compile in the heap-profiler, the
# heap-checker, or the cpu-profiler. There's also the possibility
# for a 'fully minimal' compile, which leaves out the stacktrace
@@ -2529,10 +2545,12 @@ ac_config_headers="$ac_config_headers src/config.h"
default_enable_cpu_profiler=yes
default_enable_heap_profiler=yes
default_enable_heap_checker=yes
+default_enable_debugalloc=yes
default_enable_minimal=no
need_nanosleep=yes # Used later, to decide if to run ACX_NANOSLEEP
case "$host" in
- *-mingw*) default_enable_minimal=yes; need_nanosleep=no;;
+ *-mingw*) default_enable_minimal=yes; default_enable_debugalloc=no;
+ need_nanosleep=no;;
*-cygwin*) default_enable_heap_checker=no; default_enable_cpu_profiler=no;;
*-freebsd*) default_enable_heap_checker=no;;
*-darwin*) default_enable_heap_checker=no;;
@@ -2559,6 +2577,13 @@ else
enable_heap_checker="$default_enable_heap_checker"
fi
+# Check whether --enable-debugalloc was given.
+if test "${enable_debugalloc+set}" = set; then
+ enableval=$enable_debugalloc;
+else
+ enable_debugalloc="$default_enable_debugalloc"
+fi
+
# Check whether --enable-minimal was given.
if test "${enable_minimal+set}" = set; then
enableval=$enable_minimal;
@@ -4506,11 +4531,6 @@ if eval "test \"`echo '$ac_cv_prog_cc_'${ac_cc}_c_o`\" != yes"; then
fi
# shrug: autogen.sh suddenly needs this for some reason
-# We work behind libtool's back, replacing 'ar' by 'ld -r' in some
-# situations. The only issue is that 'ld -r' output doesn't support
-# ranlib. Nobody needs ranlib anymore, so it's safe to just disable it.
-RANLIB=":"
-
# Check if we have an objcopy installed that supports -W
if test -n "$ac_tool_prefix"; then
# Extract the first word of "${ac_tool_prefix}objcopy", so it can be a program name with args.
@@ -5380,7 +5400,7 @@ ia64-*-hpux*)
;;
*-*-irix6*)
# Find out which ABI we are using.
- echo '#line 5383 "configure"' > conftest.$ac_ext
+ echo '#line 5403 "configure"' > conftest.$ac_ext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -7735,11 +7755,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7738: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7758: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:7742: \$? = $ac_status" >&5
+ echo "$as_me:7762: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -8025,11 +8045,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:8028: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:8048: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:8032: \$? = $ac_status" >&5
+ echo "$as_me:8052: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -8129,11 +8149,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:8132: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:8152: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:8136: \$? = $ac_status" >&5
+ echo "$as_me:8156: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -10506,7 +10526,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 10509 "configure"
+#line 10529 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -10606,7 +10626,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 10609 "configure"
+#line 10629 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -13007,11 +13027,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:13010: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:13030: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:13014: \$? = $ac_status" >&5
+ echo "$as_me:13034: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -13111,11 +13131,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:13114: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:13134: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:13118: \$? = $ac_status" >&5
+ echo "$as_me:13138: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -14709,11 +14729,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:14712: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:14732: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:14716: \$? = $ac_status" >&5
+ echo "$as_me:14736: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -14813,11 +14833,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:14816: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:14836: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:14820: \$? = $ac_status" >&5
+ echo "$as_me:14840: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -17033,11 +17053,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:17036: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:17056: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:17040: \$? = $ac_status" >&5
+ echo "$as_me:17060: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -17323,11 +17343,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:17326: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:17346: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:17330: \$? = $ac_status" >&5
+ echo "$as_me:17350: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -17427,11 +17447,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:17430: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:17450: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:17434: \$? = $ac_status" >&5
+ echo "$as_me:17454: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -21976,6 +21996,151 @@ fi
done
# for profiler.cc (cpu profiler)
+for ac_header in cygwin/signal.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ ( cat <<\_ASBOX
+## ------------------------------------ ##
+## Report this to opensource@google.com ##
+## ------------------------------------ ##
+_ASBOX
+ ) | sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+ # ucontext on cywgin
+
for ac_header in conflict-signal.h
do
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
@@ -22119,7 +22284,7 @@ _ACEOF
fi
done
- # defined on some windows platforms
+ # defined on some windows platforms?
for ac_header in sys/prctl.h
do
@@ -22846,6 +23011,151 @@ fi
done
# optional; for forking out to symbolizer
+for ac_header in poll.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+ ( cat <<\_ASBOX
+## ------------------------------------ ##
+## Report this to opensource@google.com ##
+## ------------------------------------ ##
+_ASBOX
+ ) | sed "s/^/$as_me: WARNING: /" >&2
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+ # optional; for forking out to symbolizer
+
for ac_header in fcntl.h
do
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
@@ -24287,30 +24597,34 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
if test "$enable_cpu_profiler" = yes; then
{ echo "$as_me:$LINENO: checking how to access the program counter from a struct ucontext" >&5
echo $ECHO_N "checking how to access the program counter from a struct ucontext... $ECHO_C" >&6; }
- pc_fields=" uc_mcontext.gregs[REG_PC]" # Solaris x86 (32+64 bit)
- pc_fields="$pc_fields uc_mcontext.gregs[REG_EIP]" # Linux (i386)
- pc_fields="$pc_fields uc_mcontext.gregs[REG_RIP]" # Linux (x86_64)
- pc_fields="$pc_fields uc_mcontext.sc_ip" # Linux (ia64)
- pc_fields="$pc_fields uc_mcontext.uc_regs->gregs[PT_NIP]" # Linux (ppc)
- pc_fields="$pc_fields uc_mcontext.mc_eip" # FreeBSD (i386)
- pc_fields="$pc_fields uc_mcontext.mc_rip" # FreeBSD (x86_64 [*])
- pc_fields="$pc_fields uc_mcontext->ss.eip" # OS X (i386, <=10.4)
- pc_fields="$pc_fields uc_mcontext->__ss.__eip" # OS X (i386, >=10.5)
- pc_fields="$pc_fields uc_mcontext->ss.rip" # OS X (x86_64)
- pc_fields="$pc_fields uc_mcontext->__ss.__rip" # OS X (x86_64>=10.5 [*])
- pc_fields="$pc_fields uc_mcontext->ss.srr0" # OS X (ppc, ppc64 [*])
- pc_fields="$pc_fields uc_mcontext->__ss.__srr0" # OS X (ppc>=10.5 [*])
- pc_field_found=false
- for pc_field in $pc_fields; do
- if ! $pc_field_found; then
- cat >conftest.$ac_ext <<_ACEOF
+ pc_fields=" uc_mcontext.gregs[REG_PC]" # Solaris x86 (32 + 64 bit)
+ pc_fields="$pc_fields uc_mcontext.gregs[REG_EIP]" # Linux (i386)
+ pc_fields="$pc_fields uc_mcontext.gregs[REG_RIP]" # Linux (x86_64)
+ pc_fields="$pc_fields uc_mcontext.sc_ip" # Linux (ia64)
+ pc_fields="$pc_fields uc_mcontext.uc_regs->gregs[PT_NIP]" # Linux (ppc)
+ pc_fields="$pc_fields uc_mcontext.gregs[R15]" # Linux (arm old [untested])
+ pc_fields="$pc_fields uc_mcontext.arm_pc" # Linux (arm new [untested])
+ pc_fields="$pc_fields uc_mcontext.mc_eip" # FreeBSD (i386)
+ pc_fields="$pc_fields uc_mcontext.mc_rip" # FreeBSD (x86_64 [untested])
+ pc_fields="$pc_fields uc_mcontext.__gregs[_REG_EIP]" # NetBSD (i386)
+ pc_fields="$pc_fields uc_mcontext.__gregs[_REG_RIP]" # NetBSD (x86_64)
+ pc_fields="$pc_fields uc_mcontext->ss.eip" # OS X (i386, <=10.4)
+ pc_fields="$pc_fields uc_mcontext->__ss.__eip" # OS X (i386, >=10.5)
+ pc_fields="$pc_fields uc_mcontext->ss.rip" # OS X (x86_64)
+ pc_fields="$pc_fields uc_mcontext->__ss.__rip" # OS X (>=10.5 [untested])
+ pc_fields="$pc_fields uc_mcontext->ss.srr0" # OS X (ppc, ppc64 [untested])
+ pc_fields="$pc_fields uc_mcontext->__ss.__srr0" # OS X (>=10.5 [untested])
+ pc_field_found=false
+ for pc_field in $pc_fields; do
+ if ! $pc_field_found; then
+ cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#define _GNU_SOURCE 1
- #include <ucontext.h>
+ #include <ucontext.h>
int
main ()
{
@@ -24341,9 +24655,9 @@ cat >>confdefs.h <<_ACEOF
#define PC_FROM_UCONTEXT $pc_field
_ACEOF
- { echo "$as_me:$LINENO: result: $pc_field" >&5
+ { echo "$as_me:$LINENO: result: $pc_field" >&5
echo "${ECHO_T}$pc_field" >&6; }
- pc_field_found=true
+ pc_field_found=true
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
@@ -24352,13 +24666,68 @@ sed 's/^/| /' conftest.$ac_ext >&5
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- fi
- done
- if ! $pc_field_found; then
- { echo "$as_me:$LINENO: WARNING: Could not find the PC. Will not try to compile libprofiler..." >&5
-echo "$as_me: WARNING: Could not find the PC. Will not try to compile libprofiler..." >&2;}
- enable_cpu_profiler=no
- fi
+ fi
+ done
+ if ! $pc_field_found; then
+ pc_fields=" sc_eip" # OpenBSD (i386)
+ pc_fields="$pc_fields sc_rip" # OpenBSD (x86_64)
+ for pc_field in $pc_fields; do
+ if ! $pc_field_found; then
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <signal.h>
+int
+main ()
+{
+ucontext_t u; return u.$pc_field == 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+
+cat >>confdefs.h <<_ACEOF
+#define PC_FROM_UCONTEXT $pc_field
+_ACEOF
+
+ { echo "$as_me:$LINENO: result: $pc_field" >&5
+echo "${ECHO_T}$pc_field" >&6; }
+ pc_field_found=true
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ done
+ fi
+ if ! $pc_field_found; then
+ { echo "$as_me:$LINENO: WARNING: Could not find the PC. Will not output failed addresses..." >&5
+echo "$as_me: WARNING: Could not find the PC. Will not output failed addresses..." >&2;}
+ fi
fi
# We want to link in libunwind if it exists
@@ -25950,7 +26319,7 @@ _ACEOF
# Make the install prefix available, to figure out where to look for pprof
ac_cv_install_prefix="$prefix";
- if test x"$ac_cv_install_prefix" == x"NONE" ; then
+ if test x"$ac_cv_install_prefix" = x"NONE" ; then
ac_cv_install_prefix="$ac_default_prefix";
fi
@@ -26018,6 +26387,16 @@ else
WITH_HEAP_CHECKER_FALSE=
fi
+
+
+if test "$enable_debugalloc" = yes; then
+ WITH_DEBUGALLOC_TRUE=
+ WITH_DEBUGALLOC_FALSE='#'
+else
+ WITH_DEBUGALLOC_TRUE='#'
+ WITH_DEBUGALLOC_FALSE=
+fi
+
# We make tcmalloc.so if either heap-profiler or heap-checker is asked for.
@@ -26227,6 +26606,13 @@ echo "$as_me: error: conditional \"WITH_HEAP_CHECKER\" was never defined.
Usually this means the macro was only invoked conditionally." >&2;}
{ (exit 1); exit 1; }; }
fi
+if test -z "${WITH_DEBUGALLOC_TRUE}" && test -z "${WITH_DEBUGALLOC_FALSE}"; then
+ { { echo "$as_me:$LINENO: error: conditional \"WITH_DEBUGALLOC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+echo "$as_me: error: conditional \"WITH_DEBUGALLOC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+ { (exit 1); exit 1; }; }
+fi
if test -z "${WITH_HEAP_PROFILER_OR_CHECKER_TRUE}" && test -z "${WITH_HEAP_PROFILER_OR_CHECKER_FALSE}"; then
{ { echo "$as_me:$LINENO: error: conditional \"WITH_HEAP_PROFILER_OR_CHECKER\" was never defined.
Usually this means the macro was only invoked conditionally." >&5
@@ -26541,7 +26927,7 @@ exec 6>&1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by google-perftools $as_me 1.3, which was
+This file was extended by google-perftools $as_me 1.4, which was
generated by GNU Autoconf 2.61. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -26594,7 +26980,7 @@ Report bugs to <bug-autoconf@gnu.org>."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
-google-perftools config.status 1.3
+google-perftools config.status 1.4
configured by $0, generated by GNU Autoconf 2.61,
with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
@@ -26839,6 +27225,9 @@ am__leading_dot!$am__leading_dot$ac_delim
AMTAR!$AMTAR$ac_delim
am__tar!$am__tar$ac_delim
am__untar!$am__untar$ac_delim
+TC_VERSION_MAJOR!$TC_VERSION_MAJOR$ac_delim
+TC_VERSION_MINOR!$TC_VERSION_MINOR$ac_delim
+TC_VERSION_PATCH!$TC_VERSION_PATCH$ac_delim
CC!$CC$ac_delim
CFLAGS!$CFLAGS$ac_delim
LDFLAGS!$LDFLAGS$ac_delim
@@ -26867,9 +27256,6 @@ GCC_FALSE!$GCC_FALSE$ac_delim
OBJCOPY!$OBJCOPY$ac_delim
HAVE_OBJCOPY_WEAKEN_TRUE!$HAVE_OBJCOPY_WEAKEN_TRUE$ac_delim
HAVE_OBJCOPY_WEAKEN_FALSE!$HAVE_OBJCOPY_WEAKEN_FALSE$ac_delim
-SED!$SED$ac_delim
-GREP!$GREP$ac_delim
-EGREP!$EGREP$ac_delim
_ACEOF
if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then
@@ -26911,6 +27297,9 @@ _ACEOF
ac_delim='%!_!# '
for ac_last_try in false false false false false :; do
cat >conf$$subs.sed <<_ACEOF
+SED!$SED$ac_delim
+GREP!$GREP$ac_delim
+EGREP!$EGREP$ac_delim
LN_S!$LN_S$ac_delim
ECHO!$ECHO$ac_delim
AR!$AR$ac_delim
@@ -26945,6 +27334,8 @@ WITH_HEAP_PROFILER_TRUE!$WITH_HEAP_PROFILER_TRUE$ac_delim
WITH_HEAP_PROFILER_FALSE!$WITH_HEAP_PROFILER_FALSE$ac_delim
WITH_HEAP_CHECKER_TRUE!$WITH_HEAP_CHECKER_TRUE$ac_delim
WITH_HEAP_CHECKER_FALSE!$WITH_HEAP_CHECKER_FALSE$ac_delim
+WITH_DEBUGALLOC_TRUE!$WITH_DEBUGALLOC_TRUE$ac_delim
+WITH_DEBUGALLOC_FALSE!$WITH_DEBUGALLOC_FALSE$ac_delim
WITH_HEAP_PROFILER_OR_CHECKER_TRUE!$WITH_HEAP_PROFILER_OR_CHECKER_TRUE$ac_delim
WITH_HEAP_PROFILER_OR_CHECKER_FALSE!$WITH_HEAP_PROFILER_OR_CHECKER_FALSE$ac_delim
WITH_STACK_TRACE_TRUE!$WITH_STACK_TRACE_TRUE$ac_delim
@@ -26953,7 +27344,7 @@ LIBOBJS!$LIBOBJS$ac_delim
LTLIBOBJS!$LTLIBOBJS$ac_delim
_ACEOF
- if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 40; then
+ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 45; then
break
elif $ac_last_try; then
{ { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
diff --git a/configure.ac b/configure.ac
index 31e9f69..9db399a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4,7 +4,7 @@
# make sure we're interpreted by some minimal autoconf
AC_PREREQ(2.57)
-AC_INIT(google-perftools, 1.3, opensource@google.com)
+AC_INIT(google-perftools, 1.4, opensource@google.com)
# The argument here is just something that should be in the current directory
# (for sanity checking)
AC_CONFIG_SRCDIR(README)
@@ -12,6 +12,15 @@ AC_CANONICAL_HOST
AM_INIT_AUTOMAKE([dist-zip])
AM_CONFIG_HEADER(src/config.h)
+# Export the version information (for tc_version and friends)
+TC_VERSION_MAJOR=`expr "$PACKAGE_VERSION" : '\([[0-9]]*\)'`
+TC_VERSION_MINOR=`expr "$PACKAGE_VERSION" : '[[^.]]*\.\([[0-9]]*\)'`
+TC_VERSION_PATCH=`expr "$PACKAGE_VERSION" : '[[^.0-9]]*\([[^0-9]]*\)$'`
+AC_SUBST(TC_VERSION_MAJOR)
+AC_SUBST(TC_VERSION_MINOR)
+AC_SUBST(TC_VERSION_PATCH)
+AC_SUBST(PACKAGE_STRING)
+
# The user can choose not to compile in the heap-profiler, the
# heap-checker, or the cpu-profiler. There's also the possibility
# for a 'fully minimal' compile, which leaves out the stacktrace
@@ -20,10 +29,12 @@ AM_CONFIG_HEADER(src/config.h)
default_enable_cpu_profiler=yes
default_enable_heap_profiler=yes
default_enable_heap_checker=yes
+default_enable_debugalloc=yes
default_enable_minimal=no
need_nanosleep=yes # Used later, to decide if to run ACX_NANOSLEEP
case "$host" in
- *-mingw*) default_enable_minimal=yes; need_nanosleep=no;;
+ *-mingw*) default_enable_minimal=yes; default_enable_debugalloc=no;
+ need_nanosleep=no;;
*-cygwin*) default_enable_heap_checker=no; default_enable_cpu_profiler=no;;
*-freebsd*) default_enable_heap_checker=no;;
*-darwin*) default_enable_heap_checker=no;;
@@ -44,9 +55,14 @@ AC_ARG_ENABLE([heap-checker],
[do not build the heap checker])],
[],
[enable_heap_checker="$default_enable_heap_checker"])
+AC_ARG_ENABLE([debugalloc],
+ [AS_HELP_STRING([--disable-debugalloc],
+ [do not build versions of libs with debugalloc])],
+ [],
+ [enable_debugalloc="$default_enable_debugalloc"])
AC_ARG_ENABLE([minimal],
[AS_HELP_STRING([--enable-minimal],
- [build only tcmalloc-minimal])],
+ [build only tcmalloc-minimal (and maybe tcmalloc-minimal-debug)])],
[],
[enable_minimal="$default_enable_minimal"])
if test "$enable_minimal" = yes; then
@@ -63,11 +79,6 @@ AC_PROG_CXX
AM_CONDITIONAL(GCC, test "$GCC" = yes) # let the Makefile know if we're gcc
AM_PROG_CC_C_O # shrug: autogen.sh suddenly needs this for some reason
-# We work behind libtool's back, replacing 'ar' by 'ld -r' in some
-# situations. The only issue is that 'ld -r' output doesn't support
-# ranlib. Nobody needs ranlib anymore, so it's safe to just disable it.
-RANLIB=":"
-
# Check if we have an objcopy installed that supports -W
AC_CHECK_TOOL([OBJCOPY], [objcopy], [])
AM_CONDITIONAL(HAVE_OBJCOPY_WEAKEN, ["$OBJCOPY" -W malloc /bin/ls /dev/null])
@@ -109,12 +120,14 @@ AC_CHECK_HEADERS(libunwind.h) # for stacktrace
AC_CHECK_HEADERS(unwind.h) # for stacktrace
AC_CHECK_HEADERS(sched.h) # for being nice in our spinlock code
AC_CHECK_HEADERS(ucontext.h) # for profiler.cc (cpu profiler)
-AC_CHECK_HEADERS(conflict-signal.h) # defined on some windows platforms
+AC_CHECK_HEADERS(cygwin/signal.h) # ucontext on cywgin
+AC_CHECK_HEADERS(conflict-signal.h) # defined on some windows platforms?
AC_CHECK_HEADERS(sys/prctl.h) # for thread_lister (needed by leak-checker)
AC_CHECK_HEADERS(linux/ptrace.h)# also needed by leak-checker
AC_CHECK_HEADERS(sys/syscall.h)
AC_CHECK_HEADERS(sys/socket.h) # optional; for forking out to symbolizer
AC_CHECK_HEADERS(sys/wait.h) # optional; for forking out to symbolizer
+AC_CHECK_HEADERS(poll.h) # optional; for forking out to symbolizer
AC_CHECK_HEADERS(fcntl.h) # for tcmalloc_unittest
AC_CHECK_HEADERS(grp.h) # for heapchecker_unittest
AC_CHECK_HEADERS(pwd.h) # for heapchecker_unittest
@@ -167,36 +180,8 @@ AC_TRY_COMPILE([#include <stdint.h>],
# bother if we're not doing cpu-profiling.
# [*] means that we've not actually tested one of these systems
if test "$enable_cpu_profiler" = yes; then
- AC_MSG_CHECKING([how to access the program counter from a struct ucontext])
- pc_fields=" uc_mcontext.gregs[[REG_PC]]" # Solaris x86 (32+64 bit)
- pc_fields="$pc_fields uc_mcontext.gregs[[REG_EIP]]" # Linux (i386)
- pc_fields="$pc_fields uc_mcontext.gregs[[REG_RIP]]" # Linux (x86_64)
- pc_fields="$pc_fields uc_mcontext.sc_ip" # Linux (ia64)
- pc_fields="$pc_fields uc_mcontext.uc_regs->gregs[[PT_NIP]]" # Linux (ppc)
- pc_fields="$pc_fields uc_mcontext.mc_eip" # FreeBSD (i386)
- pc_fields="$pc_fields uc_mcontext.mc_rip" # FreeBSD (x86_64 [*])
- pc_fields="$pc_fields uc_mcontext->ss.eip" # OS X (i386, <=10.4)
- pc_fields="$pc_fields uc_mcontext->__ss.__eip" # OS X (i386, >=10.5)
- pc_fields="$pc_fields uc_mcontext->ss.rip" # OS X (x86_64)
- pc_fields="$pc_fields uc_mcontext->__ss.__rip" # OS X (x86_64>=10.5 [*])
- pc_fields="$pc_fields uc_mcontext->ss.srr0" # OS X (ppc, ppc64 [*])
- pc_fields="$pc_fields uc_mcontext->__ss.__srr0" # OS X (ppc>=10.5 [*])
- pc_field_found=false
- for pc_field in $pc_fields; do
- if ! $pc_field_found; then
- AC_TRY_COMPILE([#define _GNU_SOURCE 1
- #include <ucontext.h>],
- [ucontext_t u; return u.$pc_field == 0;],
- AC_DEFINE_UNQUOTED(PC_FROM_UCONTEXT, $pc_field,
- How to access the PC from a struct ucontext)
- AC_MSG_RESULT([$pc_field])
- pc_field_found=true)
- fi
- done
- if ! $pc_field_found; then
- AC_MSG_WARN(Could not find the PC. Will not try to compile libprofiler...)
- enable_cpu_profiler=no
- fi
+ AC_PC_FROM_UCONTEXT(AC_MSG_WARN(Could not find the PC. Will not try to compile libprofiler...)
+ enable_cpu_profiler=no)
fi
# We want to link in libunwind if it exists
@@ -305,6 +290,7 @@ AM_CONDITIONAL(MINGW, expr $host : '.*-mingw' >/dev/null 2>&1)
AM_CONDITIONAL(WITH_CPU_PROFILER, test "$enable_cpu_profiler" = yes)
AM_CONDITIONAL(WITH_HEAP_PROFILER, test "$enable_heap_profiler" = yes)
AM_CONDITIONAL(WITH_HEAP_CHECKER, test "$enable_heap_checker" = yes)
+AM_CONDITIONAL(WITH_DEBUGALLOC, test "$enable_debugalloc" = yes)
# We make tcmalloc.so if either heap-profiler or heap-checker is asked for.
AM_CONDITIONAL(WITH_HEAP_PROFILER_OR_CHECKER,
test "$enable_heap_profiler" = yes -o \
diff --git a/doc/tcmalloc.html b/doc/tcmalloc.html
index 17d1095..4f60f92 100644
--- a/doc/tcmalloc.html
+++ b/doc/tcmalloc.html
@@ -456,21 +456,23 @@ multi-threaded case).</p>
<p>You can more finely control the behavior of the tcmalloc via
environment variables.</p>
+<p>Generally useful flags:</p>
+
<table frame=box rules=sides cellpadding=5 width=100%>
<tr valign=top>
<td><code>TCMALLOC_SAMPLE_PARAMETER</code></td>
<td>default: 524288</td>
<td>
- The approximate gap between sampling actions. That is, we take
- one sample approximately every
- <code>tcmalloc_sample_parameter</code> bytes of allocation.
+ The approximate gap between sampling actions. That is, we
+ take one sample approximately once every
+ <code>tcmalloc_sample_parmeter</code> bytes of allocation.
</td>
</tr>
<tr valign=top>
<td><code>TCMALLOC_RELEASE_RATE</code></td>
- <td>default: 1</td>
+ <td>default: 1.0</td>
<td>
Rate at which we release unused memory to the system, via
<code>madvise(MADV_DONTNEED)</code>, on systems that support
@@ -512,6 +514,31 @@ environment variables.</p>
</td>
</tr>
+</table>
+
+<p>Advanced "tweaking" flags, that control more precisely how tcmalloc
+tries to allocate memory from the kernel.</p>
+
+<table frame=box rules=sides cellpadding=5 width=100%>
+
+<tr valign=top>
+ <td><code>TCMALLOC_SKIP_MMAP</code></td>
+ <td>default: false</td>
+ <td>
+ If true, do not try to use <code>mmap</code> to obtain memory
+ from the kernel.
+ </td>
+</tr>
+
+<tr valign=top>
+ <td><code>TCMALLOC_SKIP_SBRK</code></td>
+ <td>default: false</td>
+ <td>
+ If true, do not try to use <code>sbrk</code> to obtain memory
+ from the kernel.
+ </td>
+</tr>
+
<tr valign=top>
<td><code>TCMALLOC_DEVMEM_START</code></td>
<td>default: 0</td>
@@ -540,14 +567,40 @@ environment variables.</p>
</tr>
<tr valign=top>
- <td><code>TCMALLOC_SKIP_MMAP</code></td>
+ <td><code>TCMALLOC_MEMFS_MALLOC_PATH</code></td>
+ <td>default: ""</td>
+ <td>
+ If set, specify a path where hugetlbfs or tmpfs is mounted.
+ This may allow for speedier allocations.
+ </td>
+</tr>
+
+<tr valign=top>
+ <td><code>TCMALLOC_MEMFS_LIMIT_MB</code></td>
+ <td>default: 0</td>
+ <td>
+ Limit total memfs allocation size to specified number of MB.
+ 0 means "no limit".
+ </td>
+</tr>
+
+<tr valign=top>
+ <td><code>TCMALLOC_MEMFS_ABORT_ON_FAIL</code></td>
<td>default: false</td>
<td>
- If true, do not try to use <code>mmap</code> to obtain memory
- from the kernel.
+ If true, abort() whenever memfs_malloc fails to satisfy an allocation.
+ </td>
+</tr>
+
+<tr valign=top>
+ <td><code>TCMALLOC_MEMFS_IGNORE_MMAP_FAIL</code></td>
+ <td>default: false</td>
+ <td>
+ If true, ignore failures from mmap.
</td>
</tr>
+
</table>
diff --git a/google-perftools.sln b/google-perftools.sln
index 2184420..bbdad98 100755
--- a/google-perftools.sln
+++ b/google-perftools.sln
@@ -38,6 +38,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "markidle_unittest", "vsproj
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "packed-cache_test", "vsprojects\packed-cache_test\packed-cache_test.vcproj", "{605D3CED-B530-424E-B7D2-2A31F14FD570}"
ProjectSection(ProjectDependencies) = postProject
+ {55E2B3AE-3CA1-4DB6-97F7-0A044D6F446F} = {55E2B3AE-3CA1-4DB6-97F7-0A044D6F446F}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pagemap_unittest", "vsprojects\pagemap_unittest\pagemap_unittest.vcproj", "{9765198D-5305-4AB0-9A21-A0CD8201EB2A}"
diff --git a/m4/install_prefix.m4 b/m4/install_prefix.m4
index d4afc93..ef33f42 100644
--- a/m4/install_prefix.m4
+++ b/m4/install_prefix.m4
@@ -1,6 +1,6 @@
AC_DEFUN([AC_INSTALL_PREFIX],
[ac_cv_install_prefix="$prefix";
- if test x"$ac_cv_install_prefix" == x"NONE" ; then
+ if test x"$ac_cv_install_prefix" = x"NONE" ; then
ac_cv_install_prefix="$ac_default_prefix";
fi
AC_DEFINE_UNQUOTED(INSTALL_PREFIX, "$ac_cv_install_prefix",
diff --git a/m4/pc_from_ucontext.m4 b/m4/pc_from_ucontext.m4
new file mode 100644
index 0000000..8c4c5ce
--- /dev/null
+++ b/m4/pc_from_ucontext.m4
@@ -0,0 +1,56 @@
+# We want to access the "PC" (Program Counter) register from a struct
+# ucontext. Every system has its own way of doing that. We try all the
+# possibilities we know about. Note REG_PC should come first (REG_RIP
+# is also defined on solaris, but does the wrong thing).
+
+# OpenBSD doesn't have ucontext.h, but we can get PC from ucontext_t
+# by using signal.h.
+
+AC_DEFUN([AC_PC_FROM_UCONTEXT],
+ [AC_MSG_CHECKING([how to access the program counter from a struct ucontext])
+ pc_fields=" uc_mcontext.gregs[[REG_PC]]" # Solaris x86 (32 + 64 bit)
+ pc_fields="$pc_fields uc_mcontext.gregs[[REG_EIP]]" # Linux (i386)
+ pc_fields="$pc_fields uc_mcontext.gregs[[REG_RIP]]" # Linux (x86_64)
+ pc_fields="$pc_fields uc_mcontext.sc_ip" # Linux (ia64)
+ pc_fields="$pc_fields uc_mcontext.uc_regs->gregs[[PT_NIP]]" # Linux (ppc)
+ pc_fields="$pc_fields uc_mcontext.gregs[[R15]]" # Linux (arm old [untested])
+ pc_fields="$pc_fields uc_mcontext.arm_pc" # Linux (arm new [untested])
+ pc_fields="$pc_fields uc_mcontext.mc_eip" # FreeBSD (i386)
+ pc_fields="$pc_fields uc_mcontext.mc_rip" # FreeBSD (x86_64 [untested])
+ pc_fields="$pc_fields uc_mcontext.__gregs[[_REG_EIP]]" # NetBSD (i386)
+ pc_fields="$pc_fields uc_mcontext.__gregs[[_REG_RIP]]" # NetBSD (x86_64)
+ pc_fields="$pc_fields uc_mcontext->ss.eip" # OS X (i386, <=10.4)
+ pc_fields="$pc_fields uc_mcontext->__ss.__eip" # OS X (i386, >=10.5)
+ pc_fields="$pc_fields uc_mcontext->ss.rip" # OS X (x86_64)
+ pc_fields="$pc_fields uc_mcontext->__ss.__rip" # OS X (>=10.5 [untested])
+ pc_fields="$pc_fields uc_mcontext->ss.srr0" # OS X (ppc, ppc64 [untested])
+ pc_fields="$pc_fields uc_mcontext->__ss.__srr0" # OS X (>=10.5 [untested])
+ pc_field_found=false
+ for pc_field in $pc_fields; do
+ if ! $pc_field_found; then
+ AC_TRY_COMPILE([#define _GNU_SOURCE 1
+ #include <ucontext.h>],
+ [ucontext_t u; return u.$pc_field == 0;],
+ AC_DEFINE_UNQUOTED(PC_FROM_UCONTEXT, $pc_field,
+ How to access the PC from a struct ucontext)
+ AC_MSG_RESULT([$pc_field])
+ pc_field_found=true)
+ fi
+ done
+ if ! $pc_field_found; then
+ pc_fields=" sc_eip" # OpenBSD (i386)
+ pc_fields="$pc_fields sc_rip" # OpenBSD (x86_64)
+ for pc_field in $pc_fields; do
+ if ! $pc_field_found; then
+ AC_TRY_COMPILE([#include <signal.h>],
+ [ucontext_t u; return u.$pc_field == 0;],
+ AC_DEFINE_UNQUOTED(PC_FROM_UCONTEXT, $pc_field,
+ How to access the PC from a struct ucontext)
+ AC_MSG_RESULT([$pc_field])
+ pc_field_found=true)
+ fi
+ done
+ fi
+ if ! $pc_field_found; then
+ AC_MSG_WARN(Could not find the PC. Will not output failed addresses...)
+ fi])
diff --git a/packages/deb/changelog b/packages/deb/changelog
index 4154dfb..f05cfd5 100644
--- a/packages/deb/changelog
+++ b/packages/deb/changelog
@@ -1,3 +1,9 @@
+google-perftools (1.4-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Google Inc. <opensource@google.com> Thu, 10 Sep 2009 13:51:15 -0700
+
google-perftools (1.3-1) unstable; urgency=low
* New upstream release.
diff --git a/src/base/atomicops-internals-macosx.h b/src/base/atomicops-internals-macosx.h
index 4120f8c..430b9ee 100644
--- a/src/base/atomicops-internals-macosx.h
+++ b/src/base/atomicops-internals-macosx.h
@@ -26,9 +26,6 @@
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * ---
- * Author: Mike Burrows
*/
// Implementation of atomic operations for Mac OS X. This file should not
@@ -310,7 +307,11 @@ inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
"emms\n\t" // Reset FP registers
: "=m" (*ptr)
: "m" (value)
- : "memory", "%mm0");
+ : // mark the FP stack and mmx registers as clobbered
+ "st", "st(1)", "st(2)", "st(3)", "st(4)",
+ "st(5)", "st(6)", "st(7)", "mm0", "mm1",
+ "mm2", "mm3", "mm4", "mm5", "mm6", "mm7");
+
}
inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
@@ -320,7 +321,11 @@ inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
"emms\n\t" // Reset FP registers
: "=m" (value)
: "m" (*ptr)
- : "memory", "%mm0");
+ : // mark the FP stack and mmx registers as clobbered
+ "st", "st(1)", "st(2)", "st(3)", "st(4)",
+ "st(5)", "st(6)", "st(7)", "mm0", "mm1",
+ "mm2", "mm3", "mm4", "mm5", "mm6", "mm7");
+
return value;
}
#endif
diff --git a/src/base/atomicops-internals-x86.cc b/src/base/atomicops-internals-x86.cc
index 39ed73d..4f75d47 100644
--- a/src/base/atomicops-internals-x86.cc
+++ b/src/base/atomicops-internals-x86.cc
@@ -28,8 +28,6 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* ---
- * Author: Mike Burrows
- *
* This module gets enough CPU information to optimize the
* atomicops module on x86.
*/
diff --git a/src/base/atomicops-internals-x86.h b/src/base/atomicops-internals-x86.h
index ba6a3b7..c34aa5c 100644
--- a/src/base/atomicops-internals-x86.h
+++ b/src/base/atomicops-internals-x86.h
@@ -361,7 +361,10 @@ inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
"emms\n\t" // Empty mmx state/Reset FP regs
: "=m" (*ptr)
: "m" (value)
- : "memory", "%mm0");
+ : // mark the FP stack and mmx registers as clobbered
+ "st", "st(1)", "st(2)", "st(3)", "st(4)",
+ "st(5)", "st(6)", "st(7)", "mm0", "mm1",
+ "mm2", "mm3", "mm4", "mm5", "mm6", "mm7");
}
inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
@@ -381,7 +384,10 @@ inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
"emms\n\t" // Empty mmx state/Reset FP regs
: "=m" (value)
: "m" (*ptr)
- : "%mm0"); // Do not mark mem as clobbered
+ : // mark the FP stack and mmx registers as clobbered
+ "st", "st(1)", "st(2)", "st(3)", "st(4)",
+ "st(5)", "st(6)", "st(7)", "mm0", "mm1",
+ "mm2", "mm3", "mm4", "mm5", "mm6", "mm7");
return value;
}
diff --git a/src/base/basictypes.h b/src/base/basictypes.h
index 57a6d82..e4d4140 100644
--- a/src/base/basictypes.h
+++ b/src/base/basictypes.h
@@ -106,6 +106,15 @@ const int64 kint64min = ( ((( int64) kint32min) << 32) | 0 );
#define PRIxPTR "lx"
#endif
+// Also allow for printing of a pthread_t.
+#define GPRIuPTHREAD "lu"
+#define GPRIxPTHREAD "lx"
+#if defined(__CYGWIN__) || defined(__CYGWIN32__) || defined(__APPLE__)
+#define PRINTABLE_PTHREAD(pthreadt) reinterpret_cast<uintptr_t>(pthreadt)
+#else
+#define PRINTABLE_PTHREAD(pthreadt) pthreadt
+#endif
+
// A macro to disallow the evil copy constructor and operator= functions
// This should be used in the private: declarations for a class
#define DISALLOW_EVIL_CONSTRUCTORS(TypeName) \
diff --git a/src/base/dynamic_annotations.cc b/src/base/dynamic_annotations.cc
index e370bd5..c8bbcd7 100644
--- a/src/base/dynamic_annotations.cc
+++ b/src/base/dynamic_annotations.cc
@@ -59,6 +59,9 @@ extern "C" void AnnotateCondVarSignalAll(const char *file, int line,
extern "C" void AnnotatePublishMemoryRange(const char *file, int line,
const volatile void *address,
long size){}
+extern "C" void AnnotateUnpublishMemoryRange(const char *file, int line,
+ const volatile void *address,
+ long size){}
extern "C" void AnnotatePCQCreate(const char *file, int line,
const volatile void *pcq){}
extern "C" void AnnotatePCQDestroy(const char *file, int line,
diff --git a/src/base/dynamic_annotations.h b/src/base/dynamic_annotations.h
index e189407..5995ac4 100644
--- a/src/base/dynamic_annotations.h
+++ b/src/base/dynamic_annotations.h
@@ -128,6 +128,80 @@
#define ANNOTATE_PUBLISH_MEMORY_RANGE(pointer, size) \
AnnotatePublishMemoryRange(__FILE__, __LINE__, pointer, size)
+ // Report that the bytes in the range [pointer, pointer+size) are not shared
+ // between threads any more and can be safely used by the current thread w/o
+ // synchronization. The race checker will create a happens-before arc from
+ // all previous accesses to this memory to this call.
+ //
+ // This annotation could be applied to complex objects, such as STL
+ // containers, with one condition: the accesses to the object itself
+ // and its internal data should not be separated with any synchronization.
+ //
+ // Example that works:
+ //
+ // map<int, int> the_map;
+ // void Thread1() {
+ // MutexLock lock(&mu);
+ // // Ok: accesses to the_map and its internal data is not separated by
+ // // synchronization.
+ // the_map[1]++;
+ // }
+ // void Thread2() {
+ // {
+ // MutexLock lock(&mu);
+ // ...
+ // // because of some reason we know that the_map will not be used by
+ // // other threads any more
+ // ANNOTATE_UNPUBLISH_MEMORY_RANGE(&the_map, sizeof(the_map));
+ // }
+ // the_map->DoSomething();
+ // }
+ //
+ // Example that does not work (due to the way happens-before arcs are
+ // represented in some race detectors):
+ //
+ // void Thread1() {
+ // MutexLock lock(&mu);
+ // int *guts_of_the_map = &(*the_map)[1];
+ // // we have some synchronization between access to 'c' and its guts.
+ // // This will make ANNOTATE_UNPUBLISH_MEMORY_RANGE in Thread2 useless.
+ // some_other_lock_or_other_synchronization_utility.Lock();
+ // (*guts_of_the_map)++;
+ // ...
+ // }
+ //
+ // void Thread1() { // same as above...
+ #define ANNOTATE_UNPUBLISH_MEMORY_RANGE(pointer, size) \
+ AnnotateUnpublishMemoryRange(__FILE__, __LINE__, pointer, size)
+
+ // This annotation should be used to annotate thread-safe swapping of
+ // containers. Required only when using hybrid (i.e. not pure happens-before)
+ // detectors.
+ //
+ // This annotation has the same limitation as ANNOTATE_UNPUBLISH_MEMORY_RANGE
+ // (see above).
+ //
+ // Example:
+ // map<int, int> the_map;
+ // void Thread1() {
+ // MutexLock lock(&mu);
+ // the_map[1]++;
+ // }
+ // void Thread2() {
+ // map<int,int> tmp;
+ // {
+ // MutexLock lock(&mu);
+ // the_map.swap(tmp);
+ // ANNOTATE_SWAP_MEMORY_RANGE(&the_map, sizeof(the_map));
+ // }
+ // tmp->DoSomething();
+ // }
+ #define ANNOTATE_SWAP_MEMORY_RANGE(pointer, size) \
+ do { \
+ ANNOTATE_UNPUBLISH_MEMORY_RANGE(pointer, size); \
+ ANNOTATE_PUBLISH_MEMORY_RANGE(pointer, size); \
+ } while (0)
+
// Instruct the tool to create a happens-before arc between mu->Unlock() and
// mu->Lock(). This annotation may slow down the race detector; normally it
// is used only when it would be difficult to annotate each of the mutex's
@@ -274,7 +348,8 @@
#define ANNOTATE_HAPPENS_BEFORE(obj) // empty
#define ANNOTATE_HAPPENS_AFTER(obj) // empty
#define ANNOTATE_PUBLISH_MEMORY_RANGE(address, size) // empty
- #define ANNOTATE_PUBLISH_OBJECT(address) // empty
+ #define ANNOTATE_UNPUBLISH_MEMORY_RANGE(address, size) // empty
+ #define ANNOTATE_SWAP_MEMORY_RANGE(address, size) // empty
#define ANNOTATE_PCQ_CREATE(pcq) // empty
#define ANNOTATE_PCQ_DESTROY(pcq) // empty
#define ANNOTATE_PCQ_PUT(pcq) // empty
@@ -314,6 +389,9 @@ extern "C" void AnnotateCondVarSignalAll(const char *file, int line,
extern "C" void AnnotatePublishMemoryRange(const char *file, int line,
const volatile void *address,
long size);
+extern "C" void AnnotateUnpublishMemoryRange(const char *file, int line,
+ const volatile void *address,
+ long size);
extern "C" void AnnotatePCQCreate(const char *file, int line,
const volatile void *pcq);
extern "C" void AnnotatePCQDestroy(const char *file, int line,
diff --git a/src/base/logging.h b/src/base/logging.h
index 0444740..3b1dacf 100644
--- a/src/base/logging.h
+++ b/src/base/logging.h
@@ -42,7 +42,7 @@
#ifdef HAVE_UNISTD_H
#include <unistd.h> // for write()
#endif
-#include <string.h> // for strlen()
+#include <string.h> // for strlen(), strcmp()
#include <assert.h>
#include <errno.h> // for errno
#include "base/commandlineflags.h"
@@ -136,6 +136,18 @@ enum { DEBUG_MODE = 1 };
#define CHECK_GE(val1, val2) CHECK_OP(>=, val1, val2)
#define CHECK_GT(val1, val2) CHECK_OP(> , val1, val2)
+// A synonym for CHECK_* that is used in some unittests.
+#define EXPECT_EQ(val1, val2) CHECK_EQ(val1, val2)
+#define EXPECT_NE(val1, val2) CHECK_NE(val1, val2)
+#define EXPECT_LE(val1, val2) CHECK_LE(val1, val2)
+#define EXPECT_LT(val1, val2) CHECK_LT(val1, val2)
+#define EXPECT_GE(val1, val2) CHECK_GE(val1, val2)
+#define EXPECT_GT(val1, val2) CHECK_GT(val1, val2)
+// As are these variants.
+#define EXPECT_TRUE(cond) CHECK(cond)
+#define EXPECT_FALSE(cond) CHECK(!(cond))
+#define EXPECT_STREQ(a, b) CHECK(strcmp(a, b) == 0)
+
// Used for (libc) functions that return -1 and set errno
#define CHECK_ERR(invocation) PCHECK((invocation) != -1)
diff --git a/src/base/low_level_alloc.cc b/src/base/low_level_alloc.cc
index 4fa78c4..900ae4e 100644
--- a/src/base/low_level_alloc.cc
+++ b/src/base/low_level_alloc.cc
@@ -26,9 +26,6 @@
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * ---
- * Author: Mike Burrows
*/
// A low-level allocator that can be used by other low-level
diff --git a/src/base/low_level_alloc.h b/src/base/low_level_alloc.h
index 18b8547..0df1298 100644
--- a/src/base/low_level_alloc.h
+++ b/src/base/low_level_alloc.h
@@ -26,9 +26,6 @@
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * ---
- * Author: Mike Burrows
*/
#if !defined(_BASE_LOW_LEVEL_ALLOC_H_)
diff --git a/src/base/simple_mutex.h b/src/base/simple_mutex.h
index 610e99c..a97172a 100644
--- a/src/base/simple_mutex.h
+++ b/src/base/simple_mutex.h
@@ -38,9 +38,12 @@
// AC_RWLOCK
// The latter is defined in ../autoconf.
//
-// This class is meant to be internal-only, so it's defined in the
-// global namespace. If you want to expose it, you'll want to move
-// it to the Google namespace.
+// This class is meant to be internal-only and should be wrapped by an
+// internal namespace. Before you use this module, please give the
+// name of your internal namespace for this module. Or, if you want
+// to expose it, you'll want to move it to the Google namespace. We
+// cannot put this class in global namespace because there can be some
+// problems when we have multiple versions of Mutex in each shared object.
//
// NOTE: TryLock() is broken for NO_THREADS mode, at least in NDEBUG
// mode.
@@ -87,6 +90,16 @@
// colon-initializer) and set it to true via a function that always
// evaluates to true, but that the compiler can't know always
// evaluates to true. This should be good enough.
+//
+// A related issue is code that could try to access the mutex
+// after it's been destroyed in the global destructors (because
+// the Mutex global destructor runs before some other global
+// destructor, that tries to acquire the mutex). The way we
+// deal with this is by taking a constructor arg that global
+// mutexes should pass in, that causes the destructor to do no
+// work. We still depend on the compiler not doing anything
+// weird to a Mutex's memory after it is destroyed, but for a
+// static global variable, that's pretty safe.
#ifndef GOOGLE_MUTEX_H_
#define GOOGLE_MUTEX_H_
@@ -124,10 +137,26 @@
# error Need to implement mutex.h for your architecture, or #define NO_THREADS
#endif
+#include <assert.h>
+#include <stdlib.h> // for abort()
+
+#define MUTEX_NAMESPACE perftools_mutex_namespace
+
+namespace MUTEX_NAMESPACE {
+
class Mutex {
public:
- // Create a Mutex that is not held by anybody.
+ // This is used for the single-arg constructor
+ enum LinkerInitialized { LINKER_INITIALIZED };
+
+ // Create a Mutex that is not held by anybody. This constructor is
+ // typically used for Mutexes allocated on the heap or the stack.
inline Mutex();
+ // This constructor should be used for global, static Mutex objects.
+ // It inhibits work being done by the destructor, which makes it
+ // safer for code that tries to acqiure this mutex in their global
+ // destructor.
+ inline Mutex(LinkerInitialized);
// Destructor
inline ~Mutex();
@@ -150,6 +179,8 @@ class Mutex {
// when we tell it to, and never makes assumptions is_safe_ is
// always true. volatile is the most reliable way to do that.
volatile bool is_safe_;
+ // This indicates which constructor was called.
+ bool destroy_;
inline void SetIsSafe() { is_safe_ = true; }
@@ -172,9 +203,9 @@ class Mutex {
// In debug mode, we assert these invariants, while in non-debug mode
// we do nothing, for efficiency. That's why everything is in an
// assert.
-#include <assert.h>
Mutex::Mutex() : mutex_(0) { }
+Mutex::Mutex(Mutex::LinkerInitialized) : mutex_(0) { }
Mutex::~Mutex() { assert(mutex_ == 0); }
void Mutex::Lock() { assert(--mutex_ == -1); }
void Mutex::Unlock() { assert(mutex_++ == -1); }
@@ -184,8 +215,15 @@ void Mutex::ReaderUnlock() { assert(mutex_-- > 0); }
#elif defined(_WIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__)
-Mutex::Mutex() { InitializeCriticalSection(&mutex_); SetIsSafe(); }
-Mutex::~Mutex() { DeleteCriticalSection(&mutex_); }
+Mutex::Mutex() : destroy_(true) {
+ InitializeCriticalSection(&mutex_);
+ SetIsSafe();
+}
+Mutex::Mutex(LinkerInitialized) : destroy_(false) {
+ InitializeCriticalSection(&mutex_);
+ SetIsSafe();
+}
+Mutex::~Mutex() { if (destroy_) DeleteCriticalSection(&mutex_); }
void Mutex::Lock() { if (is_safe_) EnterCriticalSection(&mutex_); }
void Mutex::Unlock() { if (is_safe_) LeaveCriticalSection(&mutex_); }
bool Mutex::TryLock() { return is_safe_ ?
@@ -195,37 +233,42 @@ void Mutex::ReaderUnlock() { Unlock(); }
#elif defined(HAVE_PTHREAD) && defined(HAVE_RWLOCK)
-#include <stdlib.h> // for abort()
#define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \
if (is_safe_ && fncall(&mutex_) != 0) abort(); \
} while (0)
-Mutex::Mutex() {
+Mutex::Mutex() : destroy_(true) {
+ SetIsSafe();
+ if (is_safe_ && pthread_rwlock_init(&mutex_, NULL) != 0) abort();
+}
+Mutex::Mutex(Mutex::LinkerInitialized) : destroy_(false) {
SetIsSafe();
if (is_safe_ && pthread_rwlock_init(&mutex_, NULL) != 0) abort();
}
-Mutex::~Mutex() { SAFE_PTHREAD(pthread_rwlock_destroy); }
+Mutex::~Mutex() { if (destroy_) SAFE_PTHREAD(pthread_rwlock_destroy); }
void Mutex::Lock() { SAFE_PTHREAD(pthread_rwlock_wrlock); }
void Mutex::Unlock() { SAFE_PTHREAD(pthread_rwlock_unlock); }
bool Mutex::TryLock() { return is_safe_ ?
- pthread_rwlock_trywrlock(&mutex_) == 0 :
- true; }
+ pthread_rwlock_trywrlock(&mutex_) == 0 : true; }
void Mutex::ReaderLock() { SAFE_PTHREAD(pthread_rwlock_rdlock); }
void Mutex::ReaderUnlock() { SAFE_PTHREAD(pthread_rwlock_unlock); }
#undef SAFE_PTHREAD
#elif defined(HAVE_PTHREAD)
-#include <stdlib.h> // for abort()
#define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \
if (is_safe_ && fncall(&mutex_) != 0) abort(); \
} while (0)
-Mutex::Mutex() {
+Mutex::Mutex() : destroy_(true) {
SetIsSafe();
if (is_safe_ && pthread_mutex_init(&mutex_, NULL) != 0) abort();
}
-Mutex::~Mutex() { SAFE_PTHREAD(pthread_mutex_destroy); }
+Mutex::Mutex(Mutex::LinkerInitialized) : destroy_(false) {
+ SetIsSafe();
+ if (is_safe_ && pthread_mutex_init(&mutex_, NULL) != 0) abort();
+}
+Mutex::~Mutex() { if (destroy_) SAFE_PTHREAD(pthread_mutex_destroy); }
void Mutex::Lock() { SAFE_PTHREAD(pthread_mutex_lock); }
void Mutex::Unlock() { SAFE_PTHREAD(pthread_mutex_unlock); }
bool Mutex::TryLock() { return is_safe_ ?
@@ -279,4 +322,10 @@ class WriterMutexLock {
#define ReaderMutexLock(x) COMPILE_ASSERT(0, rmutex_lock_decl_missing_var_name)
#define WriterMutexLock(x) COMPILE_ASSERT(0, wmutex_lock_decl_missing_var_name)
+} // namespace MUTEX_NAMESPACE
+
+using namespace MUTEX_NAMESPACE;
+
+#undef MUTEX_NAMESPACE
+
#endif /* #define GOOGLE_SIMPLE_MUTEX_H_ */
diff --git a/src/base/spinlock.cc b/src/base/spinlock.cc
index 3b22122..48cdc89 100644
--- a/src/base/spinlock.cc
+++ b/src/base/spinlock.cc
@@ -43,6 +43,7 @@
#include <string.h> /* for strncmp */
#include <errno.h>
#include "base/spinlock.h"
+#include "base/cycleclock.h"
#include "base/sysinfo.h" /* for NumCPUs() */
// We can do contention-profiling of SpinLocks, but the code is in
@@ -56,40 +57,23 @@ static int adaptive_spin_count = 0;
const base::LinkerInitialized SpinLock::LINKER_INITIALIZED =
base::LINKER_INITIALIZED;
-namespace {
-
-// OS-specific code
-#ifdef _WIN32
-
-#include <windows.h> // for Sleep()
-
-static void WaitATick() {
- Sleep(1);
-}
-static void SchedYield() {
- Sleep(0); // closest thing windows has to sched_yield()
-}
-
+// The OS-specific header included below must provide two calls:
+// Wait until *w becomes zero, atomically set it to 1 and return.
+// static void SpinLockWait(volatile Atomic32 *w);
+//
+// Hint that a thread waiting in SpinLockWait() could now make progress. May
+// do nothing. This call may not read or write *w; it must use only the
+// address.
+// static void SpinLockWake(volatile Atomic32 *w);
+#if defined(_WIN32)
+#include "base/spinlock_win32-inl.h"
+#elif defined(__linux__)
+#include "base/spinlock_linux-inl.h"
#else
-
-static void WaitATick() {
- int save_errno = errno;
- struct timespec tm;
- tm.tv_sec = 0;
- tm.tv_nsec = 2000001;
- nanosleep(&tm, NULL);
- errno = save_errno;
-}
-static void SchedYield() {
-#ifdef HAVE_SCHED_H // otherwise, yield is just a noop
- int save_errno = errno;
- sched_yield();
- errno = save_errno;
-#endif
-}
-
+#include "base/spinlock_posix-inl.h"
#endif
+namespace {
struct SpinLock_InitHelper {
SpinLock_InitHelper() {
// On multi-cpu machines, spin for longer before yielding
@@ -117,20 +101,26 @@ void SpinLock::SlowLock() {
}
if (lockword_ == 1) {
- SchedYield(); // Spinning failed. Let's try to be gentle.
+ int32 now = (CycleClock::Now() >> PROFILE_TIMESTAMP_SHIFT);
+ // Don't loose the lock: make absolutely sure "now" is not zero
+ now |= 1;
+ // Atomically replace the value of lockword_ with "now" if
+ // lockword_ is 1, thereby remembering the first timestamp to
+ // be recorded.
+ base::subtle::NoBarrier_CompareAndSwap(&lockword_, 1, now);
+ // base::subtle::NoBarrier_CompareAndSwap() returns:
+ // 0: the lock is/was available; nothing stored
+ // 1: our timestamp was stored
+ // > 1: an older timestamp is already in lockword_; nothing stored
}
- while (Acquire_CompareAndSwap(&lockword_, 0, 1) != 0) {
- // This code was adapted from the ptmalloc2 implementation of
- // spinlocks which would sched_yield() upto 50 times before
- // sleeping once for a few milliseconds. Mike Burrows suggested
- // just doing one sched_yield() outside the loop and always
- // sleeping after that. This change helped a great deal on the
- // performance of spinlocks under high contention. A test program
- // with 10 threads on a dual Xeon (four virtual processors) went
- // from taking 30 seconds to 16 seconds.
+ SpinLockWait(&lockword_); // wait until lock acquired; OS specific
+}
+
+void SpinLock::SlowUnlock(int64 wait_timestamp) {
+ SpinLockWake(&lockword_); // wake waiter if necessary; OS specific
- // Sleep for a few milliseconds
- WaitATick();
- }
+ // Collect contentionz profile info. Subtract one from wait_timestamp as
+ // antidote to "now |= 1;" in SlowLock().
+ SubmitSpinLockProfileData(this, wait_timestamp - 1);
}
diff --git a/src/base/spinlock.h b/src/base/spinlock.h
index 6761bc0..dda59a6 100644
--- a/src/base/spinlock.h
+++ b/src/base/spinlock.h
@@ -98,12 +98,10 @@ class LOCKABLE SpinLock {
int64 wait_timestamp = static_cast<uint32>(lockword_);
ANNOTATE_RWLOCK_RELEASED(this, 1);
Release_Store(&lockword_, 0);
- // Collect contention profile info if this lock was contended.
- // The lockword_ value indicates when the waiter started waiting
if (wait_timestamp != 1) {
- // Subtract one from wait_timestamp as antidote to "now |= 1;"
- // in SlowLock().
- SubmitSpinLockProfileData(this, wait_timestamp - 1);
+ // Collect contentionz profile info, and speed the wakeup of any waiter.
+ // The lockword_ value indicates when the waiter started waiting.
+ SlowUnlock(wait_timestamp);
}
}
@@ -131,9 +129,10 @@ class LOCKABLE SpinLock {
// Lock-state: 0 means unlocked; 1 means locked with no waiters; values
// greater than 1 indicate locked with waiters, where the value is the time
// the first waiter started waiting and is used for contention profiling.
- volatile AtomicWord lockword_;
+ volatile Atomic32 lockword_;
void SlowLock();
+ void SlowUnlock(int64 wait_timestamp);
DISALLOW_EVIL_CONSTRUCTORS(SpinLock);
};
diff --git a/src/base/spinlock_linux-inl.h b/src/base/spinlock_linux-inl.h
new file mode 100644
index 0000000..2165e85
--- /dev/null
+++ b/src/base/spinlock_linux-inl.h
@@ -0,0 +1,84 @@
+/* Copyright (c) 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ---
+ * This file is a Linux-specific part of spinlock.cc
+ */
+
+#include <sched.h>
+#include <time.h>
+#include "base/linux_syscall_support.h"
+
+#define FUTEX_WAIT 0
+#define FUTEX_WAKE 1
+
+static bool have_futex;
+
+namespace {
+static struct InitModule {
+ InitModule() {
+ int x = 0;
+ // futexes are ints, so we can use them only when
+ // that's the same size as the lockword_ in SpinLock.
+ have_futex = (sizeof (Atomic32) == sizeof (int) &&
+ sys_futex(&x, FUTEX_WAKE, 1, 0) >= 0);
+ }
+} init_module;
+} // anonymous namespace
+
+static void SpinLockWait(volatile Atomic32 *w) {
+ int save_errno = errno;
+ struct timespec tm;
+ tm.tv_sec = 0;
+ if (have_futex) {
+ int value;
+ tm.tv_nsec = 1000000; // 1ms; really we're trying to sleep for one kernel
+ // clock tick
+ while ((value = base::subtle::Acquire_CompareAndSwap(w, 0, 1)) != 0) {
+ sys_futex(reinterpret_cast<int *>(const_cast<Atomic32 *>(w)),
+ FUTEX_WAIT, value, reinterpret_cast<struct kernel_timespec *>(&tm));
+ }
+ } else {
+ tm.tv_nsec = 2000001; // above 2ms so linux 2.4 doesn't spin
+ if (base::subtle::NoBarrier_Load(w) != 0) {
+ sched_yield();
+ }
+ while (base::subtle::Acquire_CompareAndSwap(w, 0, 1) != 0) {
+ nanosleep(&tm, NULL);
+ }
+ }
+ errno = save_errno;
+}
+
+static void SpinLockWake(volatile Atomic32 *w) {
+ if (have_futex) {
+ sys_futex(reinterpret_cast<int *>(const_cast<Atomic32 *>(w)),
+ FUTEX_WAKE, 1, 0);
+ }
+}
diff --git a/src/base/spinlock_posix-inl.h b/src/base/spinlock_posix-inl.h
new file mode 100644
index 0000000..0d933c0
--- /dev/null
+++ b/src/base/spinlock_posix-inl.h
@@ -0,0 +1,52 @@
+/* Copyright (c) 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ---
+ * This file is a Posix-specific part of spinlock.cc
+ */
+
+#include <sched.h>
+#include <time.h>
+
+static void SpinLockWait(volatile Atomic32 *w) {
+ int save_errno = errno;
+ struct timespec tm;
+ tm.tv_sec = 0;
+ tm.tv_nsec = 1000000;
+ if (base::subtle::NoBarrier_Load(w) != 0) {
+ sched_yield();
+ }
+ while (base::subtle::Acquire_CompareAndSwap(w, 0, 1) != 0) {
+ nanosleep(&tm, NULL);
+ }
+ errno = save_errno;
+}
+
+static void SpinLockWake(volatile Atomic32 *w) {
+}
diff --git a/src/base/spinlock_win32-inl.h b/src/base/spinlock_win32-inl.h
new file mode 100644
index 0000000..9058939
--- /dev/null
+++ b/src/base/spinlock_win32-inl.h
@@ -0,0 +1,47 @@
+/* Copyright (c) 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ---
+ * This file is a Win32-specific part of spinlock.cc
+ */
+
+
+#include <windows.h>
+
+static void SpinLockWait(volatile Atomic32 *w) {
+ if (base::subtle::NoBarrier_Load(w) != 0) {
+ Sleep(0);
+ }
+ while (base::subtle::Acquire_CompareAndSwap(w, 0, 1) != 0) {
+ Sleep(1);
+ }
+}
+
+static void SpinLockWake(volatile Atomic32 *w) {
+}
diff --git a/src/base/sysinfo.cc b/src/base/sysinfo.cc
index 56f57bd..a2bc2a9 100644
--- a/src/base/sysinfo.cc
+++ b/src/base/sysinfo.cc
@@ -26,9 +26,6 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// ---
-// Author: Mike Burrows
#include <config.h>
#if (defined(_WIN32) || defined(__MINGW32__)) && !defined(__CYGWIN__) && !defined(__CYGWIN32)
diff --git a/src/base/sysinfo.h b/src/base/sysinfo.h
index 272a033..b4b5c9f 100644
--- a/src/base/sysinfo.h
+++ b/src/base/sysinfo.h
@@ -26,9 +26,6 @@
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// ---
-// Author: Mike Burrows
// All functions here are thread-hostile due to file caching unless
// commented otherwise.
diff --git a/src/base/vdso_support.cc b/src/base/vdso_support.cc
index 873a8ac..96913f6 100644
--- a/src/base/vdso_support.cc
+++ b/src/base/vdso_support.cc
@@ -53,6 +53,19 @@ using base::subtle::MemoryBarrier;
#define AT_SYSINFO_EHDR 33
#endif
+// From binutils/include/elf/common.h (this doesn't appear to be documented
+// anywhere else).
+//
+// /* This flag appears in a Versym structure. It means that the symbol
+// is hidden, and is only visible with an explicit version number.
+// This is a GNU extension. */
+// #define VERSYM_HIDDEN 0x8000
+//
+// /* This is the mask for the rest of the Versym information. */
+// #define VERSYM_VERSION 0x7fff
+
+#define VERSYM_VERSION 0x7fff
+
namespace base {
namespace {
@@ -119,26 +132,21 @@ VDSOSupport::ElfMemImage::ElfMemImage(const void *base) {
}
int VDSOSupport::ElfMemImage::GetNumSymbols() const {
- if (!dynsym_) {
+ if (!hash_) {
return 0;
}
- return dynsym_->sh_size / dynsym_->sh_entsize;
+ // See http://www.caldera.com/developers/gabi/latest/ch5.dynamic.html#hash
+ return hash_[1];
}
const ElfW(Sym) *VDSOSupport::ElfMemImage::GetDynsym(int index) const {
CHECK_LT(index, GetNumSymbols());
- return GetTableElement<ElfW(Sym)>(ehdr_,
- dynsym_->sh_offset,
- dynsym_->sh_entsize,
- index);
+ return dynsym_ + index;
}
const ElfW(Versym) *VDSOSupport::ElfMemImage::GetVersym(int index) const {
CHECK_LT(index, GetNumSymbols());
- return GetTableElement<ElfW(Versym)>(ehdr_,
- versym_->sh_offset,
- versym_->sh_entsize,
- index);
+ return versym_ + index;
}
const ElfW(Phdr) *VDSOSupport::ElfMemImage::GetPhdr(int index) const {
@@ -149,24 +157,9 @@ const ElfW(Phdr) *VDSOSupport::ElfMemImage::GetPhdr(int index) const {
index);
}
-const ElfW(Shdr) *VDSOSupport::ElfMemImage::GetSection(int index) const {
- CHECK_LT(index, ehdr_->e_shnum);
- return GetTableElement<ElfW(Shdr)>(ehdr_,
- ehdr_->e_shoff,
- ehdr_->e_shentsize,
- index);
-}
-
-const char *VDSOSupport::ElfMemImage::GetSectionData(
- const ElfW(Shdr) *section,
- ElfW(Word) offset) const {
- CHECK_LT(offset, section->sh_size);
- return GetTableElement<char>(ehdr_, section->sh_offset, 1, offset);
-}
-
const char *VDSOSupport::ElfMemImage::GetDynstr(ElfW(Word) offset) const {
- CHECK_LT(offset, dynstr_->sh_size);
- return GetTableElement<char>(ehdr_, dynstr_->sh_offset, 1, offset);
+ CHECK_LT(offset, strsize_);
+ return dynstr_ + offset;
}
const void *VDSOSupport::ElfMemImage::GetSymAddr(const ElfW(Sym) *sym) const {
@@ -179,14 +172,14 @@ const void *VDSOSupport::ElfMemImage::GetSymAddr(const ElfW(Sym) *sym) const {
}
const ElfW(Verdef) *VDSOSupport::ElfMemImage::GetVerdef(int index) const {
- size_t offset = 0;
- const ElfW(Verdef) *version_definition =
- GetTableElement<ElfW(Verdef)>(ehdr_, verdef_->sh_offset, 1, offset);
+ CHECK_LE(index, verdefnum_);
+ const ElfW(Verdef) *version_definition = verdef_;
while (version_definition->vd_ndx < index && version_definition->vd_next) {
- offset += version_definition->vd_next;
- CHECK_LT(offset, verdef_->sh_size);
+ const char *const version_definition_as_char =
+ reinterpret_cast<const char *>(version_definition);
version_definition =
- GetTableElement<ElfW(Verdef)>(ehdr_, verdef_->sh_offset, 1, offset);
+ reinterpret_cast<const ElfW(Verdef) *>(version_definition_as_char +
+ version_definition->vd_next);
}
return version_definition->vd_ndx == index ? version_definition : NULL;
}
@@ -197,7 +190,8 @@ const ElfW(Verdaux) *VDSOSupport::ElfMemImage::GetVerdefAux(
}
const char *VDSOSupport::ElfMemImage::GetVerstr(ElfW(Word) offset) const {
- return GetSectionData(GetSection(verdef_->sh_link), offset);
+ CHECK_LT(offset, strsize_);
+ return dynstr_ + offset;
}
void VDSOSupport::ElfMemImage::Init(const void *base) {
@@ -206,15 +200,19 @@ void VDSOSupport::ElfMemImage::Init(const void *base) {
dynstr_ = NULL;
versym_ = NULL;
verdef_ = NULL;
+ hash_ = NULL;
+ strsize_ = 0;
+ verdefnum_ = 0;
link_base_ = ~0L; // Sentinel: PT_LOAD .p_vaddr can't possibly be this.
if (!base) {
return;
}
- if (memcmp(base, ELFMAG, SELFMAG)) {
+ const char *const base_as_char = reinterpret_cast<const char *>(base);
+ if (base_as_char[EI_MAG0] != ELFMAG0 || base_as_char[EI_MAG1] != ELFMAG1 ||
+ base_as_char[EI_MAG2] != ELFMAG2 || base_as_char[EI_MAG3] != ELFMAG3) {
RAW_DCHECK(false, "no ELF magic"); // at %p", base);
return;
}
- const char *const base_as_char = reinterpret_cast<const char *>(base);
int elf_class = base_as_char[EI_CLASS];
if (elf_class != CurrentElfClass::kElfClass) {
DCHECK_EQ(elf_class, CurrentElfClass::kElfClass);
@@ -242,59 +240,86 @@ void VDSOSupport::ElfMemImage::Init(const void *base) {
}
ehdr_ = reinterpret_cast<const ElfW(Ehdr) *>(base);
+ const ElfW(Phdr) *dynamic_program_header = NULL;
for (int i = 0; i < ehdr_->e_phnum; ++i) {
const ElfW(Phdr) *const program_header = GetPhdr(i);
- if (program_header->p_type == PT_LOAD) {
- link_base_ = program_header->p_vaddr;
- break;
+ switch (program_header->p_type) {
+ case PT_LOAD:
+ if (link_base_ == ~0L) {
+ link_base_ = program_header->p_vaddr;
+ }
+ break;
+ case PT_DYNAMIC:
+ dynamic_program_header = program_header;
+ break;
}
}
- if (link_base_ == ~0L) {
- // Didn't find a PT_LOAD.
- RAW_DCHECK(false, "no PT_LOADs in VDSO");
+ if (link_base_ == ~0L || !dynamic_program_header) {
+ RAW_DCHECK(~0L != link_base_, "no PT_LOADs in VDSO");
+ RAW_DCHECK(dynamic_program_header, "no PT_DYNAMIC in VDSO");
// Mark this image as not present. Can not recur infinitely.
Init(0);
return;
}
- for (int i = 0; i < ehdr_->e_shnum; ++i) {
- const ElfW(Shdr) *section = GetSection(i);
- switch (section->sh_type) {
- case SHT_DYNSYM: {
- dynsym_ = section;
- break;
+ ptrdiff_t relocation =
+ base_as_char - reinterpret_cast<const char *>(link_base_);
+ ElfW(Dyn) *dynamic_entry =
+ reinterpret_cast<ElfW(Dyn) *>(dynamic_program_header->p_vaddr +
+ relocation);
+ for (; dynamic_entry->d_tag != DT_NULL; ++dynamic_entry) {
+ ElfW(Xword) value = dynamic_entry->d_un.d_val;
+ if (link_base_ == 0) {
+ // A complication: in the real VDSO, dynamic entries are not relocated
+ // (it wasn't loaded by a dynamic loader). But when testing with a
+ // "fake" dlopen()ed vdso library, the loader relocates some (but
+ // not all!) of them before we get here.
+ // Since real VDSO is never linked at address 0, and "fake" vdso
+ // library always is, we know we are dealing with the "fake" one here.
+ if (dynamic_entry->d_tag == DT_VERDEF) {
+ // The only dynamic entry (of the ones we care about) libc-2.3.6
+ // loader doesn't relocate.
+ value += relocation;
}
- case SHT_STRTAB: {
- const char *const section_name =
- GetSectionData(GetSection(ehdr_->e_shstrndx), section->sh_name);
- if (strcmp(".dynstr", section_name) == 0) {
- dynstr_ = section;
- break;
- }
+ } else {
+ // Real VDSO. Everything needs to be relocated.
+ value += relocation;
+ }
+ switch (dynamic_entry->d_tag) {
+ case DT_HASH:
+ hash_ = reinterpret_cast<ElfW(Word) *>(value);
break;
- }
- case SHT_GNU_versym: {
- versym_ = section;
+ case DT_SYMTAB:
+ dynsym_ = reinterpret_cast<ElfW(Sym) *>(value);
break;
- }
- case SHT_GNU_verdef: {
- verdef_ = section;
+ case DT_STRTAB:
+ dynstr_ = reinterpret_cast<const char *>(value);
break;
- }
- default: {
- // Unrecognized sections explicitly ignored.
+ case DT_VERSYM:
+ versym_ = reinterpret_cast<ElfW(Versym) *>(value);
+ break;
+ case DT_VERDEF:
+ verdef_ = reinterpret_cast<ElfW(Verdef) *>(value);
+ break;
+ case DT_VERDEFNUM:
+ verdefnum_ = dynamic_entry->d_un.d_val;
+ break;
+ case DT_STRSZ:
+ strsize_ = dynamic_entry->d_un.d_val;
+ break;
+ default:
+ // Unrecognized entries explicitly ignored.
break;
- }
}
}
- if (!dynsym_ || !dynstr_ || !versym_ || !verdef_ ||
- ((dynsym_->sh_size / dynsym_->sh_entsize) !=
- (versym_->sh_size / versym_->sh_entsize))) {
- RAW_DCHECK(dynsym_, "invalid VDSO (no dynsym)");
- RAW_DCHECK(dynstr_, "invalid VDSO (no dynstr)");
- RAW_DCHECK(versym_, "invalid VDSO (no versym)");
- RAW_DCHECK(verdef_, "invalid VDSO (no verdef)");
- DCHECK_EQ(dynsym_->sh_size / dynsym_->sh_entsize,
- versym_->sh_size / versym_->sh_entsize);
+ if (!hash_ || !dynsym_ || !dynstr_ || !versym_ ||
+ !verdef_ || !verdefnum_ || !strsize_) {
+ RAW_DCHECK(hash_, "invalid VDSO (no DT_HASH)");
+ RAW_DCHECK(dynsym_, "invalid VDSO (no DT_SYMTAB)");
+ RAW_DCHECK(dynstr_, "invalid VDSO (no DT_STRTAB)");
+ RAW_DCHECK(versym_, "invalid VDSO (no DT_VERSYM)");
+ RAW_DCHECK(verdef_, "invalid VDSO (no DT_VERDEF)");
+ RAW_DCHECK(verdefnum_, "invalid VDSO (no DT_VERDEFNUM)");
+ RAW_DCHECK(strsize_, "invalid VDSO (no DT_STRSZ)");
// Mark this image as not present. Can not recur infinitely.
Init(0);
return;
@@ -467,9 +492,16 @@ void VDSOSupport::SymbolIterator::Update(int increment) {
const ElfW(Versym) *version_symbol = image->GetVersym(index_);
CHECK(symbol && version_symbol);
const char *const symbol_name = image->GetDynstr(symbol->st_name);
- const ElfW(Versym) version_index = version_symbol[0];
- const ElfW(Verdef) *version_definition = image->GetVerdef(version_index);
+ const ElfW(Versym) version_index = version_symbol[0] & VERSYM_VERSION;
+ const ElfW(Verdef) *version_definition = NULL;
const char *version_name = "";
+ if (symbol->st_shndx == SHN_UNDEF) {
+ // Undefined symbols reference DT_VERNEED, not DT_VERDEF, and
+ // version_index could well be greater than verdefnum_, so calling
+ // GetVerdef(version_index) may trigger assertion.
+ } else {
+ version_definition = image->GetVerdef(version_index);
+ }
if (version_definition) {
// I am expecting 1 or 2 auxiliary entries: 1 for the version itself,
// optional 2nd if the version has a parent.
diff --git a/src/base/vdso_support.h b/src/base/vdso_support.h
index f8a4127..c47b3c5 100644
--- a/src/base/vdso_support.h
+++ b/src/base/vdso_support.h
@@ -118,23 +118,23 @@ class VDSOSupport {
void Init(const void *base);
bool IsPresent() const { return ehdr_ != NULL; }
const ElfW(Phdr)* GetPhdr(int index) const;
- const ElfW(Shdr)* GetSection(int index) const;
const ElfW(Sym)* GetDynsym(int index) const;
const ElfW(Versym)* GetVersym(int index) const;
const ElfW(Verdef)* GetVerdef(int index) const;
const ElfW(Verdaux)* GetVerdefAux(const ElfW(Verdef) *verdef) const;
- const char* GetSectionData(const ElfW(Shdr) *,
- ElfW(Word) offset) const;
const char* GetDynstr(ElfW(Word) offset) const;
const void* GetSymAddr(const ElfW(Sym) *sym) const;
const char* GetVerstr(ElfW(Word) offset) const;
int GetNumSymbols() const;
private:
const ElfW(Ehdr) *ehdr_;
- const ElfW(Shdr) *dynsym_;
- const ElfW(Shdr) *dynstr_;
- const ElfW(Shdr) *versym_;
- const ElfW(Shdr) *verdef_;
+ const ElfW(Sym) *dynsym_;
+ const ElfW(Versym) *versym_;
+ const ElfW(Verdef) *verdef_;
+ const ElfW(Word) *hash_;
+ const char *dynstr_;
+ size_t strsize_;
+ size_t verdefnum_;
ElfW(Addr) link_base_; // Link-time base (p_vaddr of first PT_LOAD).
};
diff --git a/src/common.cc b/src/common.cc
index d89ba83..04723b1 100644
--- a/src/common.cc
+++ b/src/common.cc
@@ -58,21 +58,17 @@ int SizeMap::NumMoveSize(size_t size) {
// Use approx 64k transfers between thread and central caches.
int num = static_cast<int>(64.0 * 1024.0 / size);
if (num < 2) num = 2;
- // Clamp well below kMaxFreeListLength to avoid ping pong between central
- // and thread caches.
- if (num > static_cast<int>(0.8 * kMaxFreeListLength))
- num = static_cast<int>(0.8 * kMaxFreeListLength);
-
- // Also, avoid bringing in too many objects into small object free
- // lists. There are lots of such lists, and if we allow each one to
- // fetch too many at a time, we end up having to scavenge too often
- // (especially when there are lots of threads and each thread gets a
- // small allowance for its thread cache). This fixes a problem seen
- // in the 20060502 bigtable release by both Andrew Fikes and Ben
- // Darnell.
- //
- // TODO: Make thread cache free list sizes dynamic so that we do not
- // have to equally divide a fixed resource amongst lots of threads.
+
+ // Avoid bringing too many objects into small object free lists.
+ // If this value is too large:
+ // - We waste memory with extra objects sitting in the thread caches.
+ // - The central freelist holds its lock for too long while
+ // building a linked list of objects, slowing down the allocations
+ // of other threads.
+ // If this value is too small:
+ // - We go to the central freelist too often and we have to acquire
+ // its lock each time.
+ // This value strikes a balance between the constraints above.
if (num > 32) num = 32;
return num;
diff --git a/src/common.h b/src/common.h
index 1721ded..92c582f 100644
--- a/src/common.h
+++ b/src/common.h
@@ -68,8 +68,6 @@ static const size_t kNumClasses = 61;
// want this big to avoid locking the central free-list too often. It
// should not hurt to make this list somewhat big because the
// scavenging code will shrink it down when its contents are not in use.
-static const int kMaxFreeListLength = 256;
-// Same as above but used when --tcmalloc_use_dynamic_thread_cache_sizes=true.
static const int kMaxDynamicFreeListLength = 8192;
static const Length kMaxValidPages = (~static_cast<Length>(0)) >> kPageShift;
diff --git a/src/config.h.in b/src/config.h.in
index 02782e5..18be9f3 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -6,6 +6,9 @@
/* Define to 1 if you have the <conflict-signal.h> header file. */
#undef HAVE_CONFLICT_SIGNAL_H
+/* Define to 1 if you have the <cygwin/signal.h> header file. */
+#undef HAVE_CYGWIN_SIGNAL_H
+
/* Define to 1 if you have the declaration of `cfree', and to 0 if you don't.
*/
#undef HAVE_DECL_CFREE
@@ -78,6 +81,9 @@
/* define if the compiler implements namespaces */
#undef HAVE_NAMESPACES
+/* Define to 1 if you have the <poll.h> header file. */
+#undef HAVE_POLL_H
+
/* define if libc has program_invocation_name */
#undef HAVE_PROGRAM_INVOCATION_NAME
diff --git a/src/debugallocation.cc b/src/debugallocation.cc
new file mode 100644
index 0000000..af68815
--- /dev/null
+++ b/src/debugallocation.cc
@@ -0,0 +1,1367 @@
+// Copyright (c) 2000, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ---
+// Author: Urs Holzle <opensource@google.com>
+
+#include "config.h"
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+#include <pthread.h>
+#include <stdio.h>
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+#include <stdarg.h>
+#ifdef HAVE_MMAP
+#include <sys/mman.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <errno.h>
+#include <string.h>
+
+#include "base/commandlineflags.h"
+#include "base/googleinit.h"
+#include "base/logging.h"
+#include "google/malloc_extension.h"
+#include "google/malloc_hook.h"
+#include "google/stacktrace.h"
+#include "addressmap-inl.h"
+#include "malloc_hook-inl.h"
+#include "symbolize.h"
+
+#ifdef TCMALLOC_FOR_DEBUGALLOCATION
+#include "tcmalloc.cc"
+#else
+#include "base/spinlock.h"
+// Else we already have a SpinLock defined in tcmalloc/internal_spinlock.h
+#endif
+
+// __THROW is defined in glibc systems. It means, counter-intuitively,
+// "This function will never throw an exception." It's an optional
+// optimization tool, but we may need to use it to match glibc prototypes.
+#ifndef __THROW // I guess we're not on a glibc system
+# define __THROW // __THROW is just an optimization, so ok to make it ""
+#endif
+
+// On systems (like freebsd) that don't define MAP_ANONYMOUS, use the old
+// form of the name instead.
+#ifndef MAP_ANONYMOUS
+# define MAP_ANONYMOUS MAP_ANON
+#endif
+
+// ========================================================================= //
+
+DEFINE_bool(malloctrace,
+ EnvToBool("TCMALLOC_TRACE", false),
+ "Enables memory (de)allocation tracing to /tmp/google.alloc.");
+#ifdef HAVE_MMAP
+DEFINE_bool(malloc_page_fence,
+ EnvToBool("TCMALLOC_PAGE_FENCE", false),
+ "Enables putting of memory allocations at page boundaries "
+ "with a guard page following the allocation (to catch buffer "
+ "overruns right when they happen).");
+DEFINE_bool(malloc_page_fence_never_reclaim,
+ EnvToBool("TCMALLOC_PAGE_FRANCE_NEVER_RECLAIM", false),
+ "Enables making the virtual address space inaccessible "
+ "upon a deallocation instead of returning it and reusing later.");
+#else
+DEFINE_bool(malloc_page_fence, false, "Not usable (requires mmap)");
+DEFINE_bool(malloc_page_fence_never_reclaim, false, "Not usable (required mmap)");
+#endif
+DEFINE_bool(malloc_reclaim_memory,
+ EnvToBool("TCMALLOC_RECLAIM_MEMORY", true),
+ "If set to false, we never return memory to malloc "
+ "when an object is deallocated. This ensures that all "
+ "heap object addresses are unique.");
+DEFINE_int32(max_free_queue_size,
+ EnvToInt("TCMALLOC_MAX_FREE_QUEUE_SIZE", 10*1024*1024),
+ "If greater than 0, keep freed blocks in a queue instead of "
+ "releasing them to the allocator immediately. Release them when "
+ "the total size of all blocks in the queue would otherwise exceed "
+ "this limit.");
+
+DEFINE_bool(symbolize_stacktrace,
+ EnvToBool("TCMALLOC_SYMBOLIZE_STACKTRACE", true),
+ "Symbolize the stack trace when provided (on some error exits)");
+
+// ========================================================================= //
+
+// A safe version of printf() that does not do any allocation and
+// uses very little stack space.
+static void TracePrintf(int fd, const char *fmt, ...)
+ __attribute__ ((__format__ (__printf__, 2, 3)));
+
+//
+// GNU has some weird "weak aliasing" thing that permits us to define our
+// own malloc(), free(), and realloc() which can use the normal versions of
+// of themselves by calling __libc_malloc(), __libc_free(), and
+// __libc_realloc().
+//
+extern "C" {
+ extern void* __libc_malloc(size_t size);
+ extern void __libc_free(void* ptr);
+ extern void* __libc_realloc(void* ptr, size_t size);
+ extern void* __libc_calloc(size_t nmemb, size_t size);
+ extern int __libc_mallopt(int cmd, int value);
+#ifdef HAVE_STRUCT_MALLINFO
+ extern struct mallinfo __libc_mallinfo(void);
+#endif
+}
+
+// Define the malloc/free/mallopt/mallinfo implementations
+// we will be working on top of.
+// TODO(csilvers): provide debugallocation on top of libc alloc,
+// so this #ifdef might sometimes be false.
+#ifdef TCMALLOC_FOR_DEBUGALLOCATION
+
+// The do_* functions are defined in tcmalloc.cc,
+// which is included before this file
+// when TCMALLOC_FOR_DEBUGALLOCATION is defined.
+#define BASE_MALLOC do_malloc
+#define BASE_FREE do_free
+#define BASE_MALLOPT do_mallopt
+#define BASE_MALLINFO do_mallinfo
+
+#else
+
+// We are working on top of standard libc's malloc library
+#define BASE_MALLOC __libc_malloc
+#define BASE_FREE __libc_free
+#define BASE_MALLOPT __libc_mallopt
+#define BASE_MALLINFO __libc_mallinfo
+
+#endif
+
+// ========================================================================= //
+
+class MallocBlock;
+
+// A circular buffer to hold freed blocks of memory. MallocBlock::Deallocate
+// (below) pushes blocks into this queue instead of returning them to the
+// underlying allocator immediately. See MallocBlock::Deallocate for more
+// information.
+//
+// We can't use an STL class for this because we need to be careful not to
+// perform any heap de-allocations in any of the code in this class, since the
+// code in MallocBlock::Deallocate is not re-entrant.
+template <typename QueueEntry>
+class FreeQueue {
+ public:
+ FreeQueue() : q_front_(0), q_back_(0) {}
+
+ bool Full() {
+ return (q_front_ + 1) % kFreeQueueSize == q_back_;
+ }
+
+ void Push(QueueEntry block) {
+ q_[q_front_] = block;
+ q_front_ = (q_front_ + 1) % kFreeQueueSize;
+ }
+
+ QueueEntry Pop() {
+ const QueueEntry& ret = q_[q_back_];
+ q_back_ = (q_back_ + 1) % kFreeQueueSize;
+ return ret;
+ }
+
+ size_t size() const {
+ return (q_front_ - q_back_ + kFreeQueueSize) % kFreeQueueSize;
+ }
+
+ private:
+ // Maximum number of blocks kept in the free queue before being freed.
+ static const int kFreeQueueSize = 1024;
+
+ QueueEntry q_[kFreeQueueSize];
+ int q_front_;
+ int q_back_;
+};
+
+struct MallocBlockQueueEntry {
+ MallocBlockQueueEntry() : block(NULL), size(0),
+ num_deleter_pcs(0), deleter_threadid(0) {}
+ MallocBlockQueueEntry(MallocBlock* b, size_t s) : block(b), size(s) {
+ if (FLAGS_max_free_queue_size != 0) {
+ // Adjust the number of frames to skip (4) if you change the
+ // location of this call.
+ num_deleter_pcs =
+ GetStackTrace(deleter_pcs,
+ sizeof(deleter_pcs) / sizeof(deleter_pcs[0]),
+ 4);
+ deleter_threadid = pthread_self();
+ } else {
+ num_deleter_pcs = 0;
+ // Zero is an illegal pthread id by my reading of the pthread
+ // implementation:
+ deleter_threadid = 0;
+ }
+ }
+
+ MallocBlock* block;
+ size_t size;
+
+ // When deleted and put in the free queue, we (flag-controlled)
+ // record the stack so that if corruption is later found, we can
+ // print the deleter's stack. (These three vars add 144 bytes of
+ // overhead under the LP64 data model.)
+ void* deleter_pcs[16];
+ int num_deleter_pcs;
+ pthread_t deleter_threadid;
+};
+
+class MallocBlock {
+ public: // allocation type constants
+
+ // Different allocation types we distinguish.
+ // Note: The lower 4 bits are not random: we index kAllocName array
+ // by these values masked with kAllocTypeMask;
+ // the rest are "random" magic bits to help catch memory corruption.
+ static const int kMallocType = 0xEFCDAB90;
+ static const int kNewType = 0xFEBADC81;
+ static const int kArrayNewType = 0xBCEADF72;
+
+ private: // constants
+
+ // A mask used on alloc types above to get to 0, 1, 2
+ static const int kAllocTypeMask = 0x3;
+ // An additional bit to set in AllocType constants
+ // to mark now deallocated regions.
+ static const int kDeallocatedTypeBit = 0x4;
+
+ // For better memory debugging, we initialize all storage to known
+ // values, and overwrite the storage when it's deallocated:
+ // Byte that fills uninitialized storage.
+ static const int kMagicUninitializedByte = 0xAB;
+ // Byte that fills deallocated storage.
+ // NOTE: tcmalloc.cc depends on the value of kMagicDeletedByte
+ // to work around a bug in the pthread library.
+ static const int kMagicDeletedByte = 0xCD;
+ // An int (type of alloc_type_ below) in a deallocated storage
+ // filled with kMagicDeletedByte.
+ static const int kMagicDeletedInt = 0xCDCDCDCD | ((0xCDCDCDCD << 16) << 16);
+ // Initializer works for 32 and 64 bit ints;
+ // "<< 16 << 16" is to fool gcc from issuing a warning
+ // when ints are 32 bits.
+
+ // NOTE: on Linux, you can enable malloc debugging support in libc by
+ // setting the environment variable MALLOC_CHECK_ to 1 before you
+ // start the program (see man malloc).
+
+ // We use either BASE_MALLOC or mmap to make the actual allocation. In
+ // order to remember which one of the two was used for any block, we store an
+ // appropriate magic word next to the block.
+ static const int kMagicMalloc = 0xDEADBEEF;
+ static const int kMagicMMap = 0xABCDEFAB;
+
+ // This array will be filled with 0xCD, for use with memcmp.
+ static unsigned char kMagicDeletedBuffer[1024];
+ static bool deleted_buffer_initialized_;
+
+ private: // data layout
+
+ // The four fields size1_,offset_,magic1_,alloc_type_
+ // should together occupy a multiple of 8 bytes.
+ size_t size1_;
+ size_t offset_; // normally 0 unless memaligned memory
+ // see comments in memalign() and FromRawPointer().
+ int magic1_;
+ int alloc_type_;
+ // here comes the actual data (variable length)
+ // ...
+ // then come the size2_ and magic2_, or a full page of mprotect-ed memory
+ // if the malloc_page_fence feature is enabled.
+ size_t size2_;
+ int magic2_;
+
+ private: // static data and helpers
+
+ // Allocation map: stores the allocation type for each allocated object,
+ // or the type or'ed with kDeallocatedTypeBit
+ // for each formerly allocated object.
+ typedef AddressMap<int> AllocMap;
+ static AllocMap* alloc_map_;
+ // This protects alloc_map_ and consistent state of metadata
+ // for each still-allocated object in it.
+ // We use spin locks instead of pthread_mutex_t locks
+ // to prevent crashes via calls to pthread_mutex_(un)lock
+ // for the (de)allocations coming from pthreads initialization itself.
+ static SpinLock alloc_map_lock_;
+
+ // A queue of freed blocks. Instead of releasing blocks to the allocator
+ // immediately, we put them in a queue, freeing them only when necessary
+ // to keep the total size of all the freed blocks below the limit set by
+ // FLAGS_max_free_queue_size.
+ static FreeQueue<MallocBlockQueueEntry>* free_queue_;
+
+ static size_t free_queue_size_; // total size of blocks in free_queue_
+ // protects free_queue_ and free_queue_size_
+ static SpinLock free_queue_lock_;
+
+ // Names of allocation types (kMallocType, kNewType, kArrayNewType)
+ static const char* const kAllocName[];
+ // Names of corresponding deallocation types
+ static const char* const kDeallocName[];
+
+ static const char* AllocName(int type) {
+ return kAllocName[type & kAllocTypeMask];
+ }
+
+ static const char* DeallocName(int type) {
+ return kDeallocName[type & kAllocTypeMask];
+ }
+
+ private: // helper accessors
+
+ bool IsMMapped() const { return kMagicMMap == magic1_; }
+
+ bool IsValidMagicValue(int value) const {
+ return kMagicMMap == value || kMagicMalloc == value;
+ }
+
+ static size_t real_malloced_size(size_t size) {
+ return size + sizeof(MallocBlock);
+ }
+ static size_t real_mmapped_size(size_t size) {
+ return size + MallocBlock::data_offset();
+ }
+
+ size_t real_size() {
+ return IsMMapped() ? real_mmapped_size(size1_) : real_malloced_size(size1_);
+ }
+
+ // NOTE: if the block is mmapped (that is, we're using the
+ // malloc_page_fence option) then there's no size2 or magic2
+ // (instead, the guard page begins where size2 would be).
+
+ size_t* size2_addr() { return (size_t*)((char*)&size2_ + size1_); }
+ const size_t* size2_addr() const {
+ return (const size_t*)((char*)&size2_ + size1_);
+ }
+
+ int* magic2_addr() { return (int*)(size2_addr() + 1); }
+ const int* magic2_addr() const { return (const int*)(size2_addr() + 1); }
+
+ private: // other helpers
+
+ void Initialize(size_t size, int type) {
+ RAW_CHECK(IsValidMagicValue(magic1_), "");
+ // record us as allocated in the map
+ alloc_map_lock_.Lock();
+ if (!alloc_map_) {
+ void* p = BASE_MALLOC(sizeof(AllocMap));
+ alloc_map_ = new(p) AllocMap(BASE_MALLOC, BASE_FREE);
+ }
+ alloc_map_->Insert(data_addr(), type);
+ // initialize us
+ size1_ = size;
+ offset_ = 0;
+ alloc_type_ = type;
+ if (!IsMMapped()) {
+ *magic2_addr() = magic1_;
+ *size2_addr() = size;
+ }
+ alloc_map_lock_.Unlock();
+ memset(data_addr(), kMagicUninitializedByte, size);
+ if (!IsMMapped()) {
+ RAW_CHECK(size1_ == *size2_addr(), "should hold");
+ RAW_CHECK(magic1_ == *magic2_addr(), "should hold");
+ }
+ }
+
+ size_t CheckAndClear(int type) {
+ alloc_map_lock_.Lock();
+ CheckLocked(type);
+ if (!IsMMapped()) {
+ RAW_CHECK(size1_ == *size2_addr(), "should hold");
+ }
+ // record us as deallocated in the map
+ alloc_map_->Insert(data_addr(), type | kDeallocatedTypeBit);
+ alloc_map_lock_.Unlock();
+ // clear us
+ const size_t size = real_size();
+ memset(this, kMagicDeletedByte, size);
+ return size;
+ }
+
+ void CheckLocked(int type) const {
+ int map_type = 0;
+ const int* found_type =
+ alloc_map_ != NULL ? alloc_map_->Find(data_addr()) : NULL;
+ if (found_type == NULL) {
+ RAW_LOG(FATAL, "memory allocation bug: object at %p "
+ "has never been allocated", data_addr());
+ } else {
+ map_type = *found_type;
+ }
+ if ((map_type & kDeallocatedTypeBit) != 0) {
+ RAW_LOG(FATAL, "memory allocation bug: object at %p "
+ "has been already deallocated (it was allocated with %s)",
+ data_addr(), AllocName(map_type & ~kDeallocatedTypeBit));
+ }
+ if (alloc_type_ == kMagicDeletedInt) {
+ RAW_LOG(FATAL, "memory stomping bug: a word before object at %p "
+ "has been corrupted; or else the object has been already "
+ "deallocated and our memory map has been corrupted",
+ data_addr());
+ }
+ if (!IsValidMagicValue(magic1_)) {
+ RAW_LOG(FATAL, "memory stomping bug: a word before object at %p "
+ "has been corrupted; "
+ "or else our memory map has been corrupted and this is a "
+ "deallocation for not (currently) heap-allocated object",
+ data_addr());
+ }
+ if (!IsMMapped()) {
+ if (size1_ != *size2_addr()) {
+ RAW_LOG(FATAL, "memory stomping bug: a word after object at %p "
+ "has been corrupted", data_addr());
+ }
+ if (!IsValidMagicValue(*magic2_addr())) {
+ RAW_LOG(FATAL, "memory stomping bug: a word after object at %p "
+ "has been corrupted", data_addr());
+ }
+ }
+ if (alloc_type_ != type) {
+ if ((alloc_type_ != MallocBlock::kMallocType) &&
+ (alloc_type_ != MallocBlock::kNewType) &&
+ (alloc_type_ != MallocBlock::kArrayNewType)) {
+ RAW_LOG(FATAL, "memory stomping bug: a word before object at %p "
+ "has been corrupted", data_addr());
+ }
+ RAW_LOG(FATAL, "memory allocation/deallocation mismatch at %p: "
+ "allocated with %s being deallocated with %s",
+ data_addr(), AllocName(alloc_type_), DeallocName(type));
+ }
+ if (alloc_type_ != map_type) {
+ RAW_LOG(FATAL, "memory stomping bug: our memory map has been corrupted : "
+ "allocation at %p made with %s "
+ "is recorded in the map to be made with %s",
+ data_addr(), AllocName(alloc_type_), AllocName(map_type));
+ }
+ }
+
+ public: // public accessors
+
+ void* data_addr() { return (void*)&size2_; }
+ const void* data_addr() const { return (const void*)&size2_; }
+
+ static size_t data_offset() { return OFFSETOF_MEMBER(MallocBlock, size2_); }
+
+ size_t data_size() const { return size1_; }
+
+ void set_offset(int offset) { this->offset_ = offset; }
+
+ public: // our main interface
+
+ static MallocBlock* Allocate(size_t size, int type) {
+ // Prevent an integer overflow / crash with large allocation sizes.
+ // TODO - Note that for a e.g. 64-bit size_t, max_size_t may not actually
+ // be the maximum value, depending on how the compiler treats ~0. The worst
+ // practical effect is that allocations are limited to 4Gb or so, even if
+ // the address space could take more.
+ static size_t max_size_t = ~0;
+ if (size < 0 || size > max_size_t - sizeof(MallocBlock)) {
+ RAW_LOG(ERROR, "Massive size passed to malloc: %"PRIuS"", size);
+ return NULL;
+ }
+ MallocBlock* b = NULL;
+ const bool use_malloc_page_fence = FLAGS_malloc_page_fence;
+#ifdef HAVE_MMAP
+ if (use_malloc_page_fence) {
+ // Put the block towards the end of the page and make the next page
+ // inaccessible. This will catch buffer overrun right when it happens.
+ size_t sz = real_mmapped_size(size);
+ int pagesize = getpagesize();
+ int num_pages = (sz + pagesize - 1) / pagesize + 1;
+ char* p = (char*) mmap(NULL, num_pages * pagesize, PROT_READ|PROT_WRITE,
+ MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+ if (p == MAP_FAILED) {
+ // If the allocation fails, abort rather than returning NULL to
+ // malloc. This is because in most cases, the program will run out
+ // of memory in this mode due to tremendous amount of wastage. There
+ // is no point in propagating the error elsewhere.
+ RAW_LOG(FATAL, "Out of memory: possibly due to page fence overhead: %s",
+ strerror(errno));
+ }
+ // Mark the page after the block inaccessible
+ if (mprotect(p + (num_pages - 1) * pagesize, pagesize, PROT_NONE)) {
+ RAW_LOG(FATAL, "Guard page setup failed: %s", strerror(errno));
+ }
+ b = (MallocBlock*) (p + (num_pages - 1) * pagesize - sz);
+ } else {
+ b = (MallocBlock*) BASE_MALLOC(real_malloced_size(size));
+ }
+#else
+ b = (MallocBlock*) BASE_MALLOC(real_malloced_size(size));
+#endif
+
+ // It would be nice to output a diagnostic on allocation failure
+ // here, but logging (other than FATAL) requires allocating
+ // memory, which could trigger a nasty recursion. Instead, preserve
+ // malloc semantics and return NULL on failure.
+ if (b != NULL) {
+ b->magic1_ = use_malloc_page_fence ? kMagicMMap : kMagicMalloc;
+ b->Initialize(size, type);
+ }
+ return b;
+ }
+
+ void Deallocate(int type) {
+ if (IsMMapped()) { // have to do this before CheckAndClear
+#ifdef HAVE_MMAP
+ int size = CheckAndClear(type);
+ int pagesize = getpagesize();
+ int num_pages = (size + pagesize - 1) / pagesize + 1;
+ char* p = (char*) this;
+ if (FLAGS_malloc_page_fence_never_reclaim ||
+ !FLAGS_malloc_reclaim_memory) {
+ mprotect(p - (num_pages - 1) * pagesize + size,
+ num_pages * pagesize, PROT_NONE);
+ } else {
+ munmap(p - (num_pages - 1) * pagesize + size, num_pages * pagesize);
+ }
+#endif
+ } else {
+ const size_t size = CheckAndClear(type);
+ if (FLAGS_malloc_reclaim_memory) {
+ // Instead of freeing the block immediately, push it onto a queue of
+ // recently freed blocks. Free only enough blocks to keep from
+ // exceeding the capacity of the queue or causing the total amount of
+ // un-released memory in the queue from exceeding
+ // FLAGS_max_free_queue_size.
+ ProcessFreeQueue(this, size, FLAGS_max_free_queue_size);
+ }
+ }
+ }
+
+ static size_t FreeQueueSize() {
+ SpinLockHolder l(&free_queue_lock_);
+ return free_queue_size_;
+ }
+
+ static void ProcessFreeQueue(MallocBlock* b, size_t size,
+ int max_free_queue_size) {
+ SpinLockHolder l(&free_queue_lock_);
+ if (free_queue_ == NULL)
+ free_queue_ = new FreeQueue<MallocBlockQueueEntry>;
+ RAW_CHECK(!free_queue_->Full(), "Free queue mustn't be full!");
+
+ if (b != NULL) {
+ free_queue_size_ += size + sizeof(MallocBlockQueueEntry);
+ MallocBlockQueueEntry new_entry(b, size);
+ free_queue_->Push(new_entry);
+ }
+
+ // Free blocks until the total size of unfreed blocks no longer exceeds
+ // max_free_queue_size, and the free queue has at least one free
+ // space in it.
+ while (free_queue_size_ > max_free_queue_size || free_queue_->Full()) {
+ MallocBlockQueueEntry cur = free_queue_->Pop();
+ CheckForDanglingWrites(cur);
+ free_queue_size_ -= cur.size + sizeof(MallocBlockQueueEntry);
+ BASE_FREE(cur.block);
+ }
+ RAW_CHECK(free_queue_size_ >= 0, "Free queue size went negative!");
+ }
+
+ static void CheckForDanglingWrites(const MallocBlockQueueEntry& queue_entry) {
+ // Initialize the buffer if necessary.
+ if (!deleted_buffer_initialized_) {
+ // This is threadsafe. We hold free_queue_lock_.
+ memset(kMagicDeletedBuffer, 0xcd, sizeof(kMagicDeletedBuffer));
+ deleted_buffer_initialized_ = true;
+ }
+
+ const unsigned char* p =
+ reinterpret_cast<unsigned char*>(queue_entry.block);
+
+ static const size_t size_of_buffer = sizeof(kMagicDeletedBuffer);
+ const size_t size = queue_entry.size;
+ const size_t buffers = size / size_of_buffer;
+ const size_t remainder = size % size_of_buffer;
+ size_t buffer_idx;
+ for (buffer_idx = 0; buffer_idx < buffers; ++buffer_idx) {
+ CheckForCorruptedBuffer(queue_entry, buffer_idx, p, size_of_buffer);
+ p += size_of_buffer;
+ }
+ CheckForCorruptedBuffer(queue_entry, buffer_idx, p, remainder);
+ }
+
+ static void CheckForCorruptedBuffer(const MallocBlockQueueEntry& queue_entry,
+ size_t buffer_idx,
+ const unsigned char* buffer,
+ size_t size_of_buffer) {
+ if (memcmp(buffer, kMagicDeletedBuffer, size_of_buffer) == 0) {
+ return;
+ }
+
+ RAW_LOG(ERROR,
+ "Found a corrupted memory buffer in MallocBlock (may be offset "
+ "from user ptr): buffer index: %zd, buffer ptr: %p, size of "
+ "buffer: %zd", buffer_idx, buffer, size_of_buffer);
+
+ // The magic deleted buffer should only be 1024 bytes, but in case
+ // this changes, let's put an upper limit on the number of debug
+ // lines we'll output:
+ if (size_of_buffer <= 1024) {
+ for (int i = 0; i < size_of_buffer; ++i) {
+ if (buffer[i] != 0xcd) {
+ RAW_LOG(ERROR, "Buffer byte %d is 0x%02x (should be 0xcd).",
+ i, buffer[i]);
+ }
+ }
+ } else {
+ RAW_LOG(ERROR, "Buffer too large to print corruption.");
+ }
+
+ const MallocBlock* b = queue_entry.block;
+ const size_t size = queue_entry.size;
+ if (queue_entry.num_deleter_pcs > 0) {
+ TracePrintf(STDERR_FILENO, "Deleted by thread %p\n",
+ reinterpret_cast<void*>(
+ PRINTABLE_PTHREAD(queue_entry.deleter_threadid)));
+ char sym[1000];
+ for (int i = 0; i < queue_entry.num_deleter_pcs; i++) {
+ char* pc = reinterpret_cast<char*>(queue_entry.deleter_pcs[i]);
+ // Symbolizes the previous address of pc because pc may be in the
+ // next function. This may happen when the function ends with
+ // a call to a function annotated noreturn (e.g. CHECK).
+ if (FLAGS_symbolize_stacktrace && Symbolize(pc-1, sym, sizeof(sym))) {
+ // sym has been computed
+ } else {
+ sym[0] = '\0';
+ }
+ TracePrintf(STDERR_FILENO, " @ %p %s\n", pc, sym);
+ }
+ } else {
+ RAW_LOG(ERROR,
+ "Skipping the printing of the deleter's stack! Its stack was "
+ "not found; either the corruption occurred too early in "
+ "execution to obtain a stack trace or --max_free_queue_size was "
+ "set to 0.");
+ }
+
+ RAW_LOG(FATAL,
+ "Memory was written to after being freed. MallocBlock: %p, user "
+ "ptr: %p, size: %zd. If you can't find the source of the error, "
+ "try using valgrind or purify, or study the output of the "
+ "deleter's stack printed above.", b, b->data_addr(), size);
+ }
+
+ static MallocBlock* FromRawPointer(void* p) {
+ const size_t data_offset = MallocBlock::data_offset();
+ // Find the header just before client's memory.
+ MallocBlock *mb = reinterpret_cast<MallocBlock *>(
+ reinterpret_cast<char *>(p) - data_offset);
+ // If mb->offset_ is zero (common case), mb is the real header. If
+ // mb->offset_ is non-zero, this block was allocated by memalign, and
+ // mb->offset_ is the distance backwards to the real header from mb,
+ // which is a fake header. The following subtraction works for both zero
+ // and non-zero values.
+ return reinterpret_cast<MallocBlock *>(
+ reinterpret_cast<char *>(mb) - mb->offset_);
+ }
+ static const MallocBlock* FromRawPointer(const void* p) {
+ // const-safe version: we just cast about
+ return FromRawPointer(const_cast<void*>(p));
+ }
+
+ void Check(int type) {
+ alloc_map_lock_.Lock();
+ CheckLocked(type);
+ alloc_map_lock_.Unlock();
+ }
+
+ static bool CheckEverything() {
+ alloc_map_lock_.Lock();
+ if (alloc_map_ != NULL) alloc_map_->Iterate(CheckCallback, 0);
+ alloc_map_lock_.Unlock();
+ return true; // if we get here, we're okay
+ }
+
+ static bool MemoryStats(int* blocks, size_t* total,
+ int histogram[kMallocHistogramSize]) {
+ memset(histogram, 0, kMallocHistogramSize * sizeof(int));
+ alloc_map_lock_.Lock();
+ stats_blocks_ = 0;
+ stats_total_ = 0;
+ stats_histogram_ = histogram;
+ if (alloc_map_ != NULL) alloc_map_->Iterate(StatsCallback, 0);
+ *blocks = stats_blocks_;
+ *total = stats_total_;
+ alloc_map_lock_.Unlock();
+ return true;
+ }
+
+ private: // helpers for CheckEverything and MemoryStats
+
+ static void CheckCallback(const void* ptr, int* type, int dummy) {
+ if ((*type & kDeallocatedTypeBit) == 0) {
+ FromRawPointer(ptr)->CheckLocked(*type);
+ }
+ }
+
+ // Accumulation variables for StatsCallback protected by alloc_map_lock_
+ static int stats_blocks_;
+ static size_t stats_total_;
+ static int* stats_histogram_;
+
+ static void StatsCallback(const void* ptr, int* type, int dummy) {
+ if ((*type & kDeallocatedTypeBit) == 0) {
+ const MallocBlock* b = FromRawPointer(ptr);
+ b->CheckLocked(*type);
+ ++stats_blocks_;
+ size_t mysize = b->size1_;
+ int entry = 0;
+ stats_total_ += mysize;
+ while (mysize) {
+ ++entry;
+ mysize >>= 1;
+ }
+ RAW_CHECK(entry < kMallocHistogramSize,
+ "kMallocHistogramSize should be at least as large as log2 "
+ "of the maximum process memory size");
+ stats_histogram_[entry] += 1;
+ }
+ }
+};
+
+void DanglingWriteChecker() {
+ // Clear out the remaining free queue to check for dangling writes.
+ MallocBlock::ProcessFreeQueue(NULL, 0, 0);
+}
+
+// ========================================================================= //
+
+const int MallocBlock::kMagicMalloc;
+const int MallocBlock::kMagicMMap;
+
+MallocBlock::AllocMap* MallocBlock::alloc_map_ = NULL;
+SpinLock MallocBlock::alloc_map_lock_(SpinLock::LINKER_INITIALIZED);
+
+FreeQueue<MallocBlockQueueEntry>* MallocBlock::free_queue_ = NULL;
+size_t MallocBlock::free_queue_size_ = 0;
+SpinLock MallocBlock::free_queue_lock_(SpinLock::LINKER_INITIALIZED);
+
+unsigned char MallocBlock::kMagicDeletedBuffer[1024];
+bool MallocBlock::deleted_buffer_initialized_ = false;
+
+const char* const MallocBlock::kAllocName[] = {
+ "malloc",
+ "new",
+ "new []",
+ NULL,
+};
+
+const char* const MallocBlock::kDeallocName[] = {
+ "free",
+ "delete",
+ "delete []",
+ NULL,
+};
+
+int MallocBlock::stats_blocks_;
+size_t MallocBlock::stats_total_;
+int* MallocBlock::stats_histogram_;
+
+// ========================================================================= //
+
+// The following cut-down version of printf() avoids
+// using stdio or ostreams.
+// This is to guarantee no recursive calls into
+// the allocator and to bound the stack space consumed. (The pthread
+// manager thread in linuxthreads has a very small stack,
+// so fprintf can't be called.)
+static void TracePrintf(int fd, const char *fmt, ...) {
+ char buf[64];
+ int i = 0;
+ va_list ap;
+ va_start(ap, fmt);
+ const char *p = fmt;
+ char numbuf[25];
+ numbuf[sizeof(numbuf)-1] = 0;
+ while (*p != '\0') { // until end of format string
+ char *s = &numbuf[sizeof(numbuf)-1];
+ if (p[0] == '%' && p[1] != 0) { // handle % formats
+ int64 l = 0;
+ unsigned long base = 0;
+ if (*++p == 's') { // %s
+ s = va_arg(ap, char *);
+ } else if (*p == 'l' && p[1] == 'd') { // %ld
+ l = va_arg(ap, long);
+ base = 10;
+ p++;
+ } else if (*p == 'l' && p[1] == 'u') { // %lu
+ l = va_arg(ap, unsigned long);
+ base = 10;
+ p++;
+ } else if (*p == 'z' && p[1] == 'u') { // %zu
+ l = va_arg(ap, size_t);
+ base = 10;
+ p++;
+ } else if (*p == 'u') { // %u
+ l = va_arg(ap, unsigned int);
+ base = 10;
+ } else if (*p == 'd') { // %d
+ l = va_arg(ap, int);
+ base = 10;
+ } else if (*p == 'p') { // %p
+ l = va_arg(ap, intptr_t);
+ base = 16;
+ } else {
+ write(STDERR_FILENO, "Unimplemented TracePrintf format\n", 33);
+ write(STDERR_FILENO, p, 2);
+ write(STDERR_FILENO, "\n", 1);
+ abort();
+ }
+ p++;
+ if (base != 0) {
+ bool minus = (l < 0 && base == 10);
+ uint64 ul = minus? -l : l;
+ do {
+ *--s = "0123456789abcdef"[ul % base];
+ ul /= base;
+ } while (ul != 0);
+ if (base == 16) {
+ *--s = 'x';
+ *--s = '0';
+ } else if (minus) {
+ *--s = '-';
+ }
+ }
+ } else { // handle normal characters
+ *--s = *p++;
+ }
+ while (*s != 0) {
+ if (i == sizeof(buf)) {
+ write(fd, buf, i);
+ i = 0;
+ }
+ buf[i++] = *s++;
+ }
+ }
+ if (i != 0) {
+ write(fd, buf, i);
+ }
+ va_end(ap);
+}
+
+// Return the file descriptor we're writing a log to
+static int TraceFd() {
+ static int trace_fd = -1;
+ if (trace_fd == -1) { // Open the trace file on the first call
+ trace_fd = open("/tmp/google.alloc", O_CREAT|O_TRUNC|O_WRONLY, 0666);
+ if (trace_fd == -1) {
+ trace_fd = 2;
+ TracePrintf(trace_fd,
+ "Can't open /tmp/google.alloc. Logging to stderr.\n");
+ }
+ // Add a header to the log.
+ TracePrintf(trace_fd, "Trace started: %lu\n",
+ static_cast<unsigned long>(time(NULL)));
+ TracePrintf(trace_fd,
+ "func\tsize\tptr\tthread_id\tstack pcs for tools/symbolize\n");
+ }
+ return trace_fd;
+}
+
+// Print the hex stack dump on a single line. PCs are separated by tabs.
+static void TraceStack(void) {
+ void *pcs[16];
+ int n = GetStackTrace(pcs, sizeof(pcs)/sizeof(pcs[0]), 0);
+ for (int i = 0; i != n; i++) {
+ TracePrintf(TraceFd(), "\t%p", pcs[i]);
+ }
+}
+
+// This protects MALLOC_TRACE, to make sure its info is atomically written.
+static SpinLock malloc_trace_lock(SpinLock::LINKER_INITIALIZED);
+
+#define MALLOC_TRACE(name, size, addr) \
+ do { \
+ if (FLAGS_malloctrace) { \
+ SpinLockHolder l(&malloc_trace_lock); \
+ TracePrintf(TraceFd(), "%s\t%"PRIuS"\t%p\t%"GPRIuPTHREAD, \
+ name, size, addr, PRINTABLE_PTHREAD(pthread_self())); \
+ TraceStack(); \
+ TracePrintf(TraceFd(), "\n"); \
+ } \
+ } while (0)
+
+// ========================================================================= //
+
+// Write the characters buf[0, ..., size-1] to
+// the malloc trace buffer.
+// This function is intended for debugging,
+// and is not declared in any header file.
+// You must insert a declaration of it by hand when you need
+// to use it.
+void __malloctrace_write(const char *buf, size_t size) {
+ if (FLAGS_malloctrace) {
+ write(TraceFd(), buf, size);
+ }
+}
+
+// ========================================================================= //
+
+// General debug allocation/deallocation
+
+static inline void* DebugAllocate(size_t size, int type) {
+ MallocBlock* ptr = MallocBlock::Allocate(size, type);
+ if (ptr == NULL) return NULL;
+ MALLOC_TRACE("malloc", size, ptr->data_addr());
+ return ptr->data_addr();
+}
+
+static inline void DebugDeallocate(void* ptr, int type) {
+ MALLOC_TRACE("free",
+ (ptr != 0 ? MallocBlock::FromRawPointer(ptr)->data_size() : 0),
+ ptr);
+ if (ptr) MallocBlock::FromRawPointer(ptr)->Deallocate(type);
+}
+
+// ========================================================================= //
+
+// Alloc/free stuff for debug hooks for malloc & friends
+
+// CAVEAT: The code structure below ensures that MallocHook methods are always
+// called from the stack frame of the invoked allocation function.
+// heap-checker.cc depends on this to start a stack trace from
+// the call to the (de)allocation function.
+
+// Put all callers of MallocHook::Invoke* in this module into
+// ATTRIBUTE_SECTION(google_malloc) section,
+// so that MallocHook::GetCallerStackTrace can function accurately:
+
+extern "C" {
+ void* malloc(size_t size) __THROW ATTRIBUTE_SECTION(google_malloc);
+ void free(void* ptr) __THROW ATTRIBUTE_SECTION(google_malloc);
+ void* realloc(void* ptr, size_t size) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+ void* calloc(size_t nmemb, size_t size) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+ void cfree(void* ptr) __THROW ATTRIBUTE_SECTION(google_malloc);
+
+ void* memalign(size_t __alignment, size_t __size) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+ int posix_memalign(void** ptr, size_t align, size_t size) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+ void* valloc(size_t __size) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+ void* pvalloc(size_t __size) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+}
+
+static void *MemalignOverride(size_t align, size_t size,
+ const void *caller) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+
+void* operator new(size_t size)
+ ATTRIBUTE_SECTION(google_malloc);
+void* operator new(size_t size, const std::nothrow_t&) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+void operator delete(void* p) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+void* operator new[](size_t size)
+ ATTRIBUTE_SECTION(google_malloc);
+void* operator new[](size_t size, const std::nothrow_t&) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+void operator delete[](void* p) __THROW
+ ATTRIBUTE_SECTION(google_malloc);
+
+extern "C" void* malloc(size_t size) __THROW {
+ void* ptr = DebugAllocate(size, MallocBlock::kMallocType);
+ MallocHook::InvokeNewHook(ptr, size);
+ return ptr;
+}
+
+extern "C" void free(void* ptr) __THROW {
+ MallocHook::InvokeDeleteHook(ptr);
+ DebugDeallocate(ptr, MallocBlock::kMallocType);
+}
+
+extern "C" void* realloc(void* ptr, size_t size) __THROW {
+ if (ptr == NULL) {
+ ptr = DebugAllocate(size, MallocBlock::kMallocType);
+ MallocHook::InvokeNewHook(ptr, size);
+ return ptr;
+ }
+ if (size == 0) {
+ MallocHook::InvokeDeleteHook(ptr);
+ DebugDeallocate(ptr, MallocBlock::kMallocType);
+ return NULL;
+ }
+ MallocBlock* old = MallocBlock::FromRawPointer(ptr);
+ old->Check(MallocBlock::kMallocType);
+ MallocBlock* p = MallocBlock::Allocate(size, MallocBlock::kMallocType);
+
+ // If realloc fails we are to leave the old block untouched and
+ // return null
+ if (p == NULL) return NULL;
+
+ memcpy(p->data_addr(), old->data_addr(),
+ (old->data_size() < size) ? old->data_size() : size);
+ MallocHook::InvokeDeleteHook(ptr);
+ MallocHook::InvokeNewHook(p->data_addr(), size);
+ DebugDeallocate(ptr, MallocBlock::kMallocType);
+ MALLOC_TRACE("realloc", p->data_size(), p->data_addr());
+ return p->data_addr();
+}
+
+extern "C" void* calloc(size_t count, size_t size) __THROW {
+ // Overflow check
+ const size_t total_size = count * size;
+ if (size != 0 && total_size / size != count) return NULL;
+
+ void* block = DebugAllocate(total_size, MallocBlock::kMallocType);
+ MallocHook::InvokeNewHook(block, total_size);
+ if (block) memset(block, 0, total_size);
+ return block;
+}
+
+extern "C" void cfree(void* ptr) __THROW {
+ MallocHook::InvokeDeleteHook(ptr);
+ DebugDeallocate(ptr, MallocBlock::kMallocType);
+}
+
+// Round "value" up to next "alignment" boundary.
+// Requires that "alignment" be a power of two.
+static intptr_t RoundUp(intptr_t value, intptr_t alignment) {
+ return (value + alignment - 1) & ~(alignment - 1);
+}
+
+static void *do_debug_memalign(size_t alignment, size_t size) {
+ // Allocate >= size bytes aligned on "alignment" boundary
+ // "alignment" is a power of two.
+ void *p = 0;
+ RAW_CHECK((alignment & (alignment-1)) == 0, "must be power of two");
+ const size_t data_offset = MallocBlock::data_offset();
+ // Allocate "alignment-1" extra bytes to ensure alignment is possible, and
+ // a further data_offset bytes for an additional fake header.
+ size_t extra_bytes = data_offset + alignment - 1;
+ if (size + extra_bytes < size) return NULL; // Overflow
+ p = DebugAllocate(size + extra_bytes, MallocBlock::kMallocType);
+ if (p != 0) {
+ intptr_t orig_p = reinterpret_cast<intptr_t>(p);
+ // Leave data_offset bytes for fake header, and round up to meet
+ // alignment.
+ p = reinterpret_cast<void *>(RoundUp(orig_p + data_offset, alignment));
+ // Create a fake header block with an offset_ that points back to the
+ // real header. FromRawPointer uses this value.
+ MallocBlock *fake_hdr = reinterpret_cast<MallocBlock *>(
+ reinterpret_cast<char *>(p) - data_offset);
+ // offset_ is distance between real and fake headers.
+ // p is now end of fake header (beginning of client area),
+ // and orig_p is the end of the real header, so offset_
+ // is their difference.
+ fake_hdr->set_offset(reinterpret_cast<intptr_t>(p) - orig_p);
+ }
+ return p;
+}
+
+// Override __libc_memalign in libc on linux boxes.
+// They have a bug in libc that causes them (very rarely) to allocate
+// with __libc_memalign() yet deallocate with free().
+// This function is an exception to the rule of calling MallocHook method
+// from the stack frame of the allocation function;
+// heap-checker handles this special case explicitly.
+static void *MemalignOverride(size_t align, size_t size,
+ const void *caller) __THROW {
+ void *p = do_debug_memalign(align, size);
+ MallocHook::InvokeNewHook(p, size);
+ return p;
+}
+void *(*__memalign_hook)(size_t, size_t, const void *) = MemalignOverride;
+
+extern "C" void* memalign(size_t align, size_t size) __THROW {
+ void *p = do_debug_memalign(align, size);
+ MallocHook::InvokeNewHook(p, size);
+ return p;
+}
+
+// Implementation taken from tcmalloc/tcmalloc.cc
+extern "C" int posix_memalign(void** result_ptr,
+ size_t align, size_t size) __THROW {
+ if (((align % sizeof(void*)) != 0) ||
+ ((align & (align - 1)) != 0) ||
+ (align == 0)) {
+ return EINVAL;
+ }
+
+ void* result = do_debug_memalign(align, size);
+ MallocHook::InvokeNewHook(result, size);
+ if (result == NULL) {
+ return ENOMEM;
+ } else {
+ *result_ptr = result;
+ return 0;
+ }
+}
+
+extern "C" void* valloc(size_t size) __THROW {
+ // Allocate >= size bytes starting on a page boundary
+ void *p = do_debug_memalign(getpagesize(), size);
+ MallocHook::InvokeNewHook(p, size);
+ return p;
+}
+
+extern "C" void* pvalloc(size_t size) __THROW {
+ // Round size up to a multiple of pages
+ // then allocate memory on a page boundary
+ int pagesize = getpagesize();
+ size = RoundUp(size, pagesize);
+ if (size == 0) { // pvalloc(0) should allocate one page, according to
+ size = pagesize; // http://man.free4web.biz/man3/libmpatrol.3.html
+ }
+ void *p = do_debug_memalign(pagesize, size);
+ MallocHook::InvokeNewHook(p, size);
+ return p;
+}
+
+extern "C" int mallopt(int cmd, int value) {
+ return BASE_MALLOPT(cmd, value);
+}
+
+#ifdef HAVE_STRUCT_MALLINFO
+extern "C" struct mallinfo mallinfo(void) {
+ return BASE_MALLINFO();
+}
+#endif
+
+// ========================================================================= //
+
+// Alloc/free stuff for debug operator new & friends
+
+// This is mostly the same a cpp_alloc in tcmalloc.cc.
+inline void* cpp_debug_alloc(size_t size, int new_type, bool nothrow) {
+ for (;;) {
+ void* p = DebugAllocate(size, new_type);
+#ifdef PREANSINEW
+ return p;
+#else
+ if (p == NULL) { // allocation failed
+ // Get the current new handler. NB: this function is not
+ // thread-safe. We make a feeble stab at making it so here, but
+ // this lock only protects against tcmalloc interfering with
+ // itself, not with other libraries calling set_new_handler.
+ std::new_handler nh;
+ {
+ SpinLockHolder h(&set_new_handler_lock);
+ nh = std::set_new_handler(0);
+ (void) std::set_new_handler(nh);
+ }
+#if (defined(__GNUC__) && !defined(__EXCEPTIONS)) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS)
+ if (nh) {
+ // Since exceptions are disabled, we don't really know if new_handler
+ // failed. Assume it will abort if it fails.
+ (*nh)();
+ continue;
+ }
+ return 0;
+#else
+ // If no new_handler is established, the allocation failed.
+ if (!nh) {
+ if (nothrow) return 0;
+ throw std::bad_alloc();
+ }
+ // Otherwise, try the new_handler. If it returns, retry the
+ // allocation. If it throws std::bad_alloc, fail the allocation.
+ // if it throws something else, don't interfere.
+ try {
+ (*nh)();
+ } catch (const std::bad_alloc&) {
+ if (!nothrow) throw;
+ return p;
+ }
+#endif // (defined(__GNUC__) && !defined(__EXCEPTIONS)) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS)
+ } else { // allocation success
+ return p;
+ }
+#endif // PREANSINEW
+ }
+}
+
+void* operator new(size_t size) {
+ void* ptr = cpp_debug_alloc(size, MallocBlock::kNewType, false);
+ MallocHook::InvokeNewHook(ptr, size);
+ if (ptr == NULL) {
+ RAW_LOG(FATAL, "Unable to allocate %"PRIuS" bytes: new failed.", size);
+ }
+ return ptr;
+}
+
+void* operator new(size_t size, const std::nothrow_t&) __THROW {
+ void* ptr = cpp_debug_alloc(size, MallocBlock::kNewType, true);
+ MallocHook::InvokeNewHook(ptr, size);
+ return ptr;
+}
+
+void operator delete(void* ptr) __THROW {
+ MallocHook::InvokeDeleteHook(ptr);
+ DebugDeallocate(ptr, MallocBlock::kNewType);
+}
+
+// ========================================================================= //
+
+// Alloc/free stuff for debug operator new[] & friends
+
+void* operator new[](size_t size) {
+ void* ptr = cpp_debug_alloc(size, MallocBlock::kArrayNewType, false);
+ MallocHook::InvokeNewHook(ptr, size);
+ if (ptr == NULL) {
+ RAW_LOG(FATAL, "Unable to allocate %"PRIuS" bytes: new[] failed.", size);
+ }
+ return ptr;
+}
+
+void* operator new[](size_t size, const std::nothrow_t&) __THROW {
+ void* ptr = cpp_debug_alloc(size, MallocBlock::kArrayNewType, true);
+ MallocHook::InvokeNewHook(ptr, size);
+ return ptr;
+}
+
+void operator delete[](void* ptr) __THROW {
+ MallocHook::InvokeDeleteHook(ptr);
+ DebugDeallocate(ptr, MallocBlock::kArrayNewType);
+}
+
+// ========================================================================= //
+
+// The following functions may be called via MallocExtension::instance()
+// for memory verification and statistics.
+#ifdef TCMALLOC_FOR_DEBUGALLOCATION
+// Inherit from tcmalloc's version
+typedef TCMallocImplementation ParentImplementation;
+#else
+// Inherit from default version
+typedef MallocExtension ParentImplementation;
+#endif
+
+class DebugMallocImplementation : public ParentImplementation {
+ public:
+ virtual bool GetNumericProperty(const char* name, size_t* value) {
+ bool result = ParentImplementation::GetNumericProperty(name, value);
+ if (result && (strcmp(name, "generic.current_allocated_bytes") == 0)) {
+ // Subtract bytes kept in the free queue
+ size_t qsize = MallocBlock::FreeQueueSize();
+ if (*value >= qsize) {
+ *value -= qsize;
+ }
+ }
+ return result;
+ }
+
+ virtual bool VerifyNewMemory(void* p) {
+ if (p) MallocBlock::FromRawPointer(p)->Check(MallocBlock::kNewType);
+ return true;
+ }
+
+ virtual bool VerifyArrayNewMemory(void* p) {
+ if (p) MallocBlock::FromRawPointer(p)->Check(MallocBlock::kArrayNewType);
+ return true;
+ }
+
+ virtual bool VerifyMallocMemory(void* p) {
+ if (p) MallocBlock::FromRawPointer(p)->Check(MallocBlock::kMallocType);
+ return true;
+ }
+
+ virtual bool VerifyAllMemory() {
+ return MallocBlock::CheckEverything();
+ }
+
+ virtual bool MallocMemoryStats(int* blocks, size_t* total,
+ int histogram[kMallocHistogramSize]) {
+ return MallocBlock::MemoryStats(blocks, total, histogram);
+ }
+
+ virtual size_t GetAllocatedSize(void* p) {
+ if (p) {
+ return MallocBlock::FromRawPointer(p)->data_size();
+ }
+ return 0;
+ }
+ virtual size_t GetEstimatedAllocatedSize(size_t size) {
+ return size;
+ }
+ };
+
+static DebugMallocImplementation debug_malloc_implementation;
+
+REGISTER_MODULE_INITIALIZER(debugallocation, {
+ MallocExtension::Register(&debug_malloc_implementation);
+
+ // When the program exits, check all blocks still in the free queue for
+ // corruption.
+ atexit(DanglingWriteChecker);
+});
+
+#ifdef TCMALLOC_FOR_DEBUGALLOCATION
+
+// Redefine malloc_stats to use tcmalloc's implementation:
+extern "C" void malloc_stats(void) {
+ do_malloc_stats();
+}
+
+// Some library routines on RedHat 9 allocate memory using malloc()
+// and free it using __libc_free() (or vice-versa). Since we provide
+// our own implementations of malloc/free using tcmalloc.cc,
+// we need to make sure that the __libc_XXX variants
+// also point to the same implementations.
+//
+// Note: this might not override __libc_XXX calls withing libc itself,
+// but it can be important for other libraries that mention these functions
+// or when this code is LD_PRELOAD-ed.
+// TODO: In case these __libc_* definitions do not actually matter,
+// they should go away from here and from tcmalloc/tcmalloc.cc.
+//
+extern "C" {
+ void* __libc_malloc(size_t size) { return malloc(size); }
+ void __libc_free(void* ptr) { free(ptr); }
+ void* __libc_realloc(void* ptr, size_t size) { return realloc(ptr, size); }
+ void* __libc_calloc(size_t n, size_t size) { return calloc(n, size); }
+ void __libc_cfree(void* ptr) { cfree(ptr); }
+ void* __libc_memalign(size_t align, size_t s) { return memalign(align, s); }
+ void* __libc_valloc(size_t size) { return valloc(size); }
+ void* __libc_pvalloc(size_t size) { return pvalloc(size); }
+ int __posix_memalign(void** r, size_t a, size_t s) {
+ return posix_memalign(r, a, s);
+ }
+}
+
+#endif // #ifdef TCMALLOC_FOR_DEBUGALLOCATION
diff --git a/src/getpc.h b/src/getpc.h
index 1151e79..341457b 100644
--- a/src/getpc.h
+++ b/src/getpc.h
@@ -55,8 +55,11 @@
//#define _XOPEN_SOURCE 500
#include <string.h> // for memcmp
-#ifdef HAVE_UCONTEXT_H
+#if defined(HAVE_UCONTEXT_H)
#include <ucontext.h> // for ucontext_t (and also mcontext_t)
+#elif defined(HAVE_CYGWIN_SIGNAL_H)
+#include <cygwin/signal.h>
+typedef ucontext ucontext_t;
#endif
@@ -158,7 +161,9 @@ inline void* GetPC(const ucontext_t& signal_ucontext) {
// http://msdn2.microsoft.com/en-us/library/ms680650.aspx
#include "base/logging.h" // for RAW_LOG
+#ifndef HAVE_CYGWIN_SIGNAL_H
typedef int ucontext_t;
+#endif
inline void* GetPC(const struct ucontext_t& signal_ucontext) {
RAW_LOG(ERROR, "GetPC is not yet implemented on Windows\n");
diff --git a/src/google/heap-checker.h b/src/google/heap-checker.h
index acedd46..751eb9f 100644
--- a/src/google/heap-checker.h
+++ b/src/google/heap-checker.h
@@ -1,10 +1,10 @@
// Copyright (c) 2005, Google Inc.
// All rights reserved.
-//
+//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
-//
+//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
@@ -14,7 +14,7 @@
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
-//
+//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -51,8 +51,12 @@
#ifndef BASE_HEAP_CHECKER_H_
#define BASE_HEAP_CHECKER_H_
+#include "config.h"
+
#include <sys/types.h> // for size_t
+#ifdef HAVE_STDINT_H
#include <stdint.h> // for uintptr_t
+#endif
#include <stdarg.h> // for va_list
#include <vector>
@@ -181,6 +185,10 @@ class PERFTOOLS_DLL_DECL HeapLeakChecker {
// at the time of this call, it is ignored;
// but if it does, the object must not get deleted from the heap later on;
// it must also be not already ignored at the time of this call.
+ //
+ // See also HiddenPointer, below, if you need to prevent a pointer from
+ // being traversed by the heap checker but do not wish to transitively
+ // whitelist objects referenced through it.
static void IgnoreObject(const void* ptr);
// Undo what an earlier IgnoreObject() call promised and asked to do.
@@ -364,6 +372,26 @@ class PERFTOOLS_DLL_DECL HeapLeakChecker {
};
+// Holds a pointer that will not be traversed by the heap checker.
+// Contrast with HeapLeakChecker::IgnoreObject(o), in which o and
+// all objects reachable from o are ignored by the heap checker.
+template <class T>
+class HiddenPointer {
+ public:
+ explicit HiddenPointer(T* t)
+ : masked_t_(reinterpret_cast<uintptr_t>(t) ^ kHideMask) {
+ }
+ // Returns unhidden pointer. Be careful where you save the result.
+ T* get() const { return reinterpret_cast<T*>(masked_t_ ^ kHideMask); }
+
+ private:
+ // Arbitrary value, but not such that xor'ing with it is likely
+ // to map one valid pointer to another valid pointer:
+ static const uintptr_t kHideMask =
+ static_cast<uintptr_t>(0xF03A5F7BF03A5F7Bll);
+ uintptr_t masked_t_;
+};
+
// A class that exists solely to run its destructor. This class should not be
// used directly, but instead by the REGISTER_HEAPCHECK_CLEANUP macro below.
class PERFTOOLS_DLL_DECL HeapCleaner {
diff --git a/src/google/malloc_extension.h b/src/google/malloc_extension.h
index 2e05329..bc53e0f 100644
--- a/src/google/malloc_extension.h
+++ b/src/google/malloc_extension.h
@@ -160,6 +160,13 @@ class PERFTOOLS_DLL_DECL MallocExtension {
// Most malloc implementations ignore this routine.
virtual void MarkThreadIdle();
+ // Mark the current thread as "busy". This routine should be
+ // called after MarkThreadIdle() if the thread will now do more
+ // work. If this method is not called, performance may suffer.
+ //
+ // Most malloc implementations ignore this routine.
+ virtual void MarkThreadBusy();
+
// Try to free memory back to the operating system for reuse. Only
// use this extension if the application has recently freed a lot of
// memory, and does not anticipate using it again for a long time --
@@ -185,9 +192,11 @@ class PERFTOOLS_DLL_DECL MallocExtension {
// always return SIZE.)
virtual size_t GetEstimatedAllocatedSize(size_t size);
- // Returns the actual number of bytes reserved by tcmalloc for the
- // pointer p. This number may be equal to or greater than
- // the number of bytes requested when p was allocated.
+ // Returns the actual number N of bytes reserved by tcmalloc for the
+ // pointer p. The client is allowed to use the range of bytes
+ // [p, p+N) in any way it wishes (i.e. N is the "usable size" of this
+ // allocation). This number may be equal to or greater than the number
+ // of bytes requested when p was allocated.
// p must have been allocated by this malloc implementation,
// must not be an interior pointer -- that is, must be exactly
// the pointer returned to by malloc() et al., not some offset
diff --git a/src/google/malloc_extension_c.h b/src/google/malloc_extension_c.h
index b5e4df5..aa50c20 100644
--- a/src/google/malloc_extension_c.h
+++ b/src/google/malloc_extension_c.h
@@ -55,15 +55,14 @@
extern "C" {
#endif
-bool PERFTOOLS_DLL_DECL MallocExtension_VerifyAllMemory();
-bool PERFTOOLS_DLL_DECL MallocExtension_VerifyAllMemory();
-bool PERFTOOLS_DLL_DECL MallocExtension_VerifyNewMemory(void* p);
-bool PERFTOOLS_DLL_DECL MallocExtension_VerifyArrayNewMemory(void* p);
-bool PERFTOOLS_DLL_DECL MallocExtension_VerifyMallocMemory(void* p);
-bool PERFTOOLS_DLL_DECL MallocExtension_MallocMemoryStats(int* blocks, size_t* total,
+PERFTOOLS_DLL_DECL bool MallocExtension_VerifyAllMemory();
+PERFTOOLS_DLL_DECL bool MallocExtension_VerifyNewMemory(void* p);
+PERFTOOLS_DLL_DECL bool MallocExtension_VerifyArrayNewMemory(void* p);
+PERFTOOLS_DLL_DECL bool MallocExtension_VerifyMallocMemory(void* p);
+PERFTOOLS_DLL_DECL bool MallocExtension_MallocMemoryStats(int* blocks, size_t* total,
int histogram[kMallocHistogramSize]);
-void PERFTOOLS_DLL_DECL MallocExtension_GetStats(char* buffer, int buffer_length);
+PERFTOOLS_DLL_DECL void MallocExtension_GetStats(char* buffer, int buffer_length);
/* TODO(csilvers): write a C version of these routines, that perhaps
* takes a function ptr and a void *.
@@ -71,12 +70,13 @@ void PERFTOOLS_DLL_DECL MallocExtension_GetStats(char* buffer, int buffer_length
/* void MallocExtension_GetHeapSample(string* result); */
/* void MallocExtension_GetHeapGrowthStacks(string* result); */
-bool PERFTOOLS_DLL_DECL MallocExtension_GetNumericProperty(const char* property, size_t* value);
-bool PERFTOOLS_DLL_DECL MallocExtension_SetNumericProperty(const char* property, size_t value);
-void PERFTOOLS_DLL_DECL MallocExtension_MarkThreadIdle();
-void PERFTOOLS_DLL_DECL MallocExtension_ReleaseFreeMemory();
-size_t PERFTOOLS_DLL_DECL MallocExtension_GetEstimatedAllocatedSize(size_t size);
-size_t PERFTOOLS_DLL_DECL MallocExtension_GetAllocatedSize(void* p);
+PERFTOOLS_DLL_DECL bool MallocExtension_GetNumericProperty(const char* property, size_t* value);
+PERFTOOLS_DLL_DECL bool MallocExtension_SetNumericProperty(const char* property, size_t value);
+PERFTOOLS_DLL_DECL void MallocExtension_MarkThreadIdle();
+PERFTOOLS_DLL_DECL void MallocExtension_MarkThreadBusy();
+PERFTOOLS_DLL_DECL void MallocExtension_ReleaseFreeMemory();
+PERFTOOLS_DLL_DECL size_t MallocExtension_GetEstimatedAllocatedSize(size_t size);
+PERFTOOLS_DLL_DECL size_t MallocExtension_GetAllocatedSize(void* p);
#ifdef __cplusplus
} // extern "C"
diff --git a/src/google/tcmalloc.h.in b/src/google/tcmalloc.h.in
index f49b190..4937c62 100644
--- a/src/google/tcmalloc.h.in
+++ b/src/google/tcmalloc.h.in
@@ -42,37 +42,62 @@
# define __THROW /* __THROW is just an optimization, so ok to make it "" */
#endif
+// Define the version number so folks can check against it
+#define TC_VERSION_MAJOR @TC_VERSION_MAJOR@
+#define TC_VERSION_MINOR @TC_VERSION_MINOR@
+#define TC_VERSION_PATCH "@TC_VERSION_PATCH@"
+#define TC_VERSION_STRING "google-perftools @TC_VERSION_MAJOR@.@TC_VERSION_MINOR@@TC_VERSION_PATCH@"
+
#include <stdlib.h> // for struct mallinfo, if it's defined
+// Annoying stuff for windows -- makes sure clients can import these functions
+#ifndef PERFTOOLS_DLL_DECL
+# ifdef _WIN32
+# define PERFTOOLS_DLL_DECL __declspec(dllimport)
+# else
+# define PERFTOOLS_DLL_DECL
+# endif
+#endif
+
#ifdef __cplusplus
#include <new> // for nothrow_t
extern "C" {
#endif
- void* tc_malloc(size_t size) __THROW;
- void tc_free(void* ptr) __THROW;
- void* tc_realloc(void* ptr, size_t size) __THROW;
- void* tc_calloc(size_t nmemb, size_t size) __THROW;
- void tc_cfree(void* ptr) __THROW;
+ // Returns a human-readable version string. If major, minor,
+ // and/or patch are not NULL, they are set to the major version,
+ // minor version, and patch-code (a string, usually "").
+ PERFTOOLS_DLL_DECL const char* tc_version(int* major, int* minor,
+ const char** patch) __THROW;
+
+ PERFTOOLS_DLL_DECL void* tc_malloc(size_t size) __THROW;
+ PERFTOOLS_DLL_DECL void tc_free(void* ptr) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_realloc(void* ptr, size_t size) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_calloc(size_t nmemb, size_t size) __THROW;
+ PERFTOOLS_DLL_DECL void tc_cfree(void* ptr) __THROW;
- void* tc_memalign(size_t __alignment, size_t __size) __THROW;
- int tc_posix_memalign(void** ptr, size_t align, size_t size) __THROW;
- void* tc_valloc(size_t __size) __THROW;
- void* tc_pvalloc(size_t __size) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_memalign(size_t __alignment,
+ size_t __size) __THROW;
+ PERFTOOLS_DLL_DECL int tc_posix_memalign(void** ptr,
+ size_t align, size_t size) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_valloc(size_t __size) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_pvalloc(size_t __size) __THROW;
- void tc_malloc_stats(void) __THROW;
- int tc_mallopt(int cmd, int value) __THROW;
+ PERFTOOLS_DLL_DECL void tc_malloc_stats(void) __THROW;
+ PERFTOOLS_DLL_DECL int tc_mallopt(int cmd, int value) __THROW;
#if @ac_cv_have_struct_mallinfo@
- struct mallinfo tc_mallinfo(void) __THROW;
+ PERFTOOLS_DLL_DECL struct mallinfo tc_mallinfo(void) __THROW;
#endif
#ifdef __cplusplus
- void* tc_new(size_t size);
- void tc_delete(void* p) __THROW;
- void* tc_newarray(size_t size);
- void tc_deletearray(void* p) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_new(size_t size);
+ PERFTOOLS_DLL_DECL void tc_delete(void* p) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_newarray(size_t size);
+ PERFTOOLS_DLL_DECL void tc_deletearray(void* p) __THROW;
- void* tc_new_nothrow(size_t size, const std::nothrow_t&) __THROW;
- void* tc_newarray_nothrow(size_t size, const std::nothrow_t&) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_new_nothrow(size_t size,
+ const std::nothrow_t&) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_newarray_nothrow(size_t size,
+ const std::nothrow_t&) __THROW;
}
#endif
diff --git a/src/heap-checker.cc b/src/heap-checker.cc
index dc95404..2d0a19b 100644
--- a/src/heap-checker.cc
+++ b/src/heap-checker.cc
@@ -1,10 +1,10 @@
// Copyright (c) 2005, Google Inc.
// All rights reserved.
-//
+//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
-//
+//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
@@ -14,7 +14,7 @@
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
-//
+//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -33,7 +33,7 @@
// Author: Maxim Lifantsev
//
-#include <config.h>
+#include "config.h"
#include <fcntl.h> // for O_RDONLY (we use syscall to do actual reads)
#include <string.h>
@@ -47,7 +47,9 @@
#ifdef HAVE_PTHREAD
#include <pthread.h>
#endif
-#include <sys/poll.h>
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
#include <sys/stat.h>
#include <sys/types.h>
#include <assert.h>
@@ -1489,7 +1491,7 @@ void HeapLeakChecker::Create(const char *name, bool make_start_snapshot) {
} else {
RAW_LOG(WARNING, "Heap checker is not active, "
"hence checker \"%s\" will do nothing!", name);
- RAW_LOG(WARNING, "To activate set the HEAPCHECK environment variable.\n");
+ RAW_LOG(WARNING, "To activate set the HEAPCHECK environment variable.\n");
}
}
if (name_ == NULL) {
diff --git a/src/heap-profile-table.cc b/src/heap-profile-table.cc
index 08b7479..e71000f 100644
--- a/src/heap-profile-table.cc
+++ b/src/heap-profile-table.cc
@@ -37,12 +37,6 @@
#ifdef HAVE_UNISTD_H
#include <unistd.h> // for write()
#endif
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h> // for socketpair() -- needed by Symbolize
-#endif
-#ifdef HAVE_SYS_WAIT_H
-#include <sys/wait.h> // for wait() -- needed by Symbolize
-#endif
#include <fcntl.h> // for open()
#ifdef HAVE_GLOB_H
#include <glob.h>
@@ -53,6 +47,9 @@
#ifdef HAVE_INTTYPES_H
#include <inttypes.h> // for PRIxPTR
#endif
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
#include <errno.h>
#include <stdarg.h>
#include <string>
@@ -63,6 +60,7 @@
#include "base/logging.h"
#include "raw_printer.h"
+#include "symbolize.h"
#include <google/stacktrace.h>
#include <google/malloc_hook.h>
#include "base/commandlineflags.h"
@@ -84,15 +82,6 @@ DEFINE_bool(cleanup_old_heap_profiles,
EnvToBool("HEAP_PROFILE_CLEANUP", true),
"At initialization time, delete old heap profiles.");
-DEFINE_string(heap_profile_table_pprof,
- EnvToString("PPROF_PATH", "pprof"),
- "Path to pprof to call for reporting function names.");
-
-// heap_profile_table_pprof may be referenced after destructors are
-// called (since that's when leak-checking is done), so we make
-// a more-permanent copy that won't ever get destroyed.
-static string* g_pprof_path = new string(FLAGS_heap_profile_table_pprof);
-
//----------------------------------------------------------------------
// header of the dumped heap profile
@@ -521,86 +510,6 @@ void HeapProfileTable::Snapshot::ReportCallback(const void* ptr,
e->bytes += v->bytes;
}
-// It would be much more efficient to call Symbolize on a bunch of pc's
-// at once, rather than calling one at a time, but this way it's simpler
-// to code, and efficiency probably isn't a top concern when reporting
-// found leaks at program-exit time.
-// Note that the forking/etc is not thread-safe or re-entrant. That's
-// ok for the purpose we need -- reporting leaks detected by heap-checker
-// -- but be careful if you decide to use this routine for other purposes.
-static bool Symbolize(void *pc, char *out, int out_size) {
-#if !defined(HAVE_UNISTD_H) || !defined(HAVE_SYS_SOCKET_H) || !defined(HAVE_SYS_WAIT_H)
- return false;
-#elif !defined(HAVE_PROGRAM_INVOCATION_NAME)
- return false; // TODO(csilvers): get argv[0] somehow
-#else
- // All this work is to do two-way communication. ugh.
- extern char* program_invocation_name; // gcc provides this
- int child_in[2]; // file descriptors
- int child_out[2]; // for now, we don't worry about child_err
- if (socketpair(AF_UNIX, SOCK_STREAM, 0, child_in) == -1) {
- return false;
- }
- if (socketpair(AF_UNIX, SOCK_STREAM, 0, child_out) == -1) {
- close(child_in[0]);
- close(child_in[1]);
- return false;
- }
- switch (fork()) {
- case -1: { // error
- close(child_in[0]);
- close(child_in[1]);
- close(child_out[0]);
- close(child_out[1]);
- return false;
- }
- case 0: { // child
- close(child_in[1]); // child uses the 0's, parent uses the 1's
- close(child_out[1]); // child uses the 0's, parent uses the 1's
- close(0);
- close(1);
- if (dup2(child_in[0], 0) == -1) _exit(1);
- if (dup2(child_out[0], 1) == -1) _exit(2);
- execlp(g_pprof_path->c_str(), g_pprof_path->c_str(),
- "--symbols", program_invocation_name, NULL);
- _exit(3); // if execvp fails, it's bad news for us
- }
- default: { // parent
- close(child_in[0]); // child uses the 0's, parent uses the 1's
- close(child_out[0]); // child uses the 0's, parent uses the 1's
- DumpProcSelfMaps(child_in[1]); // what pprof expects on stdin
- char pcstr[64]; // enough for a single address
- snprintf(pcstr, sizeof(pcstr), // pprof expects format to be 0xXXXXXX...
- "0x%" PRIxPTR "\n", reinterpret_cast<uintptr_t>(pc));
- write(child_in[1], pcstr, strlen(pcstr));
- close(child_in[1]); // that's all we need to write
- int total_bytes_read = 0;
- while (1) {
- int bytes_read = read(child_out[1], out + total_bytes_read,
- out_size - total_bytes_read);
- if (bytes_read < 0) {
- close(child_out[1]);
- return false;
- } else if (bytes_read == 0) {
- close(child_out[1]);
- wait(NULL);
- break;
- } else {
- total_bytes_read += bytes_read;
- }
- }
- // We have successfully read the output of pprof into out. Make sure
- // we got the full symbol (we can tell because it ends with a \n).
- if (total_bytes_read == 0 || out[total_bytes_read - 1] != '\n')
- return false;
- out[total_bytes_read - 1] = '\0'; // remove the trailing newline
- return true;
- }
- }
- return false; // shouldn't be reachable
-#endif
-}
-
void HeapProfileTable::Snapshot::ReportLeaks(const char* checker_name,
const char* filename,
bool should_symbolize) {
diff --git a/src/heap-profiler.cc b/src/heap-profiler.cc
index 9ab5d0c..a1c643a 100644
--- a/src/heap-profiler.cc
+++ b/src/heap-profiler.cc
@@ -227,9 +227,9 @@ static char* DoGetHeapProfileLocked(char* buf, int buflen) {
extern "C" char* GetHeapProfile() {
// Use normal malloc: we return the profile to the user to free it:
+ char* buffer = reinterpret_cast<char*>(malloc(kProfileBufferSize));
SpinLockHolder l(&heap_lock);
- return DoGetHeapProfileLocked(
- reinterpret_cast<char*>(malloc(kProfileBufferSize)), kProfileBufferSize);
+ return DoGetHeapProfileLocked(buffer, kProfileBufferSize);
}
// defined below
diff --git a/src/malloc_extension.cc b/src/malloc_extension.cc
index 109c8b1..b156972 100644
--- a/src/malloc_extension.cc
+++ b/src/malloc_extension.cc
@@ -45,6 +45,9 @@
#include <string>
#include "base/dynamic_annotations.h"
#include "base/sysinfo.h" // for FillProcSelfMaps
+#ifndef NO_HEAP_CHECK
+#include "google/heap-checker.h"
+#endif
#include "google/malloc_extension.h"
#include "maybe_threads.h"
@@ -136,6 +139,10 @@ void MallocExtension::MarkThreadIdle() {
// Default implementation does nothing
}
+void MallocExtension::MarkThreadBusy() {
+ // Default implementation does nothing
+}
+
void MallocExtension::ReleaseFreeMemory() {
// Default implementation does nothing
}
@@ -156,17 +163,16 @@ size_t MallocExtension::GetAllocatedSize(void* p) {
return 0;
}
-// The current malloc extension object. We also keep a pointer to
-// the default implementation so that the heap-leak checker does not
-// complain about a memory leak.
+// The current malloc extension object.
static pthread_once_t module_init = PTHREAD_ONCE_INIT;
-static MallocExtension* default_instance = NULL;
static MallocExtension* current_instance = NULL;
static void InitModule() {
- default_instance = new MallocExtension;
- current_instance = default_instance;
+ current_instance = new MallocExtension;
+#ifndef NO_HEAP_CHECK
+ HeapLeakChecker::IgnoreObject(current_instance);
+#endif
}
MallocExtension* MallocExtension::instance() {
@@ -317,6 +323,7 @@ C_SHIM(SetNumericProperty, bool,
(const char* property, size_t value), (property, value));
C_SHIM(MarkThreadIdle, void, (), ());
+C_SHIM(MarkThreadBusy, void, (), ());
C_SHIM(ReleaseFreeMemory, void, (), ());
C_SHIM(GetEstimatedAllocatedSize, size_t, (size_t size), (size));
C_SHIM(GetAllocatedSize, size_t, (void* p), (p));
diff --git a/src/malloc_hook.cc b/src/malloc_hook.cc
index 0e2ae98..d1ad12a 100644
--- a/src/malloc_hook.cc
+++ b/src/malloc_hook.cc
@@ -433,6 +433,10 @@ static inline void* do_mmap64(void *start, size_t length,
// Put all callers of MallocHook::Invoke* in this module into
// malloc_hook section,
// so that MallocHook::GetCallerStackTrace can function accurately:
+
+// Make sure mmap doesn't get #define'd away by <sys/mman.h>
+#undef mmap
+
extern "C" {
void* mmap64(void *start, size_t length, int prot, int flags,
int fd, __off64_t offset ) __THROW
@@ -457,6 +461,8 @@ extern "C" void* mmap64(void *start, size_t length, int prot, int flags,
return result;
}
+#if !defined(__USE_FILE_OFFSET64) || !defined(__REDIRECT_NTH)
+
extern "C" void* mmap(void *start, size_t length, int prot, int flags,
int fd, off_t offset) __THROW {
MallocHook::InvokePreMmapHook(start, length, prot, flags, fd, offset);
@@ -466,6 +472,8 @@ extern "C" void* mmap(void *start, size_t length, int prot, int flags,
return result;
}
+#endif
+
extern "C" int munmap(void* start, size_t length) __THROW {
MallocHook::InvokeMunmapHook(start, length);
return syscall(SYS_munmap, start, length);
diff --git a/src/memfs_malloc.cc b/src/memfs_malloc.cc
index f7fd8e9..bef2d3c 100644
--- a/src/memfs_malloc.cc
+++ b/src/memfs_malloc.cc
@@ -50,9 +50,9 @@
#include "base/basictypes.h"
#include "base/googleinit.h"
-#include "base/logging.h"
#include "base/sysinfo.h"
#include "system-alloc.h"
+#include "internal_logging.h"
using std::string;
@@ -60,8 +60,17 @@ DEFINE_string(memfs_malloc_path, EnvToString("TCMALLOC_MEMFS_MALLOC_PATH", ""),
"Path where hugetlbfs or tmpfs is mounted. The caller is "
"responsible for ensuring that the path is unique and does "
"not conflict with another process");
-DEFINE_int64(memfs_malloc_limit_mb, 0, "Limit total allocation size to the "
+DEFINE_int64(memfs_malloc_limit_mb,
+ EnvToInt("TCMALLOC_MEMFS_LIMIT_MB", 0),
+ "Limit total allocation size to the "
"specified number of MiB. 0 == no limit.");
+DEFINE_bool(memfs_malloc_abort_on_fail,
+ EnvToBool("TCMALLOC_MEMFS_ABORT_ON_FAIL", false),
+ "abort() whenever memfs_malloc fails to satisfy an allocation "
+ "for any reason.");
+DEFINE_bool(memfs_malloc_ignore_mmap_fail,
+ EnvToBool("TCMALLOC_MEMFS_IGNORE_MMAP_FAIL", false),
+ "Ignore failures from mmap");
// Hugetlbfs based allocator for tcmalloc
class HugetlbSysAllocator: public SysAllocator {
@@ -117,8 +126,17 @@ void* HugetlbSysAllocator::Alloc(size_t size, size_t *actual_size,
if (limit > 0 && hugetlb_base_ + size + extra > limit) {
// Disable the allocator when there's less than one page left.
if (limit - hugetlb_base_ < big_page_size_) {
+ TCMalloc_MESSAGE(__FILE__, __LINE__, "reached memfs_malloc_limit_mb\n");
failed_ = true;
}
+ else {
+ TCMalloc_MESSAGE(__FILE__, __LINE__, "alloc size=%"PRIuS
+ " too large while %"PRId64" bytes remain\n",
+ size, static_cast<int64_t>(limit - hugetlb_base_));
+ }
+ if (FLAGS_memfs_malloc_abort_on_fail) {
+ CRASH("memfs_malloc_abort_on_fail is set\n");
+ }
return NULL;
}
@@ -126,7 +144,12 @@ void* HugetlbSysAllocator::Alloc(size_t size, size_t *actual_size,
// hugetlbfs returns EINVAL for ftruncate.
int ret = ftruncate(hugetlb_fd_, hugetlb_base_ + size + extra);
if (ret != 0 && errno != EINVAL) {
+ TCMalloc_MESSAGE(__FILE__, __LINE__, "ftruncate failed: %s\n",
+ strerror(errno));
failed_ = true;
+ if (FLAGS_memfs_malloc_abort_on_fail) {
+ CRASH("memfs_malloc_abort_on_fail is set\n");
+ }
return NULL;
}
@@ -137,7 +160,14 @@ void* HugetlbSysAllocator::Alloc(size_t size, size_t *actual_size,
void *result = mmap(0, size + extra, PROT_WRITE|PROT_READ,
MAP_SHARED, hugetlb_fd_, hugetlb_base_);
if (result == reinterpret_cast<void*>(MAP_FAILED)) {
- failed_ = true;
+ if (!FLAGS_memfs_malloc_ignore_mmap_fail) {
+ TCMalloc_MESSAGE(__FILE__, __LINE__, "mmap failed: %s\n",
+ strerror(errno));
+ failed_ = true;
+ if (FLAGS_memfs_malloc_abort_on_fail) {
+ CRASH("memfs_malloc_abort_on_fail is set\n");
+ }
+ }
return NULL;
}
uintptr_t ptr = reinterpret_cast<uintptr_t>(result);
@@ -159,27 +189,33 @@ void* HugetlbSysAllocator::Alloc(size_t size, size_t *actual_size,
static void InitSystemAllocator() {
if (FLAGS_memfs_malloc_path.length()) {
- // Don't rely on the caller to ensure unique path name
- char pid[64]; // pids are smaller than this!
- int n = snprintf(pid, sizeof(pid), "%u", (unsigned int)(getpid()));
- CHECK(n < sizeof(pid));
- string hugetlbfs_path = FLAGS_memfs_malloc_path
- + "." + pid;
-
- int hugetlb_fd = open(hugetlbfs_path.c_str(), O_RDWR | O_CREAT | O_EXCL,
- 0600);
+ char path[PATH_MAX];
+ int rc = snprintf(path, sizeof(path), "%s.XXXXXX",
+ FLAGS_memfs_malloc_path.c_str());
+ if (rc < 0 || rc >= sizeof(path)) {
+ CRASH("XX fatal: memfs_malloc_path too long\n");
+ }
+
+ int hugetlb_fd = mkstemp(path);
if (hugetlb_fd == -1) {
- RAW_LOG(WARNING, "unable to create memfs_malloc_path file %s: %s",
- hugetlbfs_path.c_str(), strerror(errno));
+ TCMalloc_MESSAGE(__FILE__, __LINE__,
+ "warning: unable to create memfs_malloc_path %s: %s\n",
+ path, strerror(errno));
return;
}
// Cleanup memory on process exit
- CHECK_ERR(unlink(hugetlbfs_path.c_str()));
+ if (unlink(path) == -1) {
+ CRASH("fatal: error unlinking memfs_malloc_path %s: %s\n",
+ path, strerror(errno));
+ }
// Use fstatfs to figure out the default page size for memfs
struct statfs sfs;
- CHECK_ERR(fstatfs(hugetlb_fd, &sfs));
+ if (fstatfs(hugetlb_fd, &sfs) == -1) {
+ CRASH("fatal: error fstatfs of memfs_malloc_path: %s\n",
+ strerror(errno));
+ }
int64 page_size = sfs.f_bsize;
SysAllocator *alloc = new HugetlbSysAllocator(hugetlb_fd, page_size);
diff --git a/src/memory_region_map.cc b/src/memory_region_map.cc
index 8782756..17896fd 100644
--- a/src/memory_region_map.cc
+++ b/src/memory_region_map.cc
@@ -402,7 +402,7 @@ static int saved_regions_count = 0;
// be caused by a InsertRegionLocked call).
// Region has no constructor, so that c-tor execution does not interfere
// with the any-time use of the static memory behind saved_regions.
-static MemoryRegionMap::Region saved_regions[10];
+static MemoryRegionMap::Region saved_regions[20];
inline void MemoryRegionMap::HandleSavedRegionsLocked(
void (*insert_func)(const Region& region)) {
@@ -486,10 +486,38 @@ void MemoryRegionMap::RecordRegionRemoval(const void* start, size_t size) {
Lock();
if (regions_ == NULL) { // We must have just unset the hooks,
// but this thread was already inside the hook.
+ if (recursive_insert) {
+ // First remove the removed region from saved_regions, if it's
+ // there, to prevent overrunning saved_regions in recursive
+ // map/unmap call sequences.
+ uintptr_t start_addr = reinterpret_cast<uintptr_t>(start);
+ uintptr_t end_addr = start_addr + size;
+ int put_pos = 0;
+ int old_count = saved_regions_count;
+ for (int i = 0; i < old_count; ++i, ++put_pos) {
+ Region& r = saved_regions[i];
+ if (r.start_addr == start_addr && r.end_addr == end_addr) {
+ // An exact match, so it's safe to remove.
+ --saved_regions_count;
+ --put_pos;
+ RAW_VLOG(2, ("Insta-Removing saved region %p..%p; "
+ "now have %d saved regions"),
+ reinterpret_cast<void*>(start_addr),
+ reinterpret_cast<void*>(end_addr),
+ saved_regions_count);
+ } else {
+ if (put_pos < i) {
+ saved_regions[put_pos] = saved_regions[i];
+ }
+ }
+ }
+ }
Unlock();
return;
}
- HandleSavedRegionsLocked(&InsertRegionLocked);
+ if (!recursive_insert) {
+ HandleSavedRegionsLocked(&InsertRegionLocked);
+ }
// first handle adding saved regions if any
uintptr_t start_addr = reinterpret_cast<uintptr_t>(start);
uintptr_t end_addr = start_addr + size;
diff --git a/src/packed-cache-inl.h b/src/packed-cache-inl.h
index 32d92fa..77d6313 100644
--- a/src/packed-cache-inl.h
+++ b/src/packed-cache-inl.h
@@ -112,7 +112,7 @@
#define TCMALLOC_PACKED_CACHE_INL_H_
#include "base/basictypes.h" // for COMPILE_ASSERT
-#include "base/logging.h" // for DCHECK
+#include "internal_logging.h"
// A safe way of doing "(1 << n) - 1" -- without worrying about overflow
// Note this will all be resolved to a constant expression at compile-time
@@ -144,13 +144,13 @@ class PackedCache {
}
void Put(K key, V value) {
- DCHECK_EQ(key, key & kKeyMask);
- DCHECK_EQ(value, value & kValueMask);
+ ASSERT(key == (key & kKeyMask));
+ ASSERT(value == (value & kValueMask));
array_[Hash(key)] = KeyToUpper(key) | value;
}
bool Has(K key) const {
- DCHECK_EQ(key, key & kKeyMask);
+ ASSERT(key == (key & kKeyMask));
return KeyMatch(array_[Hash(key)], key);
}
@@ -159,15 +159,15 @@ class PackedCache {
// as we can. Assuming entries are read atomically (e.g., their
// type is uintptr_t on most hardware) then certain races are
// harmless.
- DCHECK_EQ(key, key & kKeyMask);
+ ASSERT(key == (key & kKeyMask));
T entry = array_[Hash(key)];
return KeyMatch(entry, key) ? EntryToValue(entry) : default_value;
}
void Clear(V value) {
- DCHECK_EQ(value, value & kValueMask);
+ ASSERT(value == (value & kValueMask));
for (int i = 0; i < 1 << kHashbits; i++) {
- RAW_DCHECK(kUseWholeKeys || KeyToUpper(i) == 0, "KeyToUpper failure");
+ ASSERT(kUseWholeKeys || KeyToUpper(i) == 0);
array_[i] = kUseWholeKeys ? (value | KeyToUpper(i)) : value;
}
}
diff --git a/src/page_heap.h b/src/page_heap.h
index f766ec7..edca506 100644
--- a/src/page_heap.h
+++ b/src/page_heap.h
@@ -110,7 +110,8 @@ class PageHeap {
// REQUIRES: span->sizeclass == 0
Span* Split(Span* span, Length n);
- // Return the descriptor for the specified page.
+ // Return the descriptor for the specified page. Returns NULL if
+ // this PageID was not allocated previously.
inline Span* GetDescriptor(PageID p) const {
return reinterpret_cast<Span*>(pagemap_.get(p));
}
diff --git a/src/pagemap.h b/src/pagemap.h
index 6393ffc..3559932 100644
--- a/src/pagemap.h
+++ b/src/pagemap.h
@@ -83,12 +83,12 @@ class TCMalloc_PageMap1 {
void PreallocateMoreMemory() {}
- // REQUIRES "k" is in range "[0,2^BITS-1]".
- // REQUIRES "k" has been ensured before.
- //
- // Return the current value for KEY. Returns "Value()" if not
- // yet set.
+ // Return the current value for KEY. Returns NULL if not yet set,
+ // or if k is out of range.
void* get(Number k) const {
+ if ((k >> BITS) > 0) {
+ return NULL;
+ }
return array_[k];
}
@@ -129,9 +129,11 @@ class TCMalloc_PageMap2 {
}
void* get(Number k) const {
- ASSERT(k >> BITS == 0);
const Number i1 = k >> LEAF_BITS;
const Number i2 = k & (LEAF_LENGTH-1);
+ if ((k >> BITS) > 0 || root_[i1] == NULL) {
+ return NULL;
+ }
return root_[i1]->values[i2];
}
@@ -212,10 +214,13 @@ class TCMalloc_PageMap3 {
}
void* get(Number k) const {
- ASSERT(k >> BITS == 0);
const Number i1 = k >> (LEAF_BITS + INTERIOR_BITS);
const Number i2 = (k >> LEAF_BITS) & (INTERIOR_LENGTH-1);
const Number i3 = k & (LEAF_LENGTH-1);
+ if ((k >> BITS) > 0 ||
+ root_->ptrs[i1] == NULL || root_->ptrs[i1]->ptrs[i2] == NULL) {
+ return NULL;
+ }
return reinterpret_cast<Leaf*>(root_->ptrs[i1]->ptrs[i2])->values[i3];
}
diff --git a/src/pprof b/src/pprof
index 9d4d0e8..bdbeebe 100755
--- a/src/pprof
+++ b/src/pprof
@@ -72,7 +72,7 @@ use strict;
use warnings;
use Getopt::Long;
-my $PPROF_VERSION = "1.3";
+my $PPROF_VERSION = "1.4";
# These are the object tools we use which can come from a
# user-specified location using --tools, from the PPROF_TOOLS
@@ -104,6 +104,8 @@ my $FILTEREDPROFILE_PAGE = "/pprof/filteredprofile(?:\\?.*)?";
my $SYMBOL_PAGE = "/pprof/symbol"; # must support symbol lookup via POST
my $PROGRAM_NAME_PAGE = "/pprof/cmdline";
+# default binary name
+my $UNKNOWN_BINARY = "(unknown)";
# There is a pervasive dependency on the length (in hex characters,
# i.e., nibbles) of an address, distinguishing between 32-bit and
@@ -120,6 +122,10 @@ sub usage_string {
Usage:
pprof [options] <program> <profiles>
<profiles> is a space separated list of profile names.
+pprof [options] <symbolized-profiles>
+ <symbolized-profiles> is a list of profile files where each file contains
+ the necessary symbol mappings as well as profile data (likely generated
+ with --raw).
pprof [options] <profile>
<profile> is a remote form. Symbols are obtained from host:port$SYMBOL_PAGE
@@ -167,6 +173,7 @@ Output type:
--ps Generate Postcript to stdout
--pdf Generate PDF to stdout
--gif Generate GIF to stdout
+ --raw Generate symbolized pprof data (useful with remote fetch)
Heap-Profile Options:
--inuse_space Display in-use (mega)bytes [default]
@@ -219,6 +226,10 @@ pprof --disasm=getdir /bin/ls ls.prof
(Per-PC) annotated disassembly for getdir()
pprof --text localhost:1234
Outputs one line per procedure for localhost:1234
+pprof --raw localhost:1234 > ./local.raw
+pprof --text ./local.raw
+ Fetches a remote profile for later analysis and then
+ analyzes it in text mode.
EOF
}
@@ -276,6 +287,7 @@ sub Init() {
$main::opt_ps = 0;
$main::opt_pdf = 0;
$main::opt_gif = 0;
+ $main::opt_raw = 0;
$main::opt_nodecount = 80;
$main::opt_nodefraction = 0.005;
@@ -303,6 +315,9 @@ sub Init() {
$main::opt_debug = 0;
$main::opt_test = 0;
+ # These are undocumented flags used only by unittests.
+ $main::opt_test_stride = 0;
+
# Are we using $SYMBOL_PAGE?
$main::use_symbol_page = 0;
@@ -335,6 +350,7 @@ sub Init() {
"ps!" => \$main::opt_ps,
"pdf!" => \$main::opt_pdf,
"gif!" => \$main::opt_gif,
+ "raw!" => \$main::opt_raw,
"interactive!" => \$main::opt_interactive,
"nodecount=i" => \$main::opt_nodecount,
"nodefraction=f" => \$main::opt_nodefraction,
@@ -355,6 +371,8 @@ sub Init() {
"tools=s" => \$main::opt_tools,
"test!" => \$main::opt_test,
"debug!" => \$main::opt_debug,
+ # Undocumented flags used only by unittests:
+ "test_stride=i" => \$main::opt_test_stride,
) || usage("Invalid option(s)");
# Deal with the standard --help and --version
@@ -410,6 +428,7 @@ sub Init() {
$main::opt_ps +
$main::opt_pdf +
$main::opt_gif +
+ $main::opt_raw +
$main::opt_interactive +
0;
if ($modes > 1) {
@@ -436,9 +455,13 @@ sub Init() {
# Remote profiling without a binary (using $SYMBOL_PAGE instead)
if (IsProfileURL($ARGV[0])) {
$main::use_symbol_page = 1;
+ } elsif (IsSymbolizedProfileFile($ARGV[0])) {
+ $main::use_symbolized_profile = 1;
+ $main::prog = $UNKNOWN_BINARY; # will be set later from the profile file
}
- if ($main::use_symbol_page) { # We don't need a binary!
+ if ($main::use_symbol_page || $main::use_symbolized_profile) {
+ # We don't need a binary!
my %disabled = ('--lines' => $main::opt_lines,
'--disasm' => $main::opt_disasm);
for my $option (keys %disabled) {
@@ -474,7 +497,7 @@ sub Init() {
}
CheckSymbolPage();
$main::prog = FetchProgramName();
- } else {
+ } elsif (!$main::use_symbolized_profile) { # may not need objtools!
ConfigureObjTools($main::prog)
}
@@ -502,12 +525,16 @@ sub Main() {
# Fetch all profile data
FetchDynamicProfiles();
-
+
+ # this will hold symbols that we read from the profile files
+ my $symbol_map = {};
+
# Read one profile, pick the last item on the list
my $data = ReadProfile($main::prog, pop(@main::profile_files));
my $profile = $data->{profile};
my $pcs = $data->{pcs};
my $libs = $data->{libs}; # Info about main program and shared libraries
+ $symbol_map = MergeSymbols($symbol_map, $data->{symbols});
# Add additional profiles, if available.
if (scalar(@main::profile_files) > 0) {
@@ -515,6 +542,7 @@ sub Main() {
my $data2 = ReadProfile($main::prog, $pname);
$profile = AddProfile($profile, $data2->{profile});
$pcs = AddPcs($pcs, $data2->{pcs});
+ $symbol_map = MergeSymbols($symbol_map, $data2->{symbols});
}
}
@@ -523,14 +551,17 @@ sub Main() {
my $base = ReadProfile($main::prog, $main::opt_base);
$profile = SubtractProfile($profile, $base->{profile});
$pcs = AddPcs($pcs, $base->{pcs});
+ $symbol_map = MergeSymbols($symbol_map, $base->{symbols});
}
# Get total data in profile
my $total = TotalProfile($profile);
# Collect symbols
- my $symbols = undef;
- if ($main::use_symbol_page) {
+ my $symbols;
+ if ($main::use_symbolized_profile) {
+ $symbols = FetchSymbols($pcs, $symbol_map);
+ } elsif ($main::use_symbol_page) {
$symbols = FetchSymbols($pcs);
} else {
$symbols = ExtractSymbols($libs, $pcs);
@@ -573,6 +604,8 @@ sub Main() {
printf("Total: %s %s\n", Unparse($total), Units());
}
PrintText($symbols, $flat, $cumulative, $total, -1);
+ } elsif ($main::opt_raw) {
+ PrintSymbolizedProfile($symbols, $profile, $main::prog);
} elsif ($main::opt_callgrind) {
PrintCallgrind($calls);
} else {
@@ -869,6 +902,73 @@ sub PsTempName {
return "$main::tmpfile_ps" . "." . "$fnum" . ".ps";
}
+# Print profile data in packed binary format (64-bit) to standard out
+sub PrintProfileData {
+ my $profile = shift;
+
+ # print header (64-bit style)
+ # (zero) (header-size) (version) (sample-period) (zero)
+ print pack('L*', 0, 0, 3, 0, 0, 0, 1, 0, 0, 0);
+
+ foreach my $k (keys(%{$profile})) {
+ my $count = $profile->{$k};
+ my @addrs = split(/\n/, $k);
+ if ($#addrs >= 0) {
+ my $depth = $#addrs + 1;
+ # int(foo / 2**32) is the only reliable way to get rid of bottom
+ # 32 bits on both 32- and 64-bit systems.
+ print pack('L*', $count & 0xFFFFFFFF, int($count / 2**32));
+ print pack('L*', $depth & 0xFFFFFFFF, int($depth / 2**32));
+
+ foreach my $full_addr (@addrs) {
+ my $addr = $full_addr;
+ $addr =~ s/0x0*//; # strip off leading 0x, zeroes
+ if (length($addr) > 16) {
+ print STDERR "Invalid address in profile: $full_addr\n";
+ next;
+ }
+ my $low_addr = substr($addr, -8); # get last 8 hex chars
+ my $high_addr = substr($addr, -16, 8); # get up to 8 more hex chars
+ print pack('L*', hex('0x' . $low_addr), hex('0x' . $high_addr));
+ }
+ }
+ }
+}
+
+# Print symbols and profile data
+sub PrintSymbolizedProfile {
+ my $symbols = shift;
+ my $profile = shift;
+ my $prog = shift;
+
+ $SYMBOL_PAGE =~ m,[^/]+$,; # matches everything after the last slash
+ my $symbol_marker = $&;
+
+ print '--- ', $symbol_marker, "\n";
+ if (defined($prog)) {
+ print 'binary=', $prog, "\n";
+ }
+ while (my ($pc, $name) = each(%{$symbols})) {
+ my $fullname = $name->[2];
+ print '0x', $pc, ' ', $fullname, "\n";
+ }
+ print '---', "\n";
+
+ if (defined($main::collected_profile)) {
+ # if used with remote fetch, simply dump the collected profile to output.
+ open(SRC, "<$main::collected_profile");
+ while (<SRC>) {
+ print $_;
+ }
+ } else {
+ # dump a cpu-format profile to standard out
+ $PROFILE_PAGE =~ m,[^/]+$,; # matches everything after the last slash
+ my $profile_marker = $&;
+ print '--- ', $profile_marker, "\n";
+ PrintProfileData($profile);
+ }
+}
+
# Print text output
sub PrintText {
my $symbols = shift;
@@ -882,7 +982,7 @@ sub PrintText {
my $running_sum = 0;
my $lines = 0;
- foreach my $k (sort { GetEntry($s,$b) <=> GetEntry($s, $a) }
+ foreach my $k (sort { GetEntry($s, $b) <=> GetEntry($s, $a) || $a cmp $b }
keys(%{$cumulative})) {
my $f = GetEntry($flat, $k);
my $c = GetEntry($cumulative, $k);
@@ -1396,7 +1496,8 @@ sub PrintDot {
# Find nodes to include
my @list = (sort { abs(GetEntry($cumulative, $b)) <=>
- abs(GetEntry($cumulative, $a)) }
+ abs(GetEntry($cumulative, $a))
+ || $a cmp $b }
keys(%{$cumulative}));
my $last = $nodecount - 1;
if ($last > $#list) {
@@ -1972,6 +2073,24 @@ sub AddProfile {
return $R;
}
+# Merges symbol maps
+sub MergeSymbols {
+ my $A = shift;
+ my $B = shift;
+
+ my $R = {};
+ foreach my $k (keys(%{$A})) {
+ $R->{$k} = $A->{$k};
+ }
+ if (defined($B)) {
+ foreach my $k (keys(%{$B})) {
+ $R->{$k} = $B->{$k};
+ }
+ }
+ return $R;
+}
+
+
# Add A to B
sub AddPcs {
my $A = shift;
@@ -2052,6 +2171,23 @@ sub AddEntries {
AddEntry($profile, (join "\n", @k), $count);
}
+sub IsSymbolizedProfileFile {
+ my $file_name = shift;
+
+ if (!(-e $file_name) || !(-r $file_name)) {
+ return 0;
+ }
+
+ $SYMBOL_PAGE =~ m,[^/]+$,; # matches everything after the last slash
+ my $symbol_marker = $&;
+ # Check if the file contains a symbol-section marker.
+ open(TFILE, "<$file_name");
+ my @lines = <TFILE>;
+ my $result = grep(/^--- *$symbol_marker/, @lines);
+ close(TFILE);
+ return $result > 0;
+}
+
##### Code to profile a server dynamically #####
sub CheckSymbolPage {
@@ -2130,35 +2266,72 @@ sub ResolveRedirectionForCurl {
return $url;
}
-# Fetch symbols from $SYMBOL_PAGE for all PC values found in profile
+# Reads a symbol map from the file handle name given as $1, returning
+# the resulting symbol map. Also processes variables relating to symbols.
+# Currently, the only variable processed is 'binary=<value>' which updates
+# $main::prog to have the correct program name.
+sub ReadSymbols {
+ my $in = shift;
+ my $map = {};
+ while (<$in>) {
+ s/\r//g; # turn windows-looking lines into unix-looking lines
+ # Removes all the leading zeroes from the symbols, see comment below.
+ if (m/^0x0*([0-9a-f]+)\s+(.+)/) {
+ $map->{$1} = $2;
+ } elsif (m/^---/) {
+ last;
+ } elsif (m/^([a-z][^=]*)=(.*)$/ ) {
+ my ($variable, $value) = ($1, $2);
+ for ($variable, $value) {
+ s/^\s+//;
+ s/\s+$//;
+ }
+ if ($variable eq "binary") {
+ if ($main::prog ne $UNKNOWN_BINARY && $main::prog ne $value) {
+ printf STDERR ("Warning: Mismatched binary name '%s', using '%s'.\n",
+ $main::prog, $value);
+ }
+ $main::prog = $value;
+ } else {
+ printf STDERR ("Ignoring unknown variable in symbols list: " .
+ "'%s' = '%s'\n", $variable, $value);
+ }
+ }
+ }
+ return $map;
+}
+
+# Fetches and processes symbols to prepare them for use in the profile output
+# code. If the optional 'symbol_map' arg is not given, fetches symbols from
+# $SYMBOL_PAGE for all PC values found in profile. Otherwise, the raw symbols
+# are assumed to have already been fetched into 'symbol_map' and are simply
+# extracted and processed.
sub FetchSymbols {
my $pcset = shift;
+ my $symbol_map = shift;
+
my %seen = ();
my @pcs = grep { !$seen{$_}++ } keys(%$pcset); # uniq
- my $post_data = join("+", sort((map {"0x" . "$_"} @pcs)));
- open(POSTFILE, ">$main::tmpfile_sym");
- print POSTFILE $post_data;
- close(POSTFILE);
- my $url = SymbolPageURL();
- # Here we use curl for sending data via POST since old
- # wget doesn't have --post-file option.
- $url = ResolveRedirectionForCurl($url);
- my $command_line = "$CURL -sd '\@$main::tmpfile_sym' '$url'";
- # We use c++filt in case $SYMBOL_PAGE gives us mangled symbols.
- my $cppfilt = $obj_tool_map{"c++filt"};
- open(SYMBOL, "$command_line | $cppfilt |") or error($command_line);
-
- my %map;
- while (<SYMBOL>) {
- s/\r//g; # turn windows-looking lines into unix-looking lines
- # Removes all the leading zeroes from the symbols, see comment below.
- if (m/^0x0*([0-9a-f]+)\s+(.+)/) {
- $map{$1} = $2;
- }
+ if (!defined($symbol_map)) {
+ my $post_data = join("+", sort((map {"0x" . "$_"} @pcs)));
+
+ open(POSTFILE, ">$main::tmpfile_sym");
+ print POSTFILE $post_data;
+ close(POSTFILE);
+
+ my $url = SymbolPageURL();
+ # Here we use curl for sending data via POST since old
+ # wget doesn't have --post-file option.
+ $url = ResolveRedirectionForCurl($url);
+ my $command_line = "$CURL -sd '\@$main::tmpfile_sym' '$url'";
+ # We use c++filt in case $SYMBOL_PAGE gives us mangled symbols.
+ my $cppfilt = $obj_tool_map{"c++filt"};
+ open(SYMBOL, "$command_line | $cppfilt |") or error($command_line);
+ $symbol_map = ReadSymbols(*SYMBOL{IO});
+ close(SYMBOL);
}
- close(SYMBOL);
my $symbols = {};
foreach my $pc (@pcs) {
@@ -2170,8 +2343,8 @@ sub FetchSymbols {
# /symbol, the symbols match and are retrievable from the map.
my $shortpc = $pc;
$shortpc =~ s/^0*//;
- if (defined($map{$shortpc})) {
- $fullname = $map{$shortpc};
+ if (defined($symbol_map->{$shortpc})) {
+ $fullname = $symbol_map->{$shortpc};
} else {
$fullname = "0x" . $pc; # Just use addresses
}
@@ -2316,6 +2489,60 @@ sub TryCollectProfile {
##### Parsing code #####
+# Provide a small streaming-read module to handle very large
+# cpu-profile files. Stream in chunks along a sliding window.
+BEGIN {
+ package CpuProfileStream;
+
+ sub new {
+ my ($class, $file) = @_;
+ my $self = { file => $file,
+ base => 0,
+ stride => 512 * 1024, # must be a multiple of |long|
+ slots => []
+ };
+ bless $self, $class;
+ # Let unittests adjust the stride
+ if ($main::opt_test_stride > 0) {
+ $self->{stride} = $main::opt_test_stride;
+ }
+ $self->overflow();
+ return $self;
+ }
+
+ # Load more data when we access slots->get(X) which is not yet in memory.
+ sub overflow {
+ my ($self) = @_;
+ my $slots = $self->{slots};
+ $self->{base} += $#$slots + 1; # skip over data we're replacing
+ my $str;
+ read($self->{file}, $str, $self->{stride});
+ @$slots = unpack("L*", $str);
+ }
+
+ # Access the i-th long in the file (logically), or -1 at EOF.
+ sub get {
+ my ($self, $idx) = @_;
+ my $slots = $self->{slots};
+ while ($#$slots >= 0) {
+ if ($idx < $self->{base}) {
+ # The only time we expect a reference to $slots[$i - something]
+ # after referencing $slots[$i] is reading the very first header.
+ # Since $stride > |header|, that shouldn't cause any lookback
+ # errors. And everything after the header is sequential.
+ print STDERR "Unexpected look-back reading CPU profile";
+ return -1; # shrug, don't know what better to return
+ } elsif ($idx > $self->{base} + $#$slots) {
+ $self->overflow();
+ } else {
+ return $slots->[$idx - $self->{base}];
+ }
+ }
+ # If we get here, $slots is [], which means we've reached EOF
+ return -1; # unique since slots is supposed to hold unsigned numbers
+ }
+}
+
# Parse profile generated by common/profiler.cc and return a reference
# to a map:
# $result->{version} Version number of profile file
@@ -2327,52 +2554,96 @@ sub ReadProfile {
my $prog = shift;
my $fname = shift;
+ if (IsSymbolizedProfileFile($fname) && !$main::use_symbolized_profile) {
+ # we have both a binary and symbolized profiles, abort
+ usage("Symbolized profile '$fname' cannot be used with a binary arg. " .
+ "Try again without passing '$prog'.");
+ }
+
$main::profile_type = '';
- # Look at first line to see if it is a heap or a CPU profile
- open(PROFILE, "<$fname") || error("$fname: $!\n");
- binmode PROFILE; # New perls do UTF-8 processing
- my $header = <PROFILE>;
- $header =~ s/\r//g; # turn windows-looking lines into unix-looking lines
$CONTENTION_PAGE =~ m,[^/]+$,; # matches everything after the last slash
my $contention_marker = $&;
- $GROWTH_PAGE =~ m,[^/]+$,;
+ $GROWTH_PAGE =~ m,[^/]+$,; # matches everything after the last slash
my $growth_marker = $&;
+ $SYMBOL_PAGE =~ m,[^/]+$,; # matches everything after the last slash
+ my $symbol_marker = $&;
+ $PROFILE_PAGE =~ m,[^/]+$,; # matches everything after the last slash
+ my $profile_marker = $&;
+
+ # Look at first line to see if it is a heap or a CPU profile.
+ # CPU profile may start with no header at all, and just binary data
+ # (starting with \0\0\0\0) -- in that case, don't try to read the
+ # whole firstline, since it may be gigabytes(!) of data.
+ open(PROFILE, "<$fname") || error("$fname: $!\n");
+ binmode PROFILE; # New perls do UTF-8 processing
+ my $firstchar = "";
+ my $header = "";
+ read(PROFILE, $firstchar, 1);
+ seek(PROFILE, -1, 1); # unread the firstchar
+ if ($firstchar ne "\0") {
+ $header = <PROFILE>;
+ $header =~ s/\r//g; # turn windows-looking lines into unix-looking lines
+ }
+
+ my $symbols;
+ if ($header =~ m/^--- *$symbol_marker/o) {
+ # read the symbol section of the symbolized profile file
+ $symbols = ReadSymbols(*PROFILE{IO});
+
+ # read the next line to get the header for the remaining profile
+ $header = "";
+ read(PROFILE, $firstchar, 1);
+ seek(PROFILE, -1, 1); # unread the firstchar
+ if ($firstchar ne "\0") {
+ $header = <PROFILE>;
+ $header =~ s/\r//g;
+ }
+ }
+
+ my $result;
+
if ($header =~ m/^heap profile:.*$growth_marker/o) {
$main::profile_type = 'growth';
- return ReadHeapProfile($prog, $fname, $header);
+ $result = ReadHeapProfile($prog, $fname, $header);
} elsif ($header =~ m/^heap profile:/) {
$main::profile_type = 'heap';
- return ReadHeapProfile($prog, $fname, $header);
+ $result = ReadHeapProfile($prog, $fname, $header);
} elsif ($header =~ m/^--- *$contention_marker/o) {
$main::profile_type = 'contention';
- return ReadSynchProfile($prog, $fname);
+ $result = ReadSynchProfile($prog, $fname);
} elsif ($header =~ m/^--- *Stacks:/) {
print STDERR
"Old format contention profile: mistakenly reports " .
"condition variable signals as lock contentions.\n";
$main::profile_type = 'contention';
- return ReadSynchProfile($prog, $fname);
+ $result = ReadSynchProfile($prog, $fname);
+ } elsif ($header =~ m/^--- *$profile_marker/) {
+ # the binary cpu profile data starts immediately after this line
+ $main::profile_type = 'cpu';
+ $result = ReadCPUProfile($prog, $fname);
} else {
- # Need to unread the line we just read
+ if (defined($symbols)) {
+ # a symbolized profile contains a format we don't recognize, bail out
+ error("$fname: Cannot recognize profile section after symbols.\n");
+ }
+ # no ascii header present -- must be a CPU profile
$main::profile_type = 'cpu';
- close(PROFILE);
- open(PROFILE, "<$fname") || error("$fname: $!\n");
- binmode PROFILE; # New perls do UTF-8 processing
- return ReadCPUProfile($prog, $fname);
+ $result = ReadCPUProfile($prog, $fname);
+ }
+
+ # if we got symbols along with the profile, return those as well
+ if (defined($symbols)) {
+ $result->{symbols} = $symbols;
}
+
+ return $result;
}
# CPU profile reader
sub ReadCPUProfile {
my $prog = shift;
my $fname = shift;
-
- # Read entire profile into a string
- my $str;
- my $nbytes = read(PROFILE, $str, (stat PROFILE)[7]); # read entire file
- close(PROFILE);
-
my $version;
my $period;
my $i;
@@ -2383,8 +2654,7 @@ sub ReadCPUProfile {
# L! cannot be used because with a native 64-bit build, it will cause
# 1) a valid 64-bit profile to use the 32-bit codepath, and
# 2) a valid 32-bit profile to be unrecognized.
-
- my @slots = unpack("L*", $str);
+ my $slots = CpuProfileStream->new(*PROFILE);
# Read header. The current header version is a 5-element structure
# containing:
@@ -2402,21 +2672,21 @@ sub ReadCPUProfile {
# 32-bit: 0 3 0 100 0
# 64-bit: 0 0 3 0 0 0 100 0 0 0
#
- if ($#slots < 4 || $slots[0] != 0 ) {
+ if ($slots->get(0) != 0 ) {
error("$fname: not a profile file, or old format profile file\n");
}
- if ($slots[1] >= 3) {
+ if ($slots->get(1) >= 3) {
# Normal 32-bit header:
- $version = $slots[2];
- $period = $slots[3];
- $i = 2 + $slots[1];
+ $version = $slots->get(2);
+ $period = $slots->get(3);
+ $i = 2 + $slots->get(1);
$address_length = 8;
# Parse profile
- while ($i <= $#slots) {
- my $n = $slots[$i++];
- my $d = $slots[$i++];
- if ($slots[$i] == 0) {
+ while ($slots->get($i) != -1) {
+ my $n = $slots->get($i++);
+ my $d = $slots->get($i++);
+ if ($slots->get($i) == 0) {
# End of profile data marker
$i += $d;
last;
@@ -2425,7 +2695,7 @@ sub ReadCPUProfile {
# Make key out of the stack entries
my @k = ();
for (my $j = 0; $j < $d; $j++) {
- my $pc = sprintf("%08x", $slots[$i+$j]);
+ my $pc = sprintf("%08x", $slots->get($i+$j));
$pcs->{$pc} = 1;
push @k, $pc;
}
@@ -2437,28 +2707,31 @@ sub ReadCPUProfile {
# Normal 64-bit header: All entries are doubled in size. The first
# word (little-endian) should contain the real value, the second should
# be zero.
- } elsif ($#slots < 9 || $slots[1] != 0 || $slots[2] < 3 || $slots[3] != 0
- || $slots[5] != 0 || $slots[7] != 0) {
- error("$fname: not a profile file, or old format profile file\n");
+ } elsif ($slots->get(1) != 0 ||
+ $slots->get(2) < 3 ||
+ $slots->get(3) != 0 ||
+ $slots->get(5) != 0 ||
+ $slots->get(7) != 0) {
+ error("$fname: not a profile file, or old format profile file\n");
} else {
- $version = $slots[4];
- $period = $slots[6];
- $i = 4 + 2 * $slots[2];
+ $version = $slots->get(4);
+ $period = $slots->get(6);
+ $i = 4 + 2 * $slots->get(2);
$address_length = 16;
# Parse profile
- while ($i <= $#slots) {
- my $n = $slots[$i++];
- my $nhi = $slots[$i++];
+ while ($slots->get($i) != -1) {
+ my $n = $slots->get($i++);
+ my $nhi = $slots->get($i++);
# Huge counts may coerce to floating point, keeping scale, not precision
if ($nhi != 0) { $n += $nhi*(2**32); }
- my $d = $slots[$i++];
- if ($slots[$i++] != 0) {
+ my $d = $slots->get($i++);
+ if ($slots->get($i++) != 0) {
my $addr = sprintf("%o", 4 * $i);
print STDERR "At index $i ($addr):\n";
error("$fname: stack trace depth >= 2**32\n");
}
- if ($slots[$i] == 0 && $slots[$i+1] == 0) {
+ if ($slots->get($i) == 0 && $slots->get($i+1) == 0) {
# End of profile data marker
$i += 2 * $d;
last;
@@ -2467,8 +2740,11 @@ sub ReadCPUProfile {
# Make key out of the stack entries
my @k = ();
for (my $j = $d; $j--; ) {
- my $pclo = $slots[$i++];
- my $pchi = $slots[$i++];
+ my $pclo = $slots->get($i++);
+ my $pchi = $slots->get($i++);
+ if ($pclo == -1 || $pchi == -1) {
+ error("$fname: Unexpected EOF when reading stack of depth $d\n");
+ }
my $pc = sprintf("%08x%08x", $pchi, $pclo);
$pcs->{$pc} = 1;
push @k, $pc;
@@ -2478,7 +2754,10 @@ sub ReadCPUProfile {
}
# Parse map
- my $map = substr($str, $i * 4);
+ my $map = '';
+ seek(PROFILE, $i * 4, 0);
+ read(PROFILE, $map, (stat PROFILE)[7]);
+ close(PROFILE);
my $r = {};
$r->{version} = $version;
@@ -2730,7 +3009,7 @@ sub ReadSynchProfile {
s/^\s+//;
s/\s+$//;
}
- if($variable eq "cycles/second") {
+ if ($variable eq "cycles/second") {
$cyclespernanosec = $value / 1e9;
$seen_clockrate = 1;
} elsif ($variable eq "sampling period") {
@@ -2903,7 +3182,7 @@ sub ParseTextSectionHeaderFromOtool {
} elsif ($line =~ /segname (\w+)/) {
$segname = $1;
} elsif (!($cmd eq "LC_SEGMENT" &&
- $sectname eq "__text" &&
+ $sectname eq "__text" &&
$segname eq "__TEXT")) {
next;
} elsif ($line =~ /\baddr 0x([0-9a-fA-F]+)/) {
@@ -2935,7 +3214,7 @@ sub ParseTextSectionHeader {
# obj_tool_map("otool") is only defined if we're in a Mach-O environment
if (defined($obj_tool_map{"otool"})) {
my $r = ParseTextSectionHeaderFromOtool(@_);
- if (defined($r)){
+ if (defined($r)){
return $r;
}
}
diff --git a/src/profiler.cc b/src/profiler.cc
index c51c7b2..183a7c7 100644
--- a/src/profiler.cc
+++ b/src/profiler.cc
@@ -281,32 +281,33 @@ void CpuProfiler::prof_handler(int sig, siginfo_t*, void* signal_ucontext,
#if !(defined(__CYGWIN__) || defined(__CYGWIN32__))
-extern "C" void ProfilerRegisterThread() {
+extern "C" PERFTOOLS_DLL_DECL void ProfilerRegisterThread() {
ProfileHandlerRegisterThread();
}
-extern "C" void ProfilerFlush() {
+extern "C" PERFTOOLS_DLL_DECL void ProfilerFlush() {
CpuProfiler::instance_.FlushTable();
}
-extern "C" int ProfilingIsEnabledForAllThreads() {
+extern "C" PERFTOOLS_DLL_DECL int ProfilingIsEnabledForAllThreads() {
return CpuProfiler::instance_.Enabled();
}
-extern "C" int ProfilerStart(const char* fname) {
+extern "C" PERFTOOLS_DLL_DECL int ProfilerStart(const char* fname) {
return CpuProfiler::instance_.Start(fname, NULL);
}
-extern "C" int ProfilerStartWithOptions(const char *fname,
- const ProfilerOptions *options) {
+extern "C" PERFTOOLS_DLL_DECL int ProfilerStartWithOptions(
+ const char *fname, const ProfilerOptions *options) {
return CpuProfiler::instance_.Start(fname, options);
}
-extern "C" void ProfilerStop() {
+extern "C" PERFTOOLS_DLL_DECL void ProfilerStop() {
CpuProfiler::instance_.Stop();
}
-extern "C" void ProfilerGetCurrentState(ProfilerState* state) {
+extern "C" PERFTOOLS_DLL_DECL void ProfilerGetCurrentState(
+ ProfilerState* state) {
CpuProfiler::instance_.GetCurrentState(state);
}
@@ -332,5 +333,5 @@ extern "C" void ProfilerGetCurrentState(ProfilerState* state) {
#endif // OS_CYGWIN
// DEPRECATED routines
-extern "C" void ProfilerEnable() { }
-extern "C" void ProfilerDisable() { }
+extern "C" PERFTOOLS_DLL_DECL void ProfilerEnable() { }
+extern "C" PERFTOOLS_DLL_DECL void ProfilerDisable() { }
diff --git a/src/sampler.h b/src/sampler.h
index f39791d..fa9e554 100755
--- a/src/sampler.h
+++ b/src/sampler.h
@@ -159,8 +159,8 @@ inline uint64_t Sampler::NextRandom(uint64_t rnd) {
// Adapted from //util/math/fastmath.[h|cc] by Noam Shazeer
// This mimics the VeryFastLog2 code in those files
inline double Sampler::FastLog2(const double & d) {
- assert(d>0);
- assert(sizeof(d) == sizeof(uint64_t));
+ ASSERT(d>0);
+ COMPILE_ASSERT(sizeof(d) == sizeof(uint64_t), DoubleMustBe64Bits);
uint64_t x;
memcpy(&x, &d, sizeof(x)); // we depend on the compiler inlining this
const uint32_t x_high = x >> 32;
diff --git a/src/stacktrace_win32-inl.h b/src/stacktrace_win32-inl.h
index 26ae297..892cd7c 100644
--- a/src/stacktrace_win32-inl.h
+++ b/src/stacktrace_win32-inl.h
@@ -49,6 +49,7 @@
// This code is inspired by a patch from David Vitek:
// http://code.google.com/p/google-perftools/issues/detail?id=83
+#include "config.h"
#include <windows.h> // for GetProcAddress and GetModuleHandle
#include <assert.h>
@@ -64,7 +65,8 @@ static RtlCaptureStackBackTrace_Function* const RtlCaptureStackBackTrace_fn =
(RtlCaptureStackBackTrace_Function*)
GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlCaptureStackBackTrace");
-int GetStackTrace(void** result, int max_depth, int skip_count) {
+PERFTOOLS_DLL_DECL int GetStackTrace(void** result, int max_depth,
+ int skip_count) {
if (!RtlCaptureStackBackTrace_fn) {
// TODO(csilvers): should we log an error here?
return 0; // can't find a stacktrace with no function to call
@@ -73,10 +75,10 @@ int GetStackTrace(void** result, int max_depth, int skip_count) {
result, 0);
}
-int GetStackFrames(void** /* pcs */,
- int* /* sizes */,
- int /* max_depth */,
- int /* skip_count */) {
+PERFTOOLS_DLL_DECL int GetStackFrames(void** /* pcs */,
+ int* /* sizes */,
+ int /* max_depth */,
+ int /* skip_count */) {
assert(0 == "Not yet implemented");
return 0;
}
diff --git a/src/stacktrace_with_context.cc b/src/stacktrace_with_context.cc
index 02f837d..ed7bfe3 100644
--- a/src/stacktrace_with_context.cc
+++ b/src/stacktrace_with_context.cc
@@ -47,13 +47,13 @@
#include "base/basictypes.h"
#if !defined(STACKTRACE_SKIP_CONTEXT_ROUTINES)
-ATTRIBUTE_NOINLINE
+ATTRIBUTE_NOINLINE PERFTOOLS_DLL_DECL
int GetStackFramesWithContext(void** pcs, int* sizes, int max_depth,
int skip_count, const void * /* uc */) {
return GetStackFrames(pcs, sizes, max_depth, skip_count + 1);
}
-ATTRIBUTE_NOINLINE
+ATTRIBUTE_NOINLINE PERFTOOLS_DLL_DECL
int GetStackTraceWithContext(void** result, int max_depth,
int skip_count, const void * /* uc */) {
return GetStackTrace(result, max_depth, skip_count + 1);
diff --git a/src/stacktrace_x86-inl.h b/src/stacktrace_x86-inl.h
index 9f68a03..9888346 100644
--- a/src/stacktrace_x86-inl.h
+++ b/src/stacktrace_x86-inl.h
@@ -37,7 +37,7 @@
// GetStackFramesWithContext. If you update one, update them all.
//
// There is no easy way to avoid this, because inlining
-// iterferes with skip_count, and there is no portable
+// interferes with skip_count, and there is no portable
// way to turn inlining off, or force it always on.
#include "config.h"
@@ -265,7 +265,37 @@ int GetStackTraceWithContext(void** result,
int max_depth,
int skip_count,
const void *uc) {
- void **sp = reinterpret_cast<void**>(__builtin_frame_address(0));
+ void **sp;
+#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2) || __llvm__
+ // __builtin_frame_address(0) can return the wrong address on gcc-4.1.0-k8.
+ // It's always correct on llvm, and the techniques below aren't (in
+ // particular, llvm-gcc will make a copy of pcs, so it's not in sp[2]),
+ // so we also prefer __builtin_frame_address when running under llvm.
+ sp = reinterpret_cast<void**>(__builtin_frame_address(0));
+#elif defined(__i386__)
+ // Stack frame format:
+ // sp[0] pointer to previous frame
+ // sp[1] caller address
+ // sp[2] first argument
+ // ...
+ // NOTE: This will break under llvm, since result is a copy and not in sp[2]
+ sp = (void **)&result - 2;
+#elif defined(__x86_64__)
+ unsigned long rbp;
+ // Move the value of the register %rbp into the local variable rbp.
+ // We need 'volatile' to prevent this instruction from getting moved
+ // around during optimization to before function prologue is done.
+ // An alternative way to achieve this
+ // would be (before this __asm__ instruction) to call Noop() defined as
+ // static void Noop() __attribute__ ((noinline)); // prevent inlining
+ // static void Noop() { asm(""); } // prevent optimizing-away
+ __asm__ volatile ("mov %%rbp, %0" : "=r" (rbp));
+ // Arguments are passed in registers on x86-64, so we can't just
+ // offset from &result
+ sp = (void **) rbp;
+#else
+# error Using stacktrace_x86-inl.h on a non x86 architecture!
+#endif
int n = 0;
while (sp && n < max_depth) {
@@ -432,7 +462,37 @@ int GetStackFramesWithContext(void** pcs,
int max_depth,
int skip_count,
const void *uc) {
- void **sp = reinterpret_cast<void**>(__builtin_frame_address(0));
+ void **sp;
+#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2) || __llvm__
+ // __builtin_frame_address(0) can return the wrong address on gcc-4.1.0-k8.
+ // It's always correct on llvm, and the techniques below aren't (in
+ // particular, llvm-gcc will make a copy of pcs, so it's not in sp[2]),
+ // so we also prefer __builtin_frame_address when running under llvm.
+ sp = reinterpret_cast<void**>(__builtin_frame_address(0));
+#elif defined(__i386__)
+ // Stack frame format:
+ // sp[0] pointer to previous frame
+ // sp[1] caller address
+ // sp[2] first argument
+ // ...
+ // NOTE: This will break under llvm, since result is a copy and not in sp[2]
+ sp = (void **)&pcs - 2;
+#elif defined(__x86_64__)
+ unsigned long rbp;
+ // Move the value of the register %rbp into the local variable rbp.
+ // We need 'volatile' to prevent this instruction from getting moved
+ // around during optimization to before function prologue is done.
+ // An alternative way to achieve this
+ // would be (before this __asm__ instruction) to call Noop() defined as
+ // static void Noop() __attribute__ ((noinline)); // prevent inlining
+ // static void Noop() { asm(""); } // prevent optimizing-away
+ __asm__ volatile ("mov %%rbp, %0" : "=r" (rbp));
+ // Arguments are passed in registers on x86-64, so we can't just
+ // offset from &result
+ sp = (void **) rbp;
+#else
+# error Using stacktrace_x86-inl.h on a non x86 architecture!
+#endif
int n = 0;
while (sp && n < max_depth) {
diff --git a/src/symbolize.cc b/src/symbolize.cc
new file mode 100644
index 0000000..40ab5da
--- /dev/null
+++ b/src/symbolize.cc
@@ -0,0 +1,162 @@
+// Copyright (c) 2009, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ---
+// Author: Craig Silverstein
+//
+// This forks out to pprof to do the actual symbolizing. We might
+// be better off writing our own in C++.
+
+#include "config.h"
+#include "symbolize.h"
+#include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h> // for write()
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h> // for socketpair() -- needed by Symbolize
+#endif
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h> // for wait() -- needed by Symbolize
+#endif
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
+#include <string>
+#include "base/commandlineflags.h"
+#include "base/sysinfo.h"
+
+using std::string;
+using tcmalloc::DumpProcSelfMaps; // from sysinfo.h
+
+
+DEFINE_string(symbolize_pprof,
+ EnvToString("PPROF_PATH", "pprof"),
+ "Path to pprof to call for reporting function names.");
+
+// heap_profile_table_pprof may be referenced after destructors are
+// called (since that's when leak-checking is done), so we make
+// a more-permanent copy that won't ever get destroyed.
+static string* g_pprof_path = new string(FLAGS_symbolize_pprof);
+
+// It would be much more efficient to call Symbolize on a bunch of pc's
+// at once, rather than calling one at a time, but this way it's simpler
+// to code, and efficiency probably isn't a top concern when reporting
+// found leaks at program-exit time.
+// Note that the forking/etc is not thread-safe or re-entrant. That's
+// ok for the purpose we need -- reporting leaks detected by heap-checker
+// -- but be careful if you decide to use this routine for other purposes.
+extern "C" bool Symbolize(void *pc, char *out, int out_size) {
+#if !defined(HAVE_UNISTD_H) || !defined(HAVE_SYS_SOCKET_H) || !defined(HAVE_SYS_WAIT_H)
+ return false;
+#elif !defined(HAVE_PROGRAM_INVOCATION_NAME)
+ return false; // TODO(csilvers): get argv[0] somehow
+#else
+ // All this work is to do two-way communication. ugh.
+ extern char* program_invocation_name; // gcc provides this
+ int child_in[2]; // file descriptors
+ int child_out[2]; // for now, we don't worry about child_err
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, child_in) == -1) {
+ return false;
+ }
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, child_out) == -1) {
+ close(child_in[0]);
+ close(child_in[1]);
+ return false;
+ }
+ switch (fork()) {
+ case -1: { // error
+ close(child_in[0]);
+ close(child_in[1]);
+ close(child_out[0]);
+ close(child_out[1]);
+ return false;
+ }
+ case 0: { // child
+ close(child_in[1]); // child uses the 0's, parent uses the 1's
+ close(child_out[1]); // child uses the 0's, parent uses the 1's
+ close(0);
+ close(1);
+ if (dup2(child_in[0], 0) == -1) _exit(1);
+ if (dup2(child_out[0], 1) == -1) _exit(2);
+ // Unset vars that might cause trouble when we fork
+ unsetenv("CPUPROFILE");
+ unsetenv("HEAPPROFILE");
+ unsetenv("HEAPCHECK");
+ unsetenv("PERFTOOLS_VERBOSE");
+ execlp(g_pprof_path->c_str(), g_pprof_path->c_str(),
+ "--symbols", program_invocation_name, NULL);
+ _exit(3); // if execvp fails, it's bad news for us
+ }
+ default: { // parent
+ close(child_in[0]); // child uses the 0's, parent uses the 1's
+ close(child_out[0]); // child uses the 0's, parent uses the 1's
+#ifdef HAVE_POLL_H
+ // For maximum safety, we check to make sure the execlp
+ // succeeded before trying to write. (Otherwise we'll get a
+ // SIGPIPE.) For systems without poll.h, we'll just skip this
+ // check, and trust that the user set PPROF_PATH correctly!
+ struct pollfd pfd = { child_in[1], POLLOUT, 0 };
+ if (!poll(&pfd, 1, 0) || !(pfd.revents & POLLOUT) ||
+ (pfd.revents & (POLLHUP|POLLERR))) {
+ return false;
+ }
+#endif
+ DumpProcSelfMaps(child_in[1]); // what pprof expects on stdin
+ char pcstr[64]; // enough for a single address
+ snprintf(pcstr, sizeof(pcstr), // pprof expects format to be 0xXXXXXX...
+ "0x%" PRIxPTR "\n", reinterpret_cast<uintptr_t>(pc));
+ write(child_in[1], pcstr, strlen(pcstr));
+ close(child_in[1]); // that's all we need to write
+ int total_bytes_read = 0;
+ while (1) {
+ int bytes_read = read(child_out[1], out + total_bytes_read,
+ out_size - total_bytes_read);
+ if (bytes_read < 0) {
+ close(child_out[1]);
+ return false;
+ } else if (bytes_read == 0) {
+ close(child_out[1]);
+ wait(NULL);
+ break;
+ } else {
+ total_bytes_read += bytes_read;
+ }
+ }
+ // We have successfully read the output of pprof into out. Make sure
+ // we got the full symbol (we can tell because it ends with a \n).
+ if (total_bytes_read == 0 || out[total_bytes_read - 1] != '\n')
+ return false;
+ out[total_bytes_read - 1] = '\0'; // remove the trailing newline
+ return true;
+ }
+ }
+ return false; // shouldn't be reachable
+#endif
+}
diff --git a/src/symbolize.h b/src/symbolize.h
new file mode 100644
index 0000000..a7e3c7d
--- /dev/null
+++ b/src/symbolize.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2009, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ---
+// Author: Craig Silverstein
+
+#ifndef TCMALLOC_SYMBOLIZE_H_
+#define TCMALLOC_SYMBOLIZE_H_
+
+extern "C" bool Symbolize(void *pc, char *out, int out_size);
+
+#endif // TCMALLOC_SYMBOLIZE_H_
diff --git a/src/system-alloc.cc b/src/system-alloc.cc
index e4e313c..3341f17 100644
--- a/src/system-alloc.cc
+++ b/src/system-alloc.cc
@@ -150,6 +150,10 @@ bool RegisterSystemAllocator(SysAllocator *a, int priority) {
void* SbrkSysAllocator::Alloc(size_t size, size_t *actual_size,
size_t alignment) {
+#ifndef HAVE_SBRK
+ failed_ = true;
+ return NULL;
+#else
// Check if we should use sbrk allocation.
// FLAGS_malloc_skip_sbrk starts out as false (its uninitialized
// state) and eventually gets initialized to the specified value. Note
@@ -216,6 +220,7 @@ void* SbrkSysAllocator::Alloc(size_t size, size_t *actual_size,
ptr += alignment - (ptr & (alignment-1));
}
return reinterpret_cast<void*>(ptr);
+#endif // HAVE_SBRK
}
void SbrkSysAllocator::DumpStats(TCMalloc_Printer* printer) {
diff --git a/src/tcmalloc.cc b/src/tcmalloc.cc
index 13ff7b0..5d634fa 100644
--- a/src/tcmalloc.cc
+++ b/src/tcmalloc.cc
@@ -185,6 +185,7 @@ DEFINE_int64(tcmalloc_large_alloc_report_threshold,
// put all callers of MallocHook::Invoke* in this module into
// ATTRIBUTE_SECTION(google_malloc) section, so that
// MallocHook::GetCallerStackTrace can function accurately.
+#ifndef _WIN32 // windows doesn't have attribute_section, so don't bother
extern "C" {
void* tc_malloc(size_t size) __THROW
ATTRIBUTE_SECTION(google_malloc);
@@ -229,19 +230,21 @@ extern "C" {
ATTRIBUTE_SECTION(google_malloc);
void* tc_newarray_nothrow(size_t size, const std::nothrow_t&) __THROW
ATTRIBUTE_SECTION(google_malloc);
-}
+} // extern "C"
+#endif // #ifndef _WIN32
// Override the libc functions to prefer our own instead. This comes
// first so code in tcmalloc.cc can use the overridden versions. One
// exception: in windows, by default, we patch our code into these
// functions (via src/windows/patch_function.cc) rather than override
// them. In that case, we don't want to do this overriding here.
-#ifndef WIN32_DO_PATCHING
+#if !defined(WIN32_DO_PATCHING) && !defined(TCMALLOC_FOR_DEBUGALLOCATION)
#if defined(__GNUC__) && !defined(__MACH__)
// Potentially faster variants that use the gcc alias extension.
- // Mach-O (Darwin) does not support weak aliases, hence the __MACH__ check.
// FreeBSD does support aliases, but apparently not correctly. :-(
+ // NOTE: we make many of these symbols weak, but do so in the makefile
+ // (via objcopy -W) and not here. That ends up being more portable.
# define ALIAS(x) __attribute__ ((alias (x)))
void* operator new(size_t size) ALIAS("tc_new");
void operator delete(void* p) __THROW ALIAS("tc_delete");
@@ -267,26 +270,8 @@ extern "C" {
#ifdef HAVE_STRUCT_MALLINFO
struct mallinfo mallinfo(void) __THROW ALIAS("tc_mallinfo");
#endif
- // Some library routines on RedHat 9 allocate memory using malloc()
- // and free it using __libc_free() (or vice-versa). Since we provide
- // our own implementations of malloc/free, we need to make sure that
- // the __libc_XXX variants (defined as part of glibc) also point to
- // the same implementations.
-# if defined(__GLIBC__)
- void* __libc_malloc(size_t size) ALIAS("tc_malloc");
- void __libc_free(void* ptr) ALIAS("tc_free");
- void* __libc_realloc(void* ptr, size_t size) ALIAS("tc_realloc");
- void* __libc_calloc(size_t n, size_t size) ALIAS("tc_calloc");
- void __libc_cfree(void* ptr) ALIAS("tc_cfree");
- void* __libc_memalign(size_t align, size_t s) ALIAS("tc_memalign");
- void* __libc_valloc(size_t size) ALIAS("tc_valloc");
- void* __libc_pvalloc(size_t size) ALIAS("tc_pvalloc");
- int __posix_memalign(void** r, size_t a, size_t s) ALIAS("tc_posix_memalign");
-# define HAVE_ALIASED___LIBC 1
-# endif // #if defined(__GLIBC__)
} // extern "C"
-# undef ALIAS
-#else
+#else // #if defined(__GNUC__) && !defined(__MACH__)
// Portable wrappers
void* operator new(size_t size) { return tc_new(size); }
void operator delete(void* p) __THROW { tc_delete(p); }
@@ -315,11 +300,27 @@ extern "C" {
#ifdef HAVE_STRUCT_MALLINFO
struct mallinfo mallinfo(void) __THROW { return tc_mallinfo(); }
#endif
-} // extern C
+} // extern "C"
#endif // #if defined(__GNUC__)
-#ifndef HAVE_ALIASED___LIBC
+// Some library routines on RedHat 9 allocate memory using malloc()
+// and free it using __libc_free() (or vice-versa). Since we provide
+// our own implementations of malloc/free, we need to make sure that
+// the __libc_XXX variants (defined as part of glibc) also point to
+// the same implementations.
+#ifdef __GLIBC__ // only glibc defines __libc_*
extern "C" {
+#ifdef ALIAS
+ void* __libc_malloc(size_t size) ALIAS("tc_malloc");
+ void __libc_free(void* ptr) ALIAS("tc_free");
+ void* __libc_realloc(void* ptr, size_t size) ALIAS("tc_realloc");
+ void* __libc_calloc(size_t n, size_t size) ALIAS("tc_calloc");
+ void __libc_cfree(void* ptr) ALIAS("tc_cfree");
+ void* __libc_memalign(size_t align, size_t s) ALIAS("tc_memalign");
+ void* __libc_valloc(size_t size) ALIAS("tc_valloc");
+ void* __libc_pvalloc(size_t size) ALIAS("tc_pvalloc");
+ int __posix_memalign(void** r, size_t a, size_t s) ALIAS("tc_posix_memalign");
+#else // #ifdef ALIAS
void* __libc_malloc(size_t size) { return malloc(size); }
void __libc_free(void* ptr) { free(ptr); }
void* __libc_realloc(void* ptr, size_t size) { return realloc(ptr, size); }
@@ -331,17 +332,22 @@ extern "C" {
int __posix_memalign(void** r, size_t a, size_t s) {
return posix_memalign(r, a, s);
}
+#endif // #ifdef ALIAS
} // extern "C"
-#endif // #ifndef HAVE_ALIASED___LIBC
+#endif // ifdef __GLIBC__
+
+#undef ALIAS
-#endif // #ifndef WIN32_DO_PATCHING
+#endif // #ifndef(WIN32_DO_PATCHING) && ndef(TCMALLOC_FOR_DEBUGALLOCATION)
// ----------------------- IMPLEMENTATION -------------------------------
-// These routines are called by free(), realloc(), etc. if the pointer is
-// invalid. This is a cheap (source-editing required) kind of exception
-// handling for these routines.
+// Routines such as free() and realloc() catch some erroneous pointers
+// passed to them, and invoke the below when they do. (An erroneous pointer
+// won't be caught if it's within a valid span or a stale span for which
+// the pagemap cache has a non-zero sizeclass.) This is a cheap (source-editing
+// required) kind of exception handling for these routines.
namespace {
void InvalidFree(void* ptr) {
CRASH("Attempt to free invalid pointer: %p\n", ptr);
@@ -407,6 +413,8 @@ static void DumpStats(TCMalloc_Printer* out, int level) {
if (level >= 2) {
out->printf("------------------------------------------------\n");
+ out->printf("Size class breakdown\n");
+ out->printf("------------------------------------------------\n");
uint64_t cumulative = 0;
for (int cl = 0; cl < kNumClasses; ++cl) {
if (class_count[cl] > 0) {
@@ -605,6 +613,8 @@ class TCMallocImplementation : public MallocExtension {
ThreadCache::BecomeIdle();
}
+ virtual void MarkThreadBusy(); // Implemented below
+
virtual void ReleaseFreeMemory() {
SpinLockHolder h(Static::pageheap_lock());
Static::pageheap()->ReleaseFreePages();
@@ -1109,39 +1119,55 @@ size_t TCMallocImplementation::GetAllocatedSize(void* ptr) {
return GetSizeWithCallback(ptr, &InvalidGetAllocatedSize);
}
+void TCMallocImplementation::MarkThreadBusy() {
+ // Allocate to force the creation of a thread cache, but avoid
+ // invoking any hooks.
+ do_free(do_malloc(0));
+}
+
//-------------------------------------------------------------------
// Exported routines
//-------------------------------------------------------------------
+extern "C" PERFTOOLS_DLL_DECL const char* tc_version(
+ int* major, int* minor, const char** patch) __THROW {
+ if (major) *major = TC_VERSION_MAJOR;
+ if (minor) *minor = TC_VERSION_MINOR;
+ if (patch) *patch = TC_VERSION_PATCH;
+ return TC_VERSION_STRING;
+}
+
// CAVEAT: The code structure below ensures that MallocHook methods are always
// called from the stack frame of the invoked allocation function.
// heap-checker.cc depends on this to start a stack trace from
// the call to the (de)allocation function.
static int tc_new_mode = 0; // See tc_set_new_mode().
-extern "C" void* tc_malloc(size_t size) __THROW {
+extern "C" PERFTOOLS_DLL_DECL void* tc_malloc(size_t size) __THROW {
void* result = (tc_new_mode ? cpp_alloc(size, false) : do_malloc(size));
MallocHook::InvokeNewHook(result, size);
return result;
}
-extern "C" void tc_free(void* ptr) __THROW {
+extern "C" PERFTOOLS_DLL_DECL void tc_free(void* ptr) __THROW {
MallocHook::InvokeDeleteHook(ptr);
do_free(ptr);
}
-extern "C" void* tc_calloc(size_t n, size_t elem_size) __THROW {
+extern "C" PERFTOOLS_DLL_DECL void* tc_calloc(size_t n,
+ size_t elem_size) __THROW {
void* result = do_calloc(n, elem_size);
MallocHook::InvokeNewHook(result, n * elem_size);
return result;
}
-extern "C" void tc_cfree(void* ptr) __THROW {
+extern "C" PERFTOOLS_DLL_DECL void tc_cfree(void* ptr) __THROW {
MallocHook::InvokeDeleteHook(ptr);
do_free(ptr);
}
-extern "C" void* tc_realloc(void* old_ptr, size_t new_size) __THROW {
+extern "C" PERFTOOLS_DLL_DECL void* tc_realloc(void* old_ptr,
+ size_t new_size) __THROW {
if (old_ptr == NULL) {
void* result = do_malloc(new_size);
MallocHook::InvokeNewHook(result, new_size);
@@ -1155,7 +1181,7 @@ extern "C" void* tc_realloc(void* old_ptr, size_t new_size) __THROW {
return do_realloc(old_ptr, new_size);
}
-extern "C" void* tc_new(size_t size) {
+extern "C" PERFTOOLS_DLL_DECL void* tc_new(size_t size) {
void* p = cpp_alloc(size, false);
// We keep this next instruction out of cpp_alloc for a reason: when
// it's in, and new just calls cpp_alloc, the optimizer may fold the
@@ -1166,18 +1192,19 @@ extern "C" void* tc_new(size_t size) {
return p;
}
-extern "C" void* tc_new_nothrow(size_t size, const std::nothrow_t&) __THROW {
+extern "C" PERFTOOLS_DLL_DECL void* tc_new_nothrow(
+ size_t size, const std::nothrow_t&) __THROW {
void* p = cpp_alloc(size, true);
MallocHook::InvokeNewHook(p, size);
return p;
}
-extern "C" void tc_delete(void* p) __THROW {
+extern "C" PERFTOOLS_DLL_DECL void tc_delete(void* p) __THROW {
MallocHook::InvokeDeleteHook(p);
do_free(p);
}
-extern "C" void* tc_newarray(size_t size) {
+extern "C" PERFTOOLS_DLL_DECL void* tc_newarray(size_t size) {
void* p = cpp_alloc(size, false);
// We keep this next instruction out of cpp_alloc for a reason: when
// it's in, and new just calls cpp_alloc, the optimizer may fold the
@@ -1188,25 +1215,27 @@ extern "C" void* tc_newarray(size_t size) {
return p;
}
-extern "C" void* tc_newarray_nothrow(size_t size, const std::nothrow_t&) __THROW {
+extern "C" PERFTOOLS_DLL_DECL void* tc_newarray_nothrow(
+ size_t size, const std::nothrow_t&) __THROW {
void* p = cpp_alloc(size, true);
MallocHook::InvokeNewHook(p, size);
return p;
}
-extern "C" void tc_deletearray(void* p) __THROW {
+extern "C" PERFTOOLS_DLL_DECL void tc_deletearray(void* p) __THROW {
MallocHook::InvokeDeleteHook(p);
do_free(p);
}
-extern "C" void* tc_memalign(size_t align, size_t size) __THROW {
+extern "C" PERFTOOLS_DLL_DECL void* tc_memalign(size_t align,
+ size_t size) __THROW {
void* result = do_memalign(align, size);
MallocHook::InvokeNewHook(result, size);
return result;
}
-extern "C" int tc_posix_memalign(void** result_ptr, size_t align, size_t size)
- __THROW {
+extern "C" PERFTOOLS_DLL_DECL int tc_posix_memalign(
+ void** result_ptr, size_t align, size_t size) __THROW {
if (((align % sizeof(void*)) != 0) ||
((align & (align - 1)) != 0) ||
(align == 0)) {
@@ -1225,7 +1254,7 @@ extern "C" int tc_posix_memalign(void** result_ptr, size_t align, size_t size)
static size_t pagesize = 0;
-extern "C" void* tc_valloc(size_t size) __THROW {
+extern "C" PERFTOOLS_DLL_DECL void* tc_valloc(size_t size) __THROW {
// Allocate page-aligned object of length >= size bytes
if (pagesize == 0) pagesize = getpagesize();
void* result = do_memalign(pagesize, size);
@@ -1233,25 +1262,28 @@ extern "C" void* tc_valloc(size_t size) __THROW {
return result;
}
-extern "C" void* tc_pvalloc(size_t size) __THROW {
+extern "C" PERFTOOLS_DLL_DECL void* tc_pvalloc(size_t size) __THROW {
// Round up size to a multiple of pagesize
if (pagesize == 0) pagesize = getpagesize();
+ if (size == 0) { // pvalloc(0) should allocate one page, according to
+ size = pagesize; // http://man.free4web.biz/man3/libmpatrol.3.html
+ }
size = (size + pagesize - 1) & ~(pagesize - 1);
void* result = do_memalign(pagesize, size);
MallocHook::InvokeNewHook(result, size);
return result;
}
-extern "C" void tc_malloc_stats(void) __THROW {
+extern "C" PERFTOOLS_DLL_DECL void tc_malloc_stats(void) __THROW {
do_malloc_stats();
}
-extern "C" int tc_mallopt(int cmd, int value) __THROW {
+extern "C" PERFTOOLS_DLL_DECL int tc_mallopt(int cmd, int value) __THROW {
return do_mallopt(cmd, value);
}
#ifdef HAVE_STRUCT_MALLINFO
-extern "C" struct mallinfo tc_mallinfo(void) __THROW {
+extern "C" PERFTOOLS_DLL_DECL struct mallinfo tc_mallinfo(void) __THROW {
return do_mallinfo();
}
#endif
@@ -1261,7 +1293,7 @@ extern "C" struct mallinfo tc_mallinfo(void) __THROW {
// If flag is 1, calls to malloc will behave like calls to new,
// and the std_new_handler will be invoked on failure.
// Returns the previous mode.
-extern "C" int tc_set_new_mode(int flag) __THROW {
+extern "C" PERFTOOLS_DLL_DECL int tc_set_new_mode(int flag) __THROW {
int old_mode = tc_new_mode;
tc_new_mode = flag;
return old_mode;
@@ -1275,6 +1307,7 @@ extern "C" int tc_set_new_mode(int flag) __THROW {
// This function is an exception to the rule of calling MallocHook method
// from the stack frame of the allocation function;
// heap-checker handles this special case explicitly.
+#ifndef TCMALLOC_FOR_DEBUGALLOCATION
static void *MemalignOverride(size_t align, size_t size, const void *caller)
__THROW ATTRIBUTE_SECTION(google_malloc);
@@ -1285,3 +1318,4 @@ static void *MemalignOverride(size_t align, size_t size, const void *caller)
return result;
}
void *(*__memalign_hook)(size_t, size_t, const void *) = MemalignOverride;
+#endif // #ifndef TCMALLOC_FOR_DEBUGALLOCATION
diff --git a/src/tests/addressmap_unittest.cc b/src/tests/addressmap_unittest.cc
index 6b65cc3..bfbb9a8 100644
--- a/src/tests/addressmap_unittest.cc
+++ b/src/tests/addressmap_unittest.cc
@@ -87,6 +87,8 @@ int main(int argc, char** argv) {
}
for (int x = 0; x < FLAGS_iters; ++x) {
+ RAW_LOG(INFO, "Iteration %d/%d...\n", x, FLAGS_iters);
+
// Permute pointers to get rid of allocation order issues
random_shuffle(ptrs_and_sizes.begin(), ptrs_and_sizes.end());
diff --git a/src/tests/debugallocation_test.cc b/src/tests/debugallocation_test.cc
new file mode 100644
index 0000000..4274b7e
--- /dev/null
+++ b/src/tests/debugallocation_test.cc
@@ -0,0 +1,223 @@
+// Copyright (c) 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ---
+// Author: Fred Akalin
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <vector>
+#include "google/malloc_extension.h"
+#include "base/logging.h"
+
+using std::vector;
+
+vector<void (*)()> g_testlist; // the tests to run
+
+#define TEST(a, b) \
+ struct Test_##a##_##b { \
+ Test_##a##_##b() { g_testlist.push_back(&Run); } \
+ static void Run(); \
+ }; \
+ static Test_##a##_##b g_test_##a##_##b; \
+ void Test_##a##_##b::Run()
+
+
+static int RUN_ALL_TESTS() {
+ vector<void (*)()>::const_iterator it;
+ for (it = g_testlist.begin(); it != g_testlist.end(); ++it) {
+ (*it)(); // The test will error-exit if there's a problem.
+ }
+ fprintf(stderr, "\nPassed %d tests\n\nPASS\n",
+ static_cast<int>(g_testlist.size()));
+ return 0;
+}
+
+// The death tests are meant to be run from a shell-script driver, which
+// passes in an integer saying which death test to run. We store that
+// test-to-run here, and in the macro use a counter to see when we get
+// to that test, so we can run it.
+static int test_to_run = 0; // set in main() based on argv
+static int test_counter = 0; // incremented every time the macro is called
+#define IF_DEBUG_EXPECT_DEATH(statement, regex) do { \
+ if (test_counter++ == test_to_run) { \
+ fprintf(stderr, "Expected regex:%s\n", regex); \
+ statement; \
+ } \
+} while (false)
+
+// This flag won't be compiled in in opt mode.
+DECLARE_int32(max_free_queue_size);
+
+TEST(DebugAllocationTest, DeallocMismatch) {
+ // Allocate with malloc.
+ {
+ int* x = static_cast<int*>(malloc(sizeof(*x)));
+ IF_DEBUG_EXPECT_DEATH(delete x, "mismatch.*being dealloc.*delete");
+ IF_DEBUG_EXPECT_DEATH(delete [] x, "mismatch.*being dealloc.*delete *[[]");
+ // Should work fine.
+ free(x);
+ }
+
+ // Allocate with new.
+ {
+ int* x = new int;
+ IF_DEBUG_EXPECT_DEATH(free(x), "mismatch.*being dealloc.*free");
+ IF_DEBUG_EXPECT_DEATH(delete [] x, "mismatch.*being dealloc.*delete *[[]");
+ delete x;
+ }
+
+ // Allocate with new[].
+ {
+ int* x = new int[1];
+ IF_DEBUG_EXPECT_DEATH(free(x), "mismatch.*being dealloc.*free");
+ IF_DEBUG_EXPECT_DEATH(delete x, "mismatch.*being dealloc.*delete");
+ delete [] x;
+ }
+}
+
+TEST(DebugAllocationTest, FreeQueueTest) {
+ // Verify that the allocator doesn't return blocks that were recently freed.
+ int* x = new int;
+ int* old_x = x;
+ delete x;
+ x = new int;
+ #if 1
+ // This check should not be read as a universal guarantee of behavior. If
+ // other threads are executing, it would be theoretically possible for this
+ // check to fail despite the efforts of debugallocation.cc to the contrary.
+ // It should always hold under the controlled conditions of this unittest,
+ // however.
+ EXPECT_NE(x, old_x); // Allocator shouldn't return recently freed blocks
+ #else
+ // The below check passes, but since it isn't *required* to pass, I've left
+ // it commented out.
+ // EXPECT_EQ(x, old_x);
+ #endif
+ old_x = NULL; // avoid breaking opt build with an unused variable warning.
+ delete x;
+}
+
+TEST(DebugAllocationTest, DanglingPointerWriteTest) {
+ // This test can only be run if debugging.
+ //
+ // If not debugging, the 'new' following the dangling write might not be
+ // safe. When debugging, we expect the (trashed) deleted block to be on the
+ // list of recently-freed blocks, so the following 'new' will be safe.
+#if 1
+ int* x = new int;
+ delete x;
+ int poisoned_x_value = *x;
+ *x = 1; // a dangling write.
+
+ char* s = new char[FLAGS_max_free_queue_size];
+ // When we delete s, we push the storage that was previously allocated to x
+ // off the end of the free queue. At that point, the write to that memory
+ // will be detected.
+ IF_DEBUG_EXPECT_DEATH(delete [] s, "Memory was written to after being freed.");
+
+ // restore the poisoned value of x so that we can delete s without causing a
+ // crash.
+ *x = poisoned_x_value;
+ delete [] s;
+#endif
+}
+
+TEST(DebugAllocationTest, DanglingWriteAtExitTest) {
+ int *x = new int;
+ delete x;
+ int old_x_value = *x;
+ *x = 1;
+ // verify that dangling writes are caught at program termination if the
+ // corrupted block never got pushed off of the end of the free queue.
+ IF_DEBUG_EXPECT_DEATH(exit(0), "Memory was written to after being freed.");
+ *x = old_x_value; // restore x so that the test can exit successfully.
+}
+
+static size_t CurrentlyAllocatedBytes() {
+ size_t value;
+ CHECK(MallocExtension::instance()->GetNumericProperty(
+ "generic.current_allocated_bytes", &value));
+ return value;
+}
+
+TEST(DebugAllocationTest, CurrentlyAllocated) {
+ // Clear the free queue
+#if 1
+ FLAGS_max_free_queue_size = 0;
+ // Force a round-trip through the queue management code so that the
+ // new size is seen and the queue of recently-freed blocks is flushed.
+ free(malloc(1));
+ FLAGS_max_free_queue_size = 1048576;
+#endif
+
+ // Free something and check that it disappears from allocated bytes
+ // immediately.
+ char* p = new char[1000];
+ size_t after_malloc = CurrentlyAllocatedBytes();
+ delete[] p;
+ size_t after_free = CurrentlyAllocatedBytes();
+ EXPECT_LE(after_free, after_malloc - 1000);
+}
+
+TEST(DebugAllocationTest, GetAllocatedSizeTest) {
+#if 1
+ // When debug_allocation is in effect, GetAllocatedSize should return
+ // exactly requested size, since debug_allocation doesn't allow users
+ // to write more than that.
+ for (int i = 0; i < 10; ++i) {
+ void *p = malloc(i);
+ EXPECT_EQ(i, MallocExtension::instance()->GetAllocatedSize(p));
+ free(p);
+ }
+#endif
+ void* a = malloc(1000);
+ EXPECT_GE(MallocExtension::instance()->GetAllocatedSize(a), 1000);
+ // This is just a sanity check. If we allocated too much, alloc is broken
+ EXPECT_LE(MallocExtension::instance()->GetAllocatedSize(a), 5000);
+ EXPECT_GE(MallocExtension::instance()->GetEstimatedAllocatedSize(1000), 1000);
+ free(a);
+}
+
+int main(int argc, char** argv) {
+ // If you run without args, we run the non-death parts of the test.
+ // Otherwise, argv[1] should be a number saying which death-test
+ // to run. We will output a regexp we expect the death-message
+ // to include, and then run the given death test (which hopefully
+ // will produce that error message). If argv[1] > the number of
+ // death tests, we will run only the non-death parts. One way to
+ // tell when you are done with all tests is when no 'expected
+ // regexp' message is printed for a given argv[1].
+ if (argc < 2) {
+ test_to_run = -1; // will never match
+ } else {
+ test_to_run = atoi(argv[1]);
+ }
+ return RUN_ALL_TESTS();
+}
diff --git a/src/tests/debugallocation_test.sh b/src/tests/debugallocation_test.sh
new file mode 100755
index 0000000..2568d54
--- /dev/null
+++ b/src/tests/debugallocation_test.sh
@@ -0,0 +1,78 @@
+#!/bin/sh
+
+# Copyright (c) 2009, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# ---
+# Author: Craig Silverstein
+
+BINDIR="${BINDIR:-.}"
+
+if [ "x$1" = "x-h" -o "x$1" = "x--help" ]; then
+ echo "USAGE: $0 [unittest dir]"
+ echo " By default, unittest_dir=$BINDIR"
+ exit 1
+fi
+
+DEBUGALLOCATION_TEST="${1:-$BINDIR/debugallocation_test}"
+
+num_failures=0
+
+# Run the i-th death test and make sure the test has the expected
+# regexp. We can depend on the first line of the output being
+# Expected regex:<regex>
+# Evaluates to "done" if we are not actually a death-test (so $1 is
+# too big a number, and we can stop). Evaluates to "" otherwise.
+# Increments num_failures if the death test does not succeed.
+OneDeathTest() {
+ "$DEBUGALLOCATION_TEST" "$1" 2>&1 | {
+ read regex_line
+ regex=`expr "$regex_line" : "Expected regex:\(.*\)"`
+ test -z "$regex" && echo "done" # no regex line, not a death-case
+ grep "$regex" >/dev/null 2>&1 # pass the rest of the lines through grep
+ } || num_failures=`expr $num_failures + 1`
+}
+
+death_test_num=0 # which death test to run
+while test -z `OneDeathTest "$death_test_num"`; do
+ echo "Done with death test $death_test_num"
+ death_test_num=`expr $death_test_num + 1`
+done
+
+# Test the non-death parts of the test too
+if ! "$DEBUGALLOCATION_TEST"; then
+ num_failures=`expr $num_failures + 1`
+fi
+
+if [ "$num_failures" = 0 ]; then
+ echo "PASS"
+else
+ echo "Failed with $num_failures failures"
+fi
+exit $num_failures
diff --git a/src/tests/heap-checker_unittest.cc b/src/tests/heap-checker_unittest.cc
index 55b6a21..4be1a7c 100644
--- a/src/tests/heap-checker_unittest.cc
+++ b/src/tests/heap-checker_unittest.cc
@@ -1,10 +1,10 @@
// Copyright (c) 2005, Google Inc.
// All rights reserved.
-//
+//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
-//
+//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
@@ -14,7 +14,7 @@
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
-//
+//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -58,7 +58,9 @@
// (see the comment in our .h file).
#include "config_for_unittests.h"
-#include <sys/poll.h>
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
#if defined HAVE_STDINT_H
#include <stdint.h> // to get uint16_t (ISO naming madness)
#elif defined HAVE_INTTYPES_H
@@ -539,6 +541,20 @@ static void TestHeapLeakCheckerDeathCountMore() {
DeAllocHidden(&bar2);
}
+static void TestHiddenPointer() {
+ int i;
+ void* foo = &i;
+ HiddenPointer<void> p(foo);
+ CHECK_EQ(foo, p.get());
+
+ // Confirm pointer doesn't appear to contain a byte sequence
+ // that == the pointer. We don't really need to test that
+ // the xor trick itself works, as without it nothing in this
+ // test suite would work. See the Hide/Unhide/*Hidden* set
+ // of helper methods.
+ CHECK_NE(foo, *reinterpret_cast<void**>(&p));
+}
+
// simple tests that deallocate what they allocated
static void TestHeapLeakChecker() {
{ HeapLeakChecker check("trivial");
@@ -1304,7 +1320,6 @@ static int Pass() {
int main(int argc, char** argv) {
run_hidden_ptr = DoRunHidden;
wipe_stack_ptr = DoWipeStack;
-
if (!HeapLeakChecker::IsActive()) {
CHECK_EQ(FLAGS_heap_check, "");
LOG(WARNING, "HeapLeakChecker got turned off; we won't test much...");
@@ -1376,6 +1391,8 @@ int main(int argc, char** argv) {
HeapLeakChecker heap_check("all");
+ TestHiddenPointer();
+
TestHeapLeakChecker();
Pause();
TestLeakButTotalsMatch();
@@ -1443,6 +1460,6 @@ int main(int argc, char** argv) {
}
CHECK(HeapLeakChecker::NoGlobalLeaks()); // so far, so good
-
+
return Pass();
}
diff --git a/src/tests/heap-profiler_unittest.cc b/src/tests/heap-profiler_unittest.cc
index a9b6510..e5dedee 100644
--- a/src/tests/heap-profiler_unittest.cc
+++ b/src/tests/heap-profiler_unittest.cc
@@ -96,6 +96,27 @@ static void TestHeapProfilerStartStopIsRunning() {
}
}
+static void TestDumpHeapProfiler() {
+ // If you run this with whole-program heap-profiling on, than
+ // IsHeapProfilerRunning should return true.
+ if (!IsHeapProfilerRunning()) {
+ const char* tmpdir = getenv("TMPDIR");
+ if (tmpdir == NULL)
+ tmpdir = "/tmp";
+ mkdir(tmpdir, 0755); // if necessary
+ HeapProfilerStart((string(tmpdir) + "/dump").c_str());
+ CHECK(IsHeapProfilerRunning());
+
+ Allocate(0, 40, 100);
+ Deallocate(0, 40);
+
+ char* output = GetHeapProfile();
+ free(output);
+ HeapProfilerStop();
+ }
+}
+
+
int main(int argc, char** argv) {
if (argc > 2 || (argc == 2 && argv[1][0] == '-')) {
printf("USAGE: %s [number of children to fork]\n", argv[0]);
@@ -107,6 +128,7 @@ int main(int argc, char** argv) {
}
TestHeapProfilerStartStopIsRunning();
+ TestDumpHeapProfiler();
Allocate(0, 40, 100);
Deallocate(0, 40);
diff --git a/src/tests/heap-profiler_unittest.sh b/src/tests/heap-profiler_unittest.sh
index a728aa9..ad0a1ec 100755
--- a/src/tests/heap-profiler_unittest.sh
+++ b/src/tests/heap-profiler_unittest.sh
@@ -136,6 +136,10 @@ VerifyMemFunction Allocate "$HEAPPROFILE"_*.1448.heap "$HEAPPROFILE"_*.1548.heap
VerifyOutputContains "62 MB allocated"
VerifyOutputContains "62 MB freed"
+# Now try running without --heap_profile specified, to allow
+# testing of the HeapProfileStart/Stop functionality.
+$HEAP_PROFILER >"$TEST_TMPDIR/output2" 2>&1
+
rm -rf $TMPDIR # clean up
if [ $num_failures = 0 ]; then
diff --git a/src/tests/low_level_alloc_unittest.cc b/src/tests/low_level_alloc_unittest.cc
index 1ec0f1b..f98f8a5 100644
--- a/src/tests/low_level_alloc_unittest.cc
+++ b/src/tests/low_level_alloc_unittest.cc
@@ -26,9 +26,6 @@
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * ---
- * Author: Mike Burrows
*/
// A test for low_level_alloc.cc
@@ -78,7 +75,7 @@ static bool using_low_level_alloc = false;
// before being freed. At the end of the run,
// all remaining allocated blocks are freed.
// If use_new_arena is true, use a fresh arena, and then delete it.
-// If call_malloc_hook is true and user_arena is true,
+// If call_malloc_hook is true and user_arena is true,
// allocations and deallocations are reported via the MallocHook
// interface.
static void Test(bool use_new_arena, bool call_malloc_hook, int n) {
@@ -93,6 +90,11 @@ static void Test(bool use_new_arena, bool call_malloc_hook, int n) {
arena = LowLevelAlloc::NewArena(flags, LowLevelAlloc::DefaultArena());
}
for (int i = 0; i != n; i++) {
+ if (i != 0 && i % 10000 == 0) {
+ printf(".");
+ fflush(stdout);
+ }
+
switch(rand() & 1) { // toss a coin
case 0: // coin came up heads: add a block
using_low_level_alloc = true;
@@ -195,7 +197,7 @@ int main(int argc, char *argv[]) {
CHECK_EQ(frees, 0);
}
}
- printf("PASS\n");
+ printf("\nPASS\n");
CHECK_EQ(MallocHook::SetNewHook(old_alloc_hook), AllocHook);
CHECK_EQ(MallocHook::SetDeleteHook(old_free_hook), FreeHook);
return 0;
diff --git a/src/tests/malloc_extension_test.cc b/src/tests/malloc_extension_test.cc
index 7254fe5..1f00f73 100644
--- a/src/tests/malloc_extension_test.cc
+++ b/src/tests/malloc_extension_test.cc
@@ -58,6 +58,13 @@ int main(int argc, char** argv) {
CHECK_LE(MallocExtension::instance()->GetAllocatedSize(a), 5000);
CHECK_GE(MallocExtension::instance()->GetEstimatedAllocatedSize(1000), 1000);
+ for (int i = 0; i < 10; ++i) {
+ void *p = malloc(i);
+ CHECK_GE(MallocExtension::instance()->GetAllocatedSize(p),
+ MallocExtension::instance()->GetEstimatedAllocatedSize(i));
+ free(p);
+ }
+
// Check the c-shim version too.
CHECK_GE(MallocExtension_GetAllocatedSize(a), 1000);
CHECK_LE(MallocExtension_GetAllocatedSize(a), 5000);
diff --git a/src/tests/markidle_unittest.cc b/src/tests/markidle_unittest.cc
index 0d9178f..ac9971f 100644
--- a/src/tests/markidle_unittest.cc
+++ b/src/tests/markidle_unittest.cc
@@ -31,6 +31,7 @@
// Author: Sanjay Ghemawat
//
// MallocExtension::MarkThreadIdle() testing
+#include <stdio.h>
#include "config_for_unittests.h"
#include "base/logging.h"
diff --git a/src/tests/memalign_unittest.cc b/src/tests/memalign_unittest.cc
index a8d418e..d5b60db 100644
--- a/src/tests/memalign_unittest.cc
+++ b/src/tests/memalign_unittest.cc
@@ -170,13 +170,19 @@ int main(int argc, char** argv) {
CHECK(posix_memalign(&ptr, sizeof(void*)+1, 1) == EINVAL);
CHECK(posix_memalign(&ptr, 4097, 1) == EINVAL);
+ // Grab some memory so that the big allocation below will definitely fail.
+ void* p_small = malloc(4*1048576);
+ CHECK(p_small != NULL);
+
// Make sure overflow is returned as ENOMEM
- for (size_t s = 0; ; s += (10 << 20)) {
- int r = posix_memalign(&ptr, 1024, s);
- if (r == ENOMEM) break;
- CHECK(r == 0);
- free(ptr);
+ const size_t zero = 0;
+ static const size_t kMinusNTimes = 10;
+ for ( size_t i = 1; i < kMinusNTimes; ++i ) {
+ int r = posix_memalign(&ptr, 1024, zero - i);
+ CHECK(r == ENOMEM);
}
+
+ free(p_small);
}
const int pagesize = getpagesize();
@@ -185,8 +191,8 @@ int main(int argc, char** argv) {
for (int s = 0; s != -1; s = NextSize(s)) {
void* p = valloc(s);
CheckAlignment(p, pagesize);
- Fill(p, pagesize, 'v');
- CHECK(Valid(p, pagesize, 'v'));
+ Fill(p, s, 'v');
+ CHECK(Valid(p, s, 'v'));
free(p);
}
}
@@ -201,12 +207,6 @@ int main(int argc, char** argv) {
CHECK(Valid(p, alloc_needed, 'x'));
free(p);
}
-
- // should be safe to write upto a page in pvalloc(0) region
- void* p = pvalloc(0);
- Fill(p, pagesize, 'y');
- CHECK(Valid(p, pagesize, 'y'));
- free(p);
}
printf("PASS\n");
diff --git a/src/tests/pagemap_unittest.cc b/src/tests/pagemap_unittest.cc
index 902b8dd..dcf6c9a 100644
--- a/src/tests/pagemap_unittest.cc
+++ b/src/tests/pagemap_unittest.cc
@@ -63,6 +63,8 @@ static void Permute(vector<intptr_t>* elements) {
// Test specified map type
template <class Type>
void TestMap(int limit, bool limit_is_below_the_overflow_boundary) {
+ RAW_LOG(INFO, "Running test with %d iterations...\n", limit);
+
{ // Test sequential ensure/assignment
Type map(malloc);
for (intptr_t i = 0; i < static_cast<intptr_t>(limit); i++) {
diff --git a/src/tests/profile-handler_unittest.cc b/src/tests/profile-handler_unittest.cc
index d780aac..4b247c7 100644
--- a/src/tests/profile-handler_unittest.cc
+++ b/src/tests/profile-handler_unittest.cc
@@ -14,15 +14,6 @@
#include "base/simple_mutex.h"
// Some helpful macros for the test class
-#define EXPECT_TRUE(cond) CHECK(cond)
-#define EXPECT_FALSE(cond) CHECK(!(cond))
-#define EXPECT_EQ(a, b) CHECK_EQ(a, b)
-#define EXPECT_NE(a, b) CHECK_NE(a, b)
-#define EXPECT_GT(a, b) CHECK_GT(a, b)
-#define EXPECT_LT(a, b) CHECK_LT(a, b)
-#define EXPECT_GE(a, b) CHECK_GE(a, b)
-#define EXPECT_LE(a, b) CHECK_LE(a, b)
-#define EXPECT_STREQ(a, b) CHECK(strcmp(a, b) == 0)
#define TEST_F(cls, fn) void cls :: fn()
namespace {
diff --git a/src/tests/profiledata_unittest.cc b/src/tests/profiledata_unittest.cc
index 31ba3b6..f569f64 100644
--- a/src/tests/profiledata_unittest.cc
+++ b/src/tests/profiledata_unittest.cc
@@ -51,18 +51,8 @@
using std::string;
// Some helpful macros for the test class
-#define EXPECT_TRUE(cond) CHECK(cond)
-#define EXPECT_FALSE(cond) CHECK(!(cond))
-#define EXPECT_EQ(a, b) CHECK_EQ(a, b)
-#define EXPECT_NE(a, b) CHECK_NE(a, b)
-#define EXPECT_GT(a, b) CHECK_GT(a, b)
-#define EXPECT_LT(a, b) CHECK_LT(a, b)
-#define EXPECT_GE(a, b) CHECK_GE(a, b)
-#define EXPECT_LE(a, b) CHECK_LE(a, b)
-#define EXPECT_STREQ(a, b) CHECK(strcmp(a, b) == 0)
#define TEST_F(cls, fn) void cls :: fn()
-
namespace {
template<typename T> class scoped_array {
diff --git a/src/tests/profiler_unittest.cc b/src/tests/profiler_unittest.cc
index 1063751..1908b03 100644
--- a/src/tests/profiler_unittest.cc
+++ b/src/tests/profiler_unittest.cc
@@ -48,7 +48,7 @@
static int result = 0;
static int g_iters = 0; // argv[1]
-Mutex mutex;
+Mutex mutex(Mutex::LINKER_INITIALIZED);
static void test_other_thread() {
#ifndef NO_THREADS
diff --git a/src/tests/profiler_unittest.sh b/src/tests/profiler_unittest.sh
index 2524b96..73be680 100755
--- a/src/tests/profiler_unittest.sh
+++ b/src/tests/profiler_unittest.sh
@@ -53,21 +53,40 @@ if [ "x$1" = "x-h" -o "x$1" = "x--help" ]; then
exit 1
fi
+TMPDIR=/tmp/profile_info
+
UNITTEST_DIR=${1:-$BINDIR}
PPROF=${2:-$PPROF_PATH}
-PROFILER1=$UNITTEST_DIR/profiler1_unittest
-PROFILER2=$UNITTEST_DIR/profiler2_unittest
-PROFILER3=$UNITTEST_DIR/profiler3_unittest
-PROFILER4=$UNITTEST_DIR/profiler4_unittest
+# We test the sliding-window functionality of the cpu-profile reader
+# by using a small stride, forcing lots of reads.
+PPROF_FLAGS="--test_stride=128"
-TMPDIR=/tmp/profile_info
+PROFILER1="$UNITTEST_DIR/profiler1_unittest"
+PROFILER2="$UNITTEST_DIR/profiler2_unittest"
+PROFILER3="$UNITTEST_DIR/profiler3_unittest"
+PROFILER4="$UNITTEST_DIR/profiler4_unittest"
+
+# Unfortunately, for us, libtool can replace executables with a shell
+# script that does some work before calling the 'real' executable
+# under a different name. We need the 'real' executable name to run
+# pprof on it. We've constructed all the binaries used in this
+# unittest so when they are called with no arguments, they report
+# their argv[0], which is the real binary name.
+Realname() {
+ "$1" 2>&1 | awk '{print $2; exit;}'
+}
+
+PROFILER1_REALNAME=`Realname "$PROFILER1"`
+PROFILER2_REALNAME=`Realname "$PROFILER2"`
+PROFILER3_REALNAME=`Realname "$PROFILER3"`
+PROFILER4_REALNAME=`Realname "$PROFILER4"`
# It's meaningful to the profiler, so make sure we know its state
unset CPUPROFILE
-rm -rf $TMPDIR
-mkdir $TMPDIR || exit 2
+rm -rf "$TMPDIR"
+mkdir "$TMPDIR" || exit 2
num_failures=0
@@ -82,15 +101,17 @@ RegisterFailure() {
# noise-reducing X units to each value. But even that would often
# spuriously fail, so now it's "both non-zero". We're pretty forgiving.
VerifySimilar() {
- prof1=$TMPDIR/$1
- # We need to run the script with no args to get the actual exe name
- exec1=`$2 2>&1 | awk '{print $2; exit;}'`
- prof2=$TMPDIR/$3
- exec2=`$4 2>&1 | awk '{print $2; exit;}'`
- mult=$5
+ prof1="$TMPDIR/$1"
+ exec1="$2"
+ prof2="$TMPDIR/$3"
+ exec2="$4"
+ mult="$5"
- mthread1=`$PPROF $exec1 $prof1 | grep test_main_thread | awk '{print $1}'`
- mthread2=`$PPROF $exec2 $prof2 | grep test_main_thread | awk '{print $1}'`
+ # We are careful not to put exec1 and exec2 in quotes, because if
+ # they are the empty string, it means we want to use the 1-arg
+ # version of pprof.
+ mthread1=`"$PPROF" $PPROF_FLAGS $exec1 "$prof1" | grep test_main_thread | awk '{print $1}'`
+ mthread2=`"$PPROF" $PPROF_FLAGS $exec2 "$prof2" | grep test_main_thread | awk '{print $1}'`
mthread1_plus=`expr $mthread1 + 5`
mthread2_plus=`expr $mthread2 + 5`
if [ -z "$mthread1" ] || [ -z "$mthread2" ] || \
@@ -106,6 +127,32 @@ VerifySimilar() {
fi
}
+# Takes two filenames representing profiles, and optionally their
+# executable scripts (these may be empty if the profiles include
+# symbols), and verifies that the two profiles are identical.
+VerifyIdentical() {
+ prof1="$TMPDIR/$1"
+ exec1="$2"
+ prof2="$TMPDIR/$3"
+ exec2="$4"
+
+ # We are careful not to put exec1 and exec2 in quotes, because if
+ # they are the empty string, it means we want to use the 1-arg
+ # version of pprof.
+ "$PPROF" $PPROF_FLAGS $exec1 "$prof1" > "$TMPDIR/out1"
+ "$PPROF" $PPROF_FLAGS $exec2 "$prof2" > "$TMPDIR/out2"
+ diff=`diff "$TMPDIR/out1" "$TMPDIR/out2"`
+
+ if [ ! -z "$diff" ]; then
+ echo
+ echo ">>> profile doesn't match, args: $exec1 $prof1 vs. $exec2 $prof2"
+ echo ">>> Diff:"
+ echo "$diff"
+ echo
+ RegisterFailure
+ fi
+}
+
# Takes a filename representing a profile, with its executable,
# and a multiplier, and verifies that the main-thread function takes
# the same amount of time as the other-threads function (possibly scaled
@@ -115,13 +162,15 @@ VerifySimilar() {
# noise-reducing X units to each value. But even that would often
# spuriously fail, so now it's "both non-zero". We're pretty forgiving.
VerifyAcrossThreads() {
- prof1=$TMPDIR/$1
+ prof1="$TMPDIR/$1"
# We need to run the script with no args to get the actual exe name
- exec1=`$2 2>&1 | awk '{print $2; exit;}'`
- mult=$3
+ exec1="$2"
+ mult="$3"
- mthread=`$PPROF $exec1 $prof1 | grep test_main_thread | awk '{print $1}'`
- othread=`$PPROF $exec1 $prof1 | grep test_other_thread | awk '{print $1}'`
+ # We are careful not to put exec1 in quotes, because if it is the
+ # empty string, it means we want to use the 1-arg version of pprof.
+ mthread=`$PPROF $PPROF_FLAGS $exec1 "$prof1" | grep test_main_thread | awk '{print $1}'`
+ othread=`$PPROF $PPROF_FLAGS $exec1 "$prof1" | grep test_other_thread | awk '{print $1}'`
if [ -z "$mthread" ] || [ -z "$othread" ] || \
[ "$mthread" -le 0 -o "$othread" -le 0 ]
# || [ `expr $mthread \* $mult \* 3` -gt `expr $othread \* 10` -o \
@@ -143,54 +192,65 @@ echo "If the test does fail with an 'Actual times' error, try running again."
echo
# profiler1 is a non-threaded version
-$PROFILER1 50 1 $TMPDIR/p1 || RegisterFailure
-$PROFILER1 100 1 $TMPDIR/p2 || RegisterFailure
-VerifySimilar p1 $PROFILER1 p2 $PROFILER1 2
+"$PROFILER1" 50 1 "$TMPDIR/p1" || RegisterFailure
+"$PROFILER1" 100 1 "$TMPDIR/p2" || RegisterFailure
+VerifySimilar p1 "$PROFILER1_REALNAME" p2 "$PROFILER1_REALNAME" 2
# Verify the same thing works if we statically link
-$PROFILER2 50 1 $TMPDIR/p3 || RegisterFailure
-$PROFILER2 100 1 $TMPDIR/p4 || RegisterFailure
-VerifySimilar p3 $PROFILER2 p4 $PROFILER2 2
+"$PROFILER2" 50 1 "$TMPDIR/p3" || RegisterFailure
+"$PROFILER2" 100 1 "$TMPDIR/p4" || RegisterFailure
+VerifySimilar p3 "$PROFILER2_REALNAME" p4 "$PROFILER2_REALNAME" 2
# Verify the same thing works if we specify via CPUPROFILE
-CPUPROFILE=$TMPDIR/p5 $PROFILER2 50 || RegisterFailure
-CPUPROFILE=$TMPDIR/p6 $PROFILER2 100 || RegisterFailure
-VerifySimilar p5 $PROFILER2 p6 $PROFILER2 2
+CPUPROFILE="$TMPDIR/p5" "$PROFILER2" 50 || RegisterFailure
+CPUPROFILE="$TMPDIR/p6" "$PROFILER2" 100 || RegisterFailure
+VerifySimilar p5 "$PROFILER2_REALNAME" p6 "$PROFILER2_REALNAME" 2
# When we compile with threads, things take a lot longer even when we only use 1
-CPUPROFILE=$TMPDIR/p5b $PROFILER3 10 || RegisterFailure
-CPUPROFILE=$TMPDIR/p5c $PROFILER3 20 || RegisterFailure
-VerifySimilar p5b $PROFILER3 p5c $PROFILER3 2
+CPUPROFILE="$TMPDIR/p5b" "$PROFILER3" 10 || RegisterFailure
+CPUPROFILE="$TMPDIR/p5c" "$PROFILER3" 20 || RegisterFailure
+VerifySimilar p5b "$PROFILER3_REALNAME" p5c "$PROFILER3_REALNAME" 2
# Now try what happens when we use threads
-$PROFILER3 5 2 $TMPDIR/p7 || RegisterFailure
-$PROFILER3 10 2 $TMPDIR/p8 || RegisterFailure
-VerifySimilar p7 $PROFILER3 p8 $PROFILER3 2
+"$PROFILER3" 5 2 "$TMPDIR/p7" || RegisterFailure
+"$PROFILER3" 10 2 "$TMPDIR/p8" || RegisterFailure
+VerifySimilar p7 "$PROFILER3_REALNAME" p8 "$PROFILER3_REALNAME" 2
-$PROFILER4 5 2 $TMPDIR/p9 || RegisterFailure
-$PROFILER4 10 2 $TMPDIR/p10 || RegisterFailure
-VerifySimilar p9 $PROFILER4 p10 $PROFILER4 2
+"$PROFILER4" 5 2 "$TMPDIR/p9" || RegisterFailure
+"$PROFILER4" 10 2 "$TMPDIR/p10" || RegisterFailure
+VerifySimilar p9 "$PROFILER4_REALNAME" p10 "$PROFILER4_REALNAME" 2
# More threads!
-$PROFILER4 2 3 $TMPDIR/p9 || RegisterFailure
-$PROFILER4 4 3 $TMPDIR/p10 || RegisterFailure
-VerifySimilar p9 $PROFILER4 p10 $PROFILER4 2
+"$PROFILER4" 2 3 "$TMPDIR/p9" || RegisterFailure
+"$PROFILER4" 4 3 "$TMPDIR/p10" || RegisterFailure
+VerifySimilar p9 "$PROFILER4_REALNAME" p10 "$PROFILER4_REALNAME" 2
# Compare how much time the main thread takes compared to the other threads
# Recall the main thread runs twice as long as the other threads, by design.
-$PROFILER4 2 4 $TMPDIR/p11 || RegisterFailure
-VerifyAcrossThreads p11 $PROFILER4 2
+"$PROFILER4" 2 4 "$TMPDIR/p11" || RegisterFailure
+VerifyAcrossThreads p11 "$PROFILER4_REALNAME" 2
+
+# Test symbol save and restore
+"$PROFILER1" 50 1 "$TMPDIR/p12" || RegisterFailure
+"$PPROF" $PPROF_FLAGS "$PROFILER1_REALNAME" "$TMPDIR/p12" --raw \
+ >"$TMPDIR/p13" 2>/dev/null || RegisterFailure
+VerifyIdentical p12 "$PROFILER1_REALNAME" p13 "" || RegisterFailure
+
+"$PROFILER3" 5 2 "$TMPDIR/p14" || RegisterFailure
+"$PPROF" $PPROF_FLAGS "$PROFILER3_REALNAME" "$TMPDIR/p14" --raw \
+ >"$TMPDIR/p15" 2>/dev/null || RegisterFailure
+VerifyIdentical p14 "$PROFILER3_REALNAME" p15 "" || RegisterFailure
# Make sure that when we have a process with a fork, the profiles don't
# clobber each other
-CPUPROFILE=$TMPDIR/p6 $PROFILER1 1 -2 || RegisterFailure
+CPUPROFILE="$TMPDIR/p6" "$PROFILER1" 1 -2 || RegisterFailure
n=`ls $TMPDIR/p6* | wc -l`
if [ $n != 3 ]; then
echo "FORK test FAILED: expected 3 profiles (for main + 2 children), found $n"
num_failures=`expr $num_failures + 1`
fi
-rm -rf $TMPDIR # clean up
+rm -rf "$TMPDIR" # clean up
echo "Tests finished with $num_failures failures"
exit $num_failures
diff --git a/src/tests/sampler_test.cc b/src/tests/sampler_test.cc
index 2d5824e..fca10ac 100755
--- a/src/tests/sampler_test.cc
+++ b/src/tests/sampler_test.cc
@@ -468,7 +468,6 @@ void OldSampler::Init(uint32_t seed) {
// A cut-down version of the old PickNextSampleRoutine
void OldSampler::PickNextSample(size_t k) {
- // Copied from "base/synchronization.cc" (written by Mike Burrows)
// Make next "random" number
// x^32+x^22+x^2+x^1+1 is a primitive polynomial for random numbers
static const uint32_t kPoly = (1 << 22) | (1 << 2) | (1 << 1) | (1 << 0);
diff --git a/src/tests/stacktrace_unittest.cc b/src/tests/stacktrace_unittest.cc
index 02a2093..69e20ba 100644
--- a/src/tests/stacktrace_unittest.cc
+++ b/src/tests/stacktrace_unittest.cc
@@ -37,65 +37,84 @@
#include "base/logging.h"
#include <google/stacktrace.h>
+namespace {
// Obtain a backtrace, verify that the expected callers are present in the
// backtrace, and maybe print the backtrace to stdout.
-//-----------------------------------------------------------------------//
-void CheckStackTraceLeaf();
-void CheckStackTrace4(int i);
-void CheckStackTrace3(int i);
-void CheckStackTrace2(int i);
-void CheckStackTrace1(int i);
-void CheckStackTrace(int i);
-//-----------------------------------------------------------------------//
-
// The sequence of functions whose return addresses we expect to see in the
// backtrace.
const int BACKTRACE_STEPS = 6;
-void * expected_stack[BACKTRACE_STEPS] = {
- (void *) &CheckStackTraceLeaf,
- (void *) &CheckStackTrace4,
- (void *) &CheckStackTrace3,
- (void *) &CheckStackTrace2,
- (void *) &CheckStackTrace1,
- (void *) &CheckStackTrace,
+
+struct AddressRange {
+ const void *start, *end;
};
-// Depending on the architecture/compiler/libraries, (not sure which)
-// the current function may or may not appear in the backtrace.
-// For gcc-2:
-//
-// stack[0] is ret addr within CheckStackTrace4
-// stack[1] is ret addr within CheckStackTrace3
-// stack[2] is ret addr within CheckStackTrace2
-// stack[3] is ret addr within CheckStackTrace1
-// stack[4] is ret addr within CheckStackTrace
-//
-// For gcc3-k8:
-//
-// stack[0] is ret addr within CheckStackTraceLeaf
-// stack[1] is ret addr within CheckStackTrace4
-// ...
-// stack[5] is ret addr within CheckStackTrace
+// Expected function [start,end] range.
+AddressRange expected_range[BACKTRACE_STEPS];
+
+#if __GNUC__
+// Using GCC extension: address of a label can be taken with '&&label'.
+// Start should be a label somewhere before recursive call, end somewhere
+// after it.
+#define INIT_ADDRESS_RANGE(fn, start_label, end_label, prange) \
+ do { \
+ (prange)->start = &&start_label; \
+ (prange)->end = &&end_label; \
+ CHECK_LT((prange)->start, (prange)->end); \
+ } while (0)
+// This macro expands into "unmovable" code (opaque to GCC), and that
+// prevents GCC from moving a_label up or down in the code.
+// Without it, there is no code following the 'end' label, and GCC
+// (4.3.1, 4.4.0) thinks it safe to assign &&end an address that is before
+// the recursive call.
+#define DECLARE_ADDRESS_LABEL(a_label) \
+ a_label: do { __asm__ __volatile__(""); } while (0)
+// Gcc 4.4.0 may split function into multiple chunks, and the chunk
+// performing recursive call may end up later in the code then the return
+// instruction (this actually happens with FDO).
+// Adjust function range from __builtin_return_address.
+#define ADJUST_ADDRESS_RANGE_FROM_RA(prange) \
+ do { \
+ void *ra = __builtin_return_address(0); \
+ CHECK_LT((prange)->start, ra); \
+ if (ra > (prange)->end) { \
+ printf("Adjusting range from %p..%p to %p..%p\n", \
+ (prange)->start, (prange)->end, \
+ (prange)->start, ra); \
+ (prange)->end = ra; \
+ } \
+ } while (0)
+#else
+// Assume the Check* functions below are not longer than 256 bytes.
+#define INIT_ADDRESS_RANGE(fn, start_label, end_label, prange) \
+ do { \
+ (prange)->start = reinterpret_cast<const void *>(&fn); \
+ (prange)->end = reinterpret_cast<const char *>(&fn) + 256; \
+ } while (0)
+#define DECLARE_ADDRESS_LABEL(a_label) do { } while (0)
+#define ADJUST_ADDRESS_RANGE_FROM_RA(prange) do { } while (0)
+#endif // __GNUC__
//-----------------------------------------------------------------------//
-const int kMaxFnLen = 0x40; // assume relevant functions are only this long
-
-void CheckRetAddrIsInFunction( void * ret_addr, void * function_start_addr)
+void CheckRetAddrIsInFunction(void *ret_addr, const AddressRange &range)
{
- CHECK_GE(ret_addr, function_start_addr);
- CHECK_LE(ret_addr, (void *) ((char *) function_start_addr + kMaxFnLen));
+ CHECK_GE(ret_addr, range.start);
+ CHECK_LE(ret_addr, range.end);
}
//-----------------------------------------------------------------------//
-void CheckStackTraceLeaf(void) {
+void ATTRIBUTE_NOINLINE CheckStackTrace(int);
+void ATTRIBUTE_NOINLINE CheckStackTraceLeaf(void) {
const int STACK_LEN = 10;
void *stack[STACK_LEN];
int size;
+ ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[1]);
+ INIT_ADDRESS_RANGE(CheckStackTraceLeaf, start, end, &expected_range[0]);
+ DECLARE_ADDRESS_LABEL(start);
size = GetStackTrace(stack, STACK_LEN, 0);
printf("Obtained %d stack frames.\n", size);
CHECK_GE(size, 1);
@@ -114,44 +133,62 @@ void CheckStackTraceLeaf(void) {
for (int i = 0; i < BACKTRACE_STEPS; i++) {
printf("Backtrace %d: expected: %p..%p actual: %p ... ",
- i, expected_stack[i],
- reinterpret_cast<char*>(expected_stack[i]) + kMaxFnLen, stack[i]);
+ i, expected_range[i].start, expected_range[i].end, stack[i]);
fflush(stdout);
- CheckRetAddrIsInFunction(stack[i], expected_stack[i]);
+ CheckRetAddrIsInFunction(stack[i], expected_range[i]);
printf("OK\n");
}
+ DECLARE_ADDRESS_LABEL(end);
}
//-----------------------------------------------------------------------//
/* Dummy functions to make the backtrace more interesting. */
void ATTRIBUTE_NOINLINE CheckStackTrace4(int i) {
+ ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[2]);
+ INIT_ADDRESS_RANGE(CheckStackTrace4, start, end, &expected_range[1]);
+ DECLARE_ADDRESS_LABEL(start);
for (int j = i; j >= 0; j--)
CheckStackTraceLeaf();
+ DECLARE_ADDRESS_LABEL(end);
}
void ATTRIBUTE_NOINLINE CheckStackTrace3(int i) {
+ ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[3]);
+ INIT_ADDRESS_RANGE(CheckStackTrace3, start, end, &expected_range[2]);
+ DECLARE_ADDRESS_LABEL(start);
for (int j = i; j >= 0; j--)
CheckStackTrace4(j);
+ DECLARE_ADDRESS_LABEL(end);
}
void ATTRIBUTE_NOINLINE CheckStackTrace2(int i) {
+ ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[4]);
+ INIT_ADDRESS_RANGE(CheckStackTrace2, start, end, &expected_range[3]);
+ DECLARE_ADDRESS_LABEL(start);
for (int j = i; j >= 0; j--)
CheckStackTrace3(j);
+ DECLARE_ADDRESS_LABEL(end);
}
void ATTRIBUTE_NOINLINE CheckStackTrace1(int i) {
+ ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[5]);
+ INIT_ADDRESS_RANGE(CheckStackTrace1, start, end, &expected_range[4]);
+ DECLARE_ADDRESS_LABEL(start);
for (int j = i; j >= 0; j--)
CheckStackTrace2(j);
+ DECLARE_ADDRESS_LABEL(end);
}
void ATTRIBUTE_NOINLINE CheckStackTrace(int i) {
+ INIT_ADDRESS_RANGE(CheckStackTrace, start, end, &expected_range[5]);
+ DECLARE_ADDRESS_LABEL(start);
for (int j = i; j >= 0; j--)
CheckStackTrace1(j);
+ DECLARE_ADDRESS_LABEL(end);
}
+} // namespace
//-----------------------------------------------------------------------//
int main(int argc, char ** argv) {
-
CheckStackTrace(0);
-
printf("PASS\n");
return 0;
}
diff --git a/src/tests/tcmalloc_unittest.cc b/src/tests/tcmalloc_unittest.cc
index 1fdd300..f1f52b8 100644
--- a/src/tests/tcmalloc_unittest.cc
+++ b/src/tests/tcmalloc_unittest.cc
@@ -45,6 +45,13 @@
// d. Free an object
// Also, at the end of every step, object(s) are freed to maintain
// the memory upper-bound.
+//
+// If this test is compiled with -DDEBUGALLOCATION, then we don't
+// run some tests that test the inner workings of tcmalloc and
+// break on debugallocation: that certain allocations are aligned
+// in a certain way (even though no standard requires it), and that
+// realloc() tries to minimize copying (which debug allocators don't
+// care about).
#include "config_for_unittests.h"
// Complicated ordering requirements. tcmalloc.h defines (indirectly)
@@ -82,6 +89,7 @@
#include "base/simple_mutex.h"
#include "google/malloc_hook.h"
#include "google/malloc_extension.h"
+#include "google/tcmalloc.h"
#include "thread_cache.h"
#include "tests/testutil.h"
@@ -511,6 +519,7 @@ static void TestHugeAllocations(AllocatorState* rnd) {
}
// Asking for memory sizes near signed/unsigned boundary (kMaxSignedSize)
// might work or not, depending on the amount of virtual memory.
+#ifndef DEBUGALLOCATION // debug allocation takes forever for huge allocs
for (size_t i = 0; i < 100; i++) {
void* p = NULL;
p = rnd->alloc(kMaxSignedSize + i);
@@ -518,6 +527,7 @@ static void TestHugeAllocations(AllocatorState* rnd) {
p = rnd->alloc(kMaxSignedSize - i);
if (p) free(p);
}
+#endif
// Check that ReleaseFreeMemory has no visible effect (aka, does not
// crash the test):
@@ -544,6 +554,7 @@ static void TestCalloc(size_t n, size_t s, bool ok) {
// This makes sure that reallocing a small number of bytes in either
// direction doesn't cause us to allocate new memory.
static void TestRealloc() {
+#ifndef DEBUGALLOCATION // debug alloc doesn't try to minimize reallocs
int start_sizes[] = { 100, 1000, 10000, 100000 };
int deltas[] = { 1, -2, 4, -8, 16, -32, 64, -128 };
@@ -562,6 +573,7 @@ static void TestRealloc() {
}
free(p);
}
+#endif
}
static void TestNewHandler() throw (std::bad_alloc) {
@@ -701,9 +713,11 @@ static void TestAlignmentForSize(int size) {
CHECK((p % sizeof(double)) == 0);
// Must have 16-byte alignment for large enough objects
+#ifndef DEBUGALLOCATION // debug allocation doesn't need to align like this
if (size >= 16) {
CHECK((p % 16) == 0);
}
+#endif
}
for (int i = 0; i < kNum; i++) {
free(ptrs[i]);
@@ -964,12 +978,14 @@ static int RunAllTests(int argc, char** argv) {
TestHugeAllocations(&rnd);
// Check that large allocations fail with NULL instead of crashing
+#ifndef DEBUGALLOCATION // debug allocation takes forever for huge allocs
fprintf(LOGSTREAM, "Testing out of memory\n");
for (int s = 0; ; s += (10<<20)) {
void* large_object = rnd.alloc(s);
if (large_object == NULL) break;
free(large_object);
}
+#endif
TestHugeThreadCache();
@@ -983,5 +999,16 @@ using testing::RunAllTests;
int main(int argc, char** argv) {
RunAllTests(argc, argv);
+ // Test tc_version()
+ fprintf(LOGSTREAM, "Testing tc_version()\n");
+ int major;
+ int minor;
+ const char* patch;
+ char mmp[64];
+ const char* human_version = tc_version(&major, &minor, &patch);
+ snprintf(mmp, sizeof(mmp), "%d.%d%s", major, minor, patch);
+ CHECK(!strcmp(PACKAGE_STRING, human_version));
+ CHECK(!strcmp(PACKAGE_VERSION, mmp));
+
fprintf(LOGSTREAM, "PASS\n");
}
diff --git a/src/thread_cache.cc b/src/thread_cache.cc
index 05e002c..fd44a70 100644
--- a/src/thread_cache.cc
+++ b/src/thread_cache.cc
@@ -41,15 +41,6 @@
using std::min;
using std::max;
-DEFINE_bool(tcmalloc_use_dynamic_thread_cache_sizes,
- EnvToBool("TCMALLOC_USE_DYNAMIC_THREAD_CACHE_SIZES", true),
- "When false, active threads will equally share "
- "FLAGS_tcmalloc_max_total_thread_cache_bytes and the freelists "
- "within each thread cache will have a max length of "
- "256. When on, active threads will compete for allocation of "
- "FLAGS_tcmalloc_max_total_thread_cache_bytes, and the max length "
- "of each freelist will change based on the usage pattern.");
-
DEFINE_int64(tcmalloc_max_total_thread_cache_bytes,
EnvToInt64("TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES", 16<<20),
"Bound on the total amount of bytes allocated to "
@@ -60,8 +51,6 @@ namespace tcmalloc {
static bool phinited = false;
-volatile bool ThreadCache::use_dynamic_cache_size_ =
- FLAGS_tcmalloc_use_dynamic_thread_cache_sizes;
volatile size_t ThreadCache::per_thread_cache_size_ = kMaxThreadCacheSize;
size_t ThreadCache::overall_thread_cache_size_ = kDefaultOverallThreadCacheSize;
ssize_t ThreadCache::unclaimed_cache_space_ = kDefaultOverallThreadCacheSize;
@@ -113,20 +102,16 @@ bool kernel_supports_tls = false; // be conservative
void ThreadCache::Init(pthread_t tid) {
size_ = 0;
- if (use_dynamic_cache_size_) {
- max_size_ = 0;
- IncreaseCacheLimitLocked();
- if (max_size_ == 0) {
- // There isn't enough memory to go around. Just give the minimum to
- // this thread.
- max_size_ = kMinThreadCacheSize;
-
- // Take unclaimed_cache_space_ negative.
- unclaimed_cache_space_ -= kMinThreadCacheSize;
- ASSERT(unclaimed_cache_space_ < 0);
- }
- } else {
- max_size_ = per_thread_cache_size_;
+ max_size_ = 0;
+ IncreaseCacheLimitLocked();
+ if (max_size_ == 0) {
+ // There isn't enough memory to go around. Just give the minimum to
+ // this thread.
+ max_size_ = kMinThreadCacheSize;
+
+ // Take unclaimed_cache_space_ negative.
+ unclaimed_cache_space_ -= kMinThreadCacheSize;
+ ASSERT(unclaimed_cache_space_ < 0);
}
next_ = NULL;
@@ -158,8 +143,6 @@ void* ThreadCache::FetchFromCentralCache(size_t cl, size_t byte_size) {
ASSERT(list->empty());
const int batch_size = Static::sizemap()->num_objects_to_move(cl);
- // If !use_dynamic_cache_size_, batch_size should always be less than
- // max_length() (which will be kMaxFreeListLength).
const int num_to_move = min<int>(list->max_length(), batch_size);
void *start, *end;
int fetch_count = Static::central_cache()[cl].RemoveRange(
@@ -171,25 +154,23 @@ void* ThreadCache::FetchFromCentralCache(size_t cl, size_t byte_size) {
list->PushRange(fetch_count, SLL_Next(start), end);
}
- if (use_dynamic_cache_size_) {
- // Increase max length slowly up to batch_size. After that,
- // increase by batch_size in one shot so that the length is a
- // multiple of batch_size.
- if (list->max_length() < batch_size) {
- list->set_max_length(list->max_length() + 1);
- } else {
- // Don't let the list get too long. In 32 bit builds, the length
- // is represented by a 16 bit int, so we need to watch out for
- // integer overflow.
- int new_length = min<int>(list->max_length() + batch_size,
- kMaxDynamicFreeListLength);
- // The list's max_length must always be a multiple of batch_size,
- // and kMaxDynamicFreeListLength is not necessarily a multiple
- // of batch_size.
- new_length -= new_length % batch_size;
- ASSERT(new_length % batch_size == 0);
- list->set_max_length(new_length);
- }
+ // Increase max length slowly up to batch_size. After that,
+ // increase by batch_size in one shot so that the length is a
+ // multiple of batch_size.
+ if (list->max_length() < batch_size) {
+ list->set_max_length(list->max_length() + 1);
+ } else {
+ // Don't let the list get too long. In 32 bit builds, the length
+ // is represented by a 16 bit int, so we need to watch out for
+ // integer overflow.
+ int new_length = min<int>(list->max_length() + batch_size,
+ kMaxDynamicFreeListLength);
+ // The list's max_length must always be a multiple of batch_size,
+ // and kMaxDynamicFreeListLength is not necessarily a multiple
+ // of batch_size.
+ new_length -= new_length % batch_size;
+ ASSERT(new_length % batch_size == 0);
+ list->set_max_length(new_length);
}
return start;
}
@@ -198,10 +179,6 @@ void ThreadCache::ListTooLong(FreeList* list, size_t cl) {
const int batch_size = Static::sizemap()->num_objects_to_move(cl);
ReleaseToCentralCache(list, cl, batch_size);
- if (!use_dynamic_cache_size_) {
- return;
- }
-
// If the list is too long, we need to transfer some number of
// objects to the central cache. Ideally, we would transfer
// num_objects_to_move, so the code below tries to make max_length
@@ -259,27 +236,23 @@ void ThreadCache::Scavenge() {
const int drop = (lowmark > 1) ? lowmark/2 : 1;
ReleaseToCentralCache(list, cl, drop);
- if (use_dynamic_cache_size_) {
- // Shrink the max length if it isn't used. Only shrink down to
- // batch_size -- if the thread was active enough to get the max_length
- // above batch_size, it will likely be that active again. If
- // max_length shinks below batch_size, the thread will have to
- // go through the slow-start behavior again. The slow-start is useful
- // mainly for threads that stay relatively idle for their entire
- // lifetime.
- const int batch_size = Static::sizemap()->num_objects_to_move(cl);
- if (list->max_length() > batch_size) {
- list->set_max_length(
- max<int>(list->max_length() - batch_size, batch_size));
- }
+ // Shrink the max length if it isn't used. Only shrink down to
+ // batch_size -- if the thread was active enough to get the max_length
+ // above batch_size, it will likely be that active again. If
+ // max_length shinks below batch_size, the thread will have to
+ // go through the slow-start behavior again. The slow-start is useful
+ // mainly for threads that stay relatively idle for their entire
+ // lifetime.
+ const int batch_size = Static::sizemap()->num_objects_to_move(cl);
+ if (list->max_length() > batch_size) {
+ list->set_max_length(
+ max<int>(list->max_length() - batch_size, batch_size));
}
}
list->clear_lowwatermark();
}
- if (use_dynamic_cache_size_) {
- IncreaseCacheLimit();
- }
+ IncreaseCacheLimit();
// int64 finish = CycleClock::Now();
// CycleTimer ct;
@@ -414,9 +387,6 @@ ThreadCache* ThreadCache::NewHeap(pthread_t tid) {
}
thread_heaps_ = heap;
thread_heap_count_++;
- if (!use_dynamic_cache_size_) {
- RecomputePerThreadCacheSize();
- }
return heap;
}
@@ -470,10 +440,6 @@ void ThreadCache::DeleteCache(ThreadCache* heap) {
if (next_memory_steal_ == NULL) next_memory_steal_ = thread_heaps_;
unclaimed_cache_space_ += heap->max_size_;
- if (!use_dynamic_cache_size_) {
- RecomputePerThreadCacheSize();
- }
-
threadcache_allocator.Delete(heap);
}
@@ -489,17 +455,10 @@ void ThreadCache::RecomputePerThreadCacheSize() {
double ratio = space / max<double>(1, per_thread_cache_size_);
size_t claimed = 0;
for (ThreadCache* h = thread_heaps_; h != NULL; h = h->next_) {
- if (use_dynamic_cache_size_) {
- // Don't circumvent the slow-start growth of max_size_ by increasing the
- // total cache size.
- if (ratio < 1.0) {
+ // Increasing the total cache size should not circumvent the
+ // slow-start growth of max_size_.
+ if (ratio < 1.0) {
h->max_size_ = static_cast<size_t>(h->max_size_ * ratio);
- }
- } else {
- // Don't try to be clever and multiply by 'ratio' because rounding
- // errors will eventually cause long-lived threads to have zero
- // max_size_.
- h->max_size_ = space;
}
claimed += h->max_size_;
}
@@ -551,8 +510,4 @@ void ThreadCache::set_overall_thread_cache_size(size_t new_size) {
RecomputePerThreadCacheSize();
}
-void ThreadCache::set_use_dynamic_thread_cache_size(bool use_dynamic) {
- use_dynamic_cache_size_ = use_dynamic;
-}
-
} // namespace tcmalloc
diff --git a/src/thread_cache.h b/src/thread_cache.h
index e7ce0c4..4c6a233 100644
--- a/src/thread_cache.h
+++ b/src/thread_cache.h
@@ -121,15 +121,6 @@ class ThreadCache {
return overall_thread_cache_size_;
}
- // Turn on/off dynamic sizing of the thread caches and the freelists
- // within those thread caches. When off, threads will equally share
- // the overall_thread_cache_size() and the freelists will have a
- // max_length() of kMaxFreeListLength. When on, threads will compete
- // for allocation of overall_thread_cache_size() and the max_length()
- // of each freelist will change based on the usage pattern.
- // REQUIRES: Static::pageheap lock is held.
- static void set_use_dynamic_thread_cache_size(bool use_dynamic);
-
private:
class FreeList {
private:
@@ -168,19 +159,13 @@ class ThreadCache {
// Return the maximum length of the list.
size_t max_length() const {
- if (use_dynamic_cache_size_) {
- return max_length_;
- } else {
- return kMaxFreeListLength;
- }
+ return max_length_;
}
// Set the maximum length of the list. If 'new_max' > length(), the
// client is responsible for removing objects from the list.
void set_max_length(size_t new_max) {
- if (use_dynamic_cache_size_) {
- max_length_ = new_max;
- }
+ max_length_ = new_max;
}
// Return the number of times that length() has gone over max_length().
@@ -301,15 +286,9 @@ class ThreadCache {
// Global per-thread cache size. Writes are protected by
// Static::pageheap_lock. Reads are done without any locking, which should be
// fine as long as size_t can be written atomically and we don't place
- // invariants between this variable and other pieces of state. See
- // use_dynamic_cache_size_ below.
+ // invariants between this variable and other pieces of state.
static volatile size_t per_thread_cache_size_;
- // If true, threads use a dynamic max_size_ and dynamic freelist lengths.
- // If false, threads each get a max_size_ equal to per_thread_cache_size_,
- // and the freelist lengths are statically sized.
- static volatile bool use_dynamic_cache_size_;
-
// Represents overall_thread_cache_size_ minus the sum of max_size_
// across all ThreadCaches. Protected by Static::pageheap_lock.
static ssize_t unclaimed_cache_space_;
diff --git a/src/windows/config.h b/src/windows/config.h
index 52b86a7..0f4daff 100644
--- a/src/windows/config.h
+++ b/src/windows/config.h
@@ -28,6 +28,9 @@
/* Define to 1 if you have the <conflict-signal.h> header file. */
#undef HAVE_CONFLICT_SIGNAL_H
+/* Define to 1 if you have the <cygwin/signal.h> header file. */
+#undef HAVE_CYGWIN_SIGNAL_H
+
/* Define to 1 if you have the declaration of `cfree', and to 0 if you don't.
*/
#undef HAVE_DECL_CFREE
@@ -100,6 +103,9 @@
/* define if the compiler implements namespaces */
#define HAVE_NAMESPACES 1
+/* Define to 1 if you have the <poll.h> header file. */
+#undef HAVE_POLL_H
+
/* define if libc has program_invocation_name */
#undef HAVE_PROGRAM_INVOCATION_NAME
@@ -179,22 +185,22 @@
#undef NO_MINUS_C_MINUS_O
/* Name of package */
-#undef PACKAGE
+#define PACKAGE "google-perftools"
/* Define to the address where bug reports for this package should be sent. */
-#undef PACKAGE_BUGREPORT
+#define PACKAGE_BUGREPORT "opensource@google.com"
/* Define to the full name of this package. */
-#undef PACKAGE_NAME
+#define PACKAGE_NAME "google-perftools"
/* Define to the full name and version of this package. */
-#undef PACKAGE_STRING
+#define PACKAGE_STRING "google-perftools 1.4"
/* Define to the one symbol short name of this package. */
-#undef PACKAGE_TARNAME
+#define PACKAGE_TARNAME "google-perftools"
/* Define to the version of this package. */
-#undef PACKAGE_VERSION
+#define PACKAGE_VERSION "1.4"
/* How to access the PC from a struct ucontext */
#undef PC_FROM_UCONTEXT
@@ -252,6 +258,9 @@
# define _WIN32_WINNT 0x0400
#endif
+// We want to make sure not to ever try to #include heap-checker.h
+#define NO_HEAP_CHECK 1
+
// TODO(csilvers): include windows/port.h in every relevant source file instead?
#include "windows/port.h"
diff --git a/src/windows/google/tcmalloc.h b/src/windows/google/tcmalloc.h
index 700609a..9c0c5c6 100644
--- a/src/windows/google/tcmalloc.h
+++ b/src/windows/google/tcmalloc.h
@@ -35,6 +35,12 @@
#ifndef TCMALLOC_TCMALLOC_H_
#define TCMALLOC_TCMALLOC_H_
+// Define the version number so folks can check against it
+#define TC_VERSION_MAJOR 1
+#define TC_VERSION_MINOR 4
+#define TC_VERSION_PATCH ""
+#define TC_VERSION_STRING "google-perftools 1.4"
+
// __THROW is defined in glibc systems. It means, counter-intuitively,
// "This function will never throw an exception." It's an optional
// optimization tool, but we may need to use it to match glibc prototypes.
@@ -42,37 +48,57 @@
# define __THROW /* __THROW is just an optimization, so ok to make it "" */
#endif
+
#include <stdlib.h> // for struct mallinfo, if it's defined
+// Annoying stuff for windows -- makes sure clients can import these functions
+#ifndef PERFTOOLS_DLL_DECL
+# ifdef _WIN32
+# define PERFTOOLS_DLL_DECL __declspec(dllimport)
+# else
+# define PERFTOOLS_DLL_DECL
+# endif
+#endif
+
#ifdef __cplusplus
#include <new> // for nothrow_t
extern "C" {
#endif
- void* tc_malloc(size_t size) __THROW;
- void tc_free(void* ptr) __THROW;
- void* tc_realloc(void* ptr, size_t size) __THROW;
- void* tc_calloc(size_t nmemb, size_t size) __THROW;
- void tc_cfree(void* ptr) __THROW;
+ // Returns a human-readable version string. If major, minor,
+ // and/or patch are not NULL, they are set to the major version,
+ // minor version, and patch-code (a string, usually "").
+ PERFTOOLS_DLL_DECL const char* tc_version(int* major, int* minor,
+ const char** patch) __THROW;
+
+ PERFTOOLS_DLL_DECL void* tc_malloc(size_t size) __THROW;
+ PERFTOOLS_DLL_DECL void tc_free(void* ptr) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_realloc(void* ptr, size_t size) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_calloc(size_t nmemb, size_t size) __THROW;
+ PERFTOOLS_DLL_DECL void tc_cfree(void* ptr) __THROW;
- void* tc_memalign(size_t __alignment, size_t __size) __THROW;
- int tc_posix_memalign(void** ptr, size_t align, size_t size) __THROW;
- void* tc_valloc(size_t __size) __THROW;
- void* tc_pvalloc(size_t __size) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_memalign(size_t __alignment,
+ size_t __size) __THROW;
+ PERFTOOLS_DLL_DECL int tc_posix_memalign(void** ptr,
+ size_t align, size_t size) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_valloc(size_t __size) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_pvalloc(size_t __size) __THROW;
- void tc_malloc_stats(void) __THROW;
- int tc_mallopt(int cmd, int value) __THROW;
+ PERFTOOLS_DLL_DECL void tc_malloc_stats(void) __THROW;
+ PERFTOOLS_DLL_DECL int tc_mallopt(int cmd, int value) __THROW;
#if 0
- struct mallinfo tc_mallinfo(void) __THROW;
+ PERFTOOLS_DLL_DECL struct mallinfo tc_mallinfo(void) __THROW;
#endif
#ifdef __cplusplus
- void* tc_new(size_t size);
- void tc_delete(void* p) __THROW;
- void* tc_newarray(size_t size);
- void tc_deletearray(void* p) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_new(size_t size);
+ PERFTOOLS_DLL_DECL void tc_delete(void* p) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_newarray(size_t size);
+ PERFTOOLS_DLL_DECL void tc_deletearray(void* p) __THROW;
- void* tc_new_nothrow(size_t size, const std::nothrow_t&) __THROW;
- void* tc_newarray_nothrow(size_t size, const std::nothrow_t&) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_new_nothrow(size_t size,
+ const std::nothrow_t&) __THROW;
+ PERFTOOLS_DLL_DECL void* tc_newarray_nothrow(size_t size,
+ const std::nothrow_t&) __THROW;
}
#endif
diff --git a/src/windows/patch_functions.cc b/src/windows/patch_functions.cc
index 3a20a62..d0e54ff 100644
--- a/src/windows/patch_functions.cc
+++ b/src/windows/patch_functions.cc
@@ -132,15 +132,24 @@ class LibcInfo {
memset(this, 0, sizeof(*this)); // easiest way to initialize the array
}
bool SameAs(const LibcInfo& that) const {
- return (module_base_address_ == that.module_base_address_ &&
+ return (is_valid() &&
+ module_base_address_ == that.module_base_address_ &&
module_base_size_ == that.module_base_size_);
}
- bool patched() const { return module_name_[0] != '\0'; }
- const char* module_name() const { return module_name_; }
+ bool SameAsME32(const MODULEENTRY32& me32) const {
+ return (is_valid() &&
+ module_base_address_ == me32.modBaseAddr &&
+ module_base_size_ == me32.modBaseSize);
+ }
+ bool patched() const { return is_valid() && module_name_[0] != '\0'; }
+ const char* module_name() const { return is_valid() ? module_name_ : ""; }
+
+ void set_is_valid(bool b) { is_valid_ = b; }
// These shouldn't have to be public, since only subclasses of
// LibcInfo need it, but they do. Maybe something to do with
// templates. Shrug.
+ bool is_valid() const { return is_valid_; }
GenericFnPtr windows_fn(int ifunction) const {
return windows_fn_[ifunction];
}
@@ -148,14 +157,13 @@ class LibcInfo {
// Populates all the windows_fn_[] vars based on our module info.
// Returns false if windows_fn_ is all NULL's, because there's
// nothing to patch. Also populates the me32 info.
- bool PopulateWindowsFn(MODULEENTRY32 me32);
-
- static int num_patched_modules;
+ bool PopulateWindowsFn(const MODULEENTRY32& me32);
protected:
void CopyFrom(const LibcInfo& that) {
if (this == &that)
return;
+ this->is_valid_ = that.is_valid_;
memcpy(this->windows_fn_, that.windows_fn_, sizeof(windows_fn_));
this->module_base_address_ = that.module_base_address_;
this->module_base_size_ = that.module_base_size_;
@@ -192,6 +200,11 @@ class LibcInfo {
// patch-specific subclasses, below.
GenericFnPtr windows_fn_[kNumFunctions];
+ // This is set to true when this structure is initialized (because
+ // we're patching a new library) and set to false when it's
+ // uninitialized (because we've freed that library).
+ bool is_valid_;
+
const void *module_base_address_;
size_t module_base_size_;
char module_name_[MAX_MODULE_NAME32 + 1];
@@ -263,7 +276,7 @@ class WindowsInfo {
// for pre-XP systems?
enum {
kHeapAlloc, kHeapFree, kVirtualAllocEx, kVirtualFreeEx,
- kMapViewOfFileEx, kUnmapViewOfFile, kLoadLibraryExW,
+ kMapViewOfFileEx, kUnmapViewOfFile, kLoadLibraryExW, kFreeLibrary,
kNumFunctions
};
@@ -299,6 +312,7 @@ class WindowsInfo {
static HMODULE WINAPI Perftools_LoadLibraryExW(LPCWSTR lpFileName,
HANDLE hFile,
DWORD dwFlags);
+ static BOOL WINAPI Perftools_FreeLibrary(HMODULE hLibModule);
};
// If you run out, just add a few more to the array. You'll also need
@@ -318,8 +332,6 @@ static LibcInfo* module_libcs[] = {
};
static WindowsInfo main_executable_windows;
-/*static*/ int LibcInfo::num_patched_modules;
-
const char* const LibcInfo::function_name_[] = {
"malloc", "free", "realloc", "calloc",
kMangledNew, kMangledNewArray, kMangledDelete, kMangledDeleteArray,
@@ -404,9 +416,10 @@ const GenericFnPtr LibcInfoWithPatchFunctions<T>::perftools_fn_[] = {
{ "MapViewOfFileEx", NULL, NULL, (GenericFnPtr)&Perftools_MapViewOfFileEx },
{ "UnmapViewOfFile", NULL, NULL, (GenericFnPtr)&Perftools_UnmapViewOfFile },
{ "LoadLibraryExW", NULL, NULL, (GenericFnPtr)&Perftools_LoadLibraryExW },
+ { "FreeLibrary", NULL, NULL, (GenericFnPtr)&Perftools_FreeLibrary },
};
-bool LibcInfo::PopulateWindowsFn(MODULEENTRY32 me32) {
+bool LibcInfo::PopulateWindowsFn(const MODULEENTRY32& me32) {
module_base_address_ = me32.modBaseAddr;
module_base_size_ = me32.modBaseSize;
strcpy(module_name_, me32.szModule);
@@ -448,9 +461,12 @@ bool LibcInfo::PopulateWindowsFn(MODULEENTRY32 me32) {
// as another module that we've already loaded. In that case, we
// need to set our windows_fn to NULL, to avoid double-patching.
for (int ifn = 0; ifn < kNumFunctions; ifn++) {
- for (int imod = 0; imod < LibcInfo::num_patched_modules; imod++) {
- if (this->windows_fn(ifn) == module_libcs[imod]->windows_fn(ifn))
+ for (int imod = 0;
+ imod < sizeof(module_libcs)/sizeof(*module_libcs); imod++) {
+ if (module_libcs[imod]->is_valid() &&
+ this->windows_fn(ifn) == module_libcs[imod]->windows_fn(ifn)) {
windows_fn_[ifn] = NULL;
+ }
}
}
@@ -483,6 +499,7 @@ bool LibcInfoWithPatchFunctions<T>::Patch(const LibcInfo& me_info) {
PreamblePatcher::Patch(windows_fn_[i], perftools_fn_[i],
&origstub_fn_[i]));
}
+ set_is_valid(true);
return true;
}
@@ -497,6 +514,7 @@ void LibcInfoWithPatchFunctions<T>::Unpatch() {
(void*)perftools_fn_[i],
(void*)origstub_fn_[i]));
}
+ set_is_valid(false);
}
void WindowsInfo::Patch() {
@@ -526,35 +544,35 @@ void WindowsInfo::Unpatch() {
}
}
- // You should hold the patch_all_modules_lock when calling this.
-void PatchOneModuleLocked(const LibcInfo& me_info, bool still_loaded[]) {
- // First, check to see if we already have info on this module
- for (int i = 0; i < LibcInfo::num_patched_modules; i++) {
+// You should hold the patch_all_modules_lock when calling this.
+void PatchOneModuleLocked(const LibcInfo& me_info) {
+ // Double-check we haven't seen this module before.
+ for (int i = 0; i < sizeof(module_libcs)/sizeof(*module_libcs); i++) {
if (module_libcs[i]->SameAs(me_info)) {
- still_loaded[i] = true;
- return;
+ fprintf(stderr, "%s:%d: FATAL ERROR: %s double-patched somehow.\n",
+ __FILE__, __LINE__, module_libcs[i]->module_name());
+ CHECK(false);
}
}
// If we don't already have info on this module, let's add it. This
// is where we're sad that each libcX has a different type, so we
// can't use an array; instead, we have to use a switch statement.
// Patch() returns false if there were no libc functions in the module.
- switch (LibcInfo::num_patched_modules) {
- case 0: if (!libc1.Patch(me_info)) return; break;
- case 1: if (!libc2.Patch(me_info)) return; break;
- case 2: if (!libc3.Patch(me_info)) return; break;
- case 3: if (!libc4.Patch(me_info)) return; break;
- case 4: if (!libc5.Patch(me_info)) return; break;
- case 5: if (!libc6.Patch(me_info)) return; break;
- case 6: if (!libc7.Patch(me_info)) return; break;
- case 7: if (!libc8.Patch(me_info)) return; break;
- default:
- printf("ERROR: Too many modules containing libc in this executable\n");
- CHECK_LE(LibcInfo::num_patched_modules,
- sizeof(module_libcs)/sizeof(*module_libcs));
+ for (int i = 0; i < sizeof(module_libcs)/sizeof(*module_libcs); i++) {
+ if (!module_libcs[i]->is_valid()) { // found an empty spot to add!
+ switch (i) {
+ case 0: libc1.Patch(me_info); return;
+ case 1: libc2.Patch(me_info); return;
+ case 2: libc3.Patch(me_info); return;
+ case 3: libc4.Patch(me_info); return;
+ case 4: libc5.Patch(me_info); return;
+ case 5: libc6.Patch(me_info); return;
+ case 6: libc7.Patch(me_info); return;
+ case 7: libc8.Patch(me_info); return;
+ }
+ }
}
- // If we get here, we successfully patched this module.
- LibcInfo::num_patched_modules++;
+ printf("ERROR: Too many modules containing libc in this executable\n");
}
void PatchMainExecutableLocked() {
@@ -573,10 +591,11 @@ static SpinLock patch_all_modules_lock(SpinLock::LINKER_INITIALIZED);
// Iterates over all the modules currently loaded by the executable,
// and makes sure they're all patched. For ones that aren't, we patch
-// them in. (We also check that every module we had patched in the
-// past is still loaded, and complain loudly if not.)
+// them in. We also check that every module we had patched in the
+// past is still loaded, and update internal data structures if so.
void PatchAllModules() {
std::vector<LibcInfo*> modules;
+ bool still_loaded[sizeof(module_libcs)/sizeof(*module_libcs)] = {};
HANDLE hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE |
TH32CS_SNAPMODULE32,
@@ -586,11 +605,21 @@ void PatchAllModules() {
me32.dwSize = sizeof(me32);
if (Module32First(hModuleSnap, &me32)) {
do {
- LibcInfo* libc_info = new LibcInfo;
- if (libc_info->PopulateWindowsFn(me32))
- modules.push_back(libc_info);
- else
- delete libc_info;
+ bool module_already_loaded = false;
+ for (int i = 0; i < sizeof(module_libcs)/sizeof(*module_libcs); i++) {
+ if (module_libcs[i]->SameAsME32(me32)) {
+ still_loaded[i] = true;
+ module_already_loaded = true;
+ break;
+ }
+ }
+ if (!module_already_loaded) {
+ LibcInfo* libc_info = new LibcInfo;
+ if (libc_info->PopulateWindowsFn(me32))
+ modules.push_back(libc_info);
+ else // means module has no libc routines
+ delete libc_info;
+ }
} while (Module32Next(hModuleSnap, &me32));
}
CloseHandle(hModuleSnap);
@@ -599,29 +628,20 @@ void PatchAllModules() {
// Now do the actual patching.
{
SpinLockHolder h(&patch_all_modules_lock);
- // We want to make sure every module we have patch-info about is
- // still loaded. Otherwise, there's danger that the module could
- // later be reloaded at the same address, and we wouldn't repatch
- // it. This code isn't able to handle shrinking the number of libcs
- // at present, but if it becomes necessary then I would recommend
- // compacting the arrays and repatching as needed. You must do all
- // of this inside a FreeLibrary hook.
- int old_num_libcs = LibcInfo::num_patched_modules;
- bool still_loaded[sizeof(module_libcs)/sizeof(*module_libcs)] = {};
+ // First, delete the modules that are no longer loaded. (We go first
+ // so we can try to open up space for the new modules we need to load.)
+ for (int i = 0; i < sizeof(module_libcs)/sizeof(*module_libcs); i++) {
+ if (!still_loaded[i]) {
+ // We could call Unpatch() here, but why bother? The module
+ // has gone away, so nobody is going to call into it anyway.
+ module_libcs[i]->set_is_valid(false);
+ }
+ }
+ // Now, add in new modules that we need to load.
for (std::vector<LibcInfo*>::iterator it = modules.begin();
it != modules.end(); ++it) {
- PatchOneModuleLocked(**it, still_loaded); // updates num_patched_modules
- }
-
- // Check the still_loaded array, which was updated in PatchOneModule.
- // If any old libc is not still loaded, scream bloody murder.
- for (int i = 0; i < old_num_libcs; i++) {
- if (!still_loaded[i]) {
- fprintf(stderr, "%s:%d: FATAL ERROR: %s unloaded after I patched it.\n",
- __FILE__, __LINE__, module_libcs[i]->module_name());
- CHECK(false);
- }
+ PatchOneModuleLocked(**it); // updates num_patched_modules
}
// Now that we've dealt with the modules (dlls), update the main
@@ -676,14 +696,14 @@ void UnpatchWindowsFunctions() {
// Who knows, it may help avoid weird bugs in some situations.
main_executable_windows.Unpatch();
main_executable.Unpatch();
- if (LibcInfo::num_patched_modules-- > 0) libc1.Unpatch();
- if (LibcInfo::num_patched_modules-- > 0) libc2.Unpatch();
- if (LibcInfo::num_patched_modules-- > 0) libc3.Unpatch();
- if (LibcInfo::num_patched_modules-- > 0) libc4.Unpatch();
- if (LibcInfo::num_patched_modules-- > 0) libc5.Unpatch();
- if (LibcInfo::num_patched_modules-- > 0) libc6.Unpatch();
- if (LibcInfo::num_patched_modules-- > 0) libc7.Unpatch();
- if (LibcInfo::num_patched_modules-- > 0) libc8.Unpatch();
+ if (libc1.is_valid()) libc1.Unpatch();
+ if (libc2.is_valid()) libc2.Unpatch();
+ if (libc3.is_valid()) libc3.Unpatch();
+ if (libc4.is_valid()) libc4.Unpatch();
+ if (libc5.is_valid()) libc5.Unpatch();
+ if (libc6.is_valid()) libc6.Unpatch();
+ if (libc7.is_valid()) libc7.Unpatch();
+ if (libc8.is_valid()) libc8.Unpatch();
}
#endif
@@ -910,3 +930,10 @@ HMODULE WINAPI WindowsInfo::Perftools_LoadLibraryExW(LPCWSTR lpFileName,
PatchAllModules(); // this will patch any newly loaded libraries
return rv;
}
+
+BOOL WINAPI WindowsInfo::Perftools_FreeLibrary(HMODULE hLibModule) {
+ BOOL rv = ((BOOL (WINAPI *)(HMODULE))
+ function_info_[kFreeLibrary].origstub_fn)(hLibModule);
+ PatchAllModules(); // this will fix up the list of patched libraries
+ return rv;
+}
diff --git a/src/windows/port.h b/src/windows/port.h
index 592f2ae..66745d1 100644
--- a/src/windows/port.h
+++ b/src/windows/port.h
@@ -1,10 +1,10 @@
/* Copyright (c) 2007, Google Inc.
* All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
@@ -14,7 +14,7 @@
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -54,6 +54,7 @@
#endif
#include <windows.h>
#include <io.h> /* because we so often use open/close/etc */
+#include <process.h> /* for _getpid */
#include <stdarg.h> /* for va_list */
#include <stdio.h> /* need this to override stdio's (v)snprintf */
@@ -99,6 +100,7 @@ enum { PTHREAD_ONCE_INIT = 0 }; // important that this be 0! for SpinLock
#define pthread_self GetCurrentThreadId
#define pthread_equal(pthread_t_1, pthread_t_2) ((pthread_t_1)==(pthread_t_2))
+#ifdef __cplusplus
// This replaces maybe_threads.{h,cc}
extern pthread_key_t PthreadKeyCreate(void (*destr_fn)(void*)); // in port.cc
#define perftools_pthread_key_create(pkey, destr_fn) \
@@ -115,6 +117,7 @@ inline void* perftools_pthread_getspecific(DWORD key) {
#define perftools_pthread_once(once, init) do { \
if (InterlockedCompareExchange(once, 1, 0) == 0) (init)(); \
} while (0)
+#endif // __cplusplus
#endif // HAVE_PTHREAD
// __declspec(thread) isn't usable in a dll opened via LoadLibrary().
@@ -277,6 +280,15 @@ enum { STDIN_FILENO = 0, STDOUT_FILENO = 1, STDERR_FILENO = 2 };
// ----------------------------------- SYSTEM/PROCESS
typedef int pid_t;
#define getpid _getpid
+#define getppid() (0)
+
+// Handle case when poll is used to simulate sleep.
+#define poll(r, w, t) \
+ do { \
+ assert(r == 0); \
+ assert(w == 0); \
+ Sleep(t); \
+ } while(0)
extern PERFTOOLS_DLL_DECL int getpagesize(); // in port.cc
diff --git a/src/windows/preamble_patcher.cc b/src/windows/preamble_patcher.cc
index 8b403d1..62b6e7f 100644
--- a/src/windows/preamble_patcher.cc
+++ b/src/windows/preamble_patcher.cc
@@ -125,7 +125,8 @@ SideStepError PreamblePatcher::RawPatchWithStubAndProtections(
// MAX_PREAMBLE_STUB_SIZE bytes of target_function
DWORD old_target_function_protect = 0;
BOOL succeeded = ::VirtualProtect(reinterpret_cast<void*>(target_function),
- MAX_PREAMBLE_STUB_SIZE, PAGE_READWRITE,
+ MAX_PREAMBLE_STUB_SIZE,
+ PAGE_EXECUTE_READWRITE,
&old_target_function_protect);
if (!succeeded) {
SIDESTEP_ASSERT(false && "Failed to make page containing target function "
@@ -206,8 +207,8 @@ SideStepError PreamblePatcher::RawPatch(void* target_function,
// Execution Prevention) which will cause an exception if code is executed
// from a page on which you do not have read access.
DWORD old_stub_protect = 0;
- BOOL succeeded = VirtualProtect(preamble_stub, MAX_PREAMBLE_STUB_SIZE,
- PAGE_EXECUTE_READWRITE, &old_stub_protect);
+ BOOL succeeded = ::VirtualProtect(preamble_stub, MAX_PREAMBLE_STUB_SIZE,
+ PAGE_EXECUTE_READWRITE, &old_stub_protect);
if (!succeeded) {
SIDESTEP_ASSERT(false &&
"Failed to make page preamble stub read-write-execute.");
diff --git a/vsprojects/addr2line-pdb/addr2line-pdb.vcproj b/vsprojects/addr2line-pdb/addr2line-pdb.vcproj
index c5ae27b..a4ffae4 100755
--- a/vsprojects/addr2line-pdb/addr2line-pdb.vcproj
+++ b/vsprojects/addr2line-pdb/addr2line-pdb.vcproj
@@ -25,7 +25,6 @@
RuntimeLibrary="5"
UsePrecompiledHeader="0"
WarningLevel="3"
- Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -71,7 +70,6 @@
RuntimeLibrary="4"
UsePrecompiledHeader="0"
WarningLevel="3"
- Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/vsprojects/addressmap_unittest/addressmap_unittest.vcproj b/vsprojects/addressmap_unittest/addressmap_unittest.vcproj
index 10930b0..7dd8657 100755
--- a/vsprojects/addressmap_unittest/addressmap_unittest.vcproj
+++ b/vsprojects/addressmap_unittest/addressmap_unittest.vcproj
@@ -25,7 +25,6 @@
RuntimeLibrary="5"
UsePrecompiledHeader="0"
WarningLevel="3"
- Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -70,7 +69,6 @@
RuntimeLibrary="4"
UsePrecompiledHeader="0"
WarningLevel="3"
- Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/vsprojects/frag_unittest/frag_unittest.vcproj b/vsprojects/frag_unittest/frag_unittest.vcproj
index b34818e..8e85253 100755
--- a/vsprojects/frag_unittest/frag_unittest.vcproj
+++ b/vsprojects/frag_unittest/frag_unittest.vcproj
@@ -25,7 +25,6 @@
RuntimeLibrary="5"
UsePrecompiledHeader="0"
WarningLevel="3"
- Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -71,7 +70,6 @@
RuntimeLibrary="4"
UsePrecompiledHeader="0"
WarningLevel="3"
- Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj b/vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj
index 5f2fecc..3755fb0 100755
--- a/vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj
+++ b/vsprojects/libtcmalloc_minimal/libtcmalloc_minimal.vcproj
@@ -25,7 +25,6 @@
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="3"
- Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -71,7 +70,6 @@
RuntimeLibrary="0"
UsePrecompiledHeader="0"
WarningLevel="3"
- Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -166,6 +164,23 @@
</FileConfiguration>
</File>
<File
+ RelativePath="..\..\src\symbolize.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
RelativePath="..\..\src\windows\ia32_modrm_map.cc">
<FileConfiguration
Name="Debug|Win32">
@@ -620,6 +635,9 @@
RelativePath="..\..\src\heap-profile-table.h">
</File>
<File
+ RelativePath="..\..\src\symbolize.h">
+ </File>
+ <File
RelativePath="..\..\src\google\heap-profiler.h">
</File>
<File
@@ -710,7 +728,7 @@
RelativePath="..\..\src\stacktrace_config.h">
</File>
<File
- RelativePath="..\..\src\stacktrace_win32-inl.h.h">
+ RelativePath="..\..\src\stacktrace_win32-inl.h">
</File>
<File
RelativePath="..\..\src\stack_trace_table.h">
diff --git a/vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj b/vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj
index 165b9c6..85fe7f7 100755
--- a/vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj
+++ b/vsprojects/low_level_alloc_unittest/low_level_alloc_unittest.vcproj
@@ -25,7 +25,6 @@
RuntimeLibrary="5"
UsePrecompiledHeader="0"
WarningLevel="3"
- Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -70,7 +69,6 @@
RuntimeLibrary="4"
UsePrecompiledHeader="0"
WarningLevel="3"
- Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/vsprojects/malloc_extension_test/malloc_extension_test.vcproj b/vsprojects/malloc_extension_test/malloc_extension_test.vcproj
index 378d686..ce15411 100755
--- a/vsprojects/malloc_extension_test/malloc_extension_test.vcproj
+++ b/vsprojects/malloc_extension_test/malloc_extension_test.vcproj
@@ -25,7 +25,6 @@
RuntimeLibrary="5"
UsePrecompiledHeader="0"
WarningLevel="3"
- Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -70,7 +69,6 @@
RuntimeLibrary="4"
UsePrecompiledHeader="0"
WarningLevel="3"
- Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/vsprojects/markidle_unittest/markidle_unittest.vcproj b/vsprojects/markidle_unittest/markidle_unittest.vcproj
index f029400..701a8cb 100755
--- a/vsprojects/markidle_unittest/markidle_unittest.vcproj
+++ b/vsprojects/markidle_unittest/markidle_unittest.vcproj
@@ -25,7 +25,6 @@
RuntimeLibrary="5"
UsePrecompiledHeader="0"
WarningLevel="3"
- Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -71,7 +70,6 @@
RuntimeLibrary="4"
UsePrecompiledHeader="0"
WarningLevel="3"
- Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/vsprojects/nm-pdb/nm-pdb.vcproj b/vsprojects/nm-pdb/nm-pdb.vcproj
index e922297..5982e3c 100755
--- a/vsprojects/nm-pdb/nm-pdb.vcproj
+++ b/vsprojects/nm-pdb/nm-pdb.vcproj
@@ -25,7 +25,6 @@
RuntimeLibrary="5"
UsePrecompiledHeader="0"
WarningLevel="3"
- Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -71,7 +70,6 @@
RuntimeLibrary="4"
UsePrecompiledHeader="0"
WarningLevel="3"
- Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/vsprojects/packed-cache_test/packed-cache_test.vcproj b/vsprojects/packed-cache_test/packed-cache_test.vcproj
index e0b242b..908fe8f 100755
--- a/vsprojects/packed-cache_test/packed-cache_test.vcproj
+++ b/vsprojects/packed-cache_test/packed-cache_test.vcproj
@@ -25,7 +25,6 @@
RuntimeLibrary="5"
UsePrecompiledHeader="0"
WarningLevel="3"
- Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -33,6 +32,7 @@
Name="VCLinkerTool"
OutputFile="$(OutDir)/packed-cache_test.exe"
LinkIncremental="2"
+ ForceSymbolReferences="__tcmalloc"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/packed-cache_test.pdb"
SubSystem="1"
@@ -70,7 +70,6 @@
RuntimeLibrary="4"
UsePrecompiledHeader="0"
WarningLevel="3"
- Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -78,6 +77,7 @@
Name="VCLinkerTool"
OutputFile="$(OutDir)/packed-cache_test.exe"
LinkIncremental="1"
+ ForceSymbolReferences="__tcmalloc"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
@@ -113,74 +113,6 @@
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
<File
- RelativePath="..\..\src\base\logging.cc">
- <FileConfiguration
- Name="Debug|Win32">
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
- RuntimeLibrary="3"/>
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32">
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
- RuntimeLibrary="2"/>
- </FileConfiguration>
- </File>
- <File
- RelativePath="..\..\src\base\spinlock.cc">
- <FileConfiguration
- Name="Debug|Win32">
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
- RuntimeLibrary="3"/>
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32">
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
- RuntimeLibrary="2"/>
- </FileConfiguration>
- </File>
- <File
- RelativePath="..\..\src\base\dynamic_annotations.cc">
- <FileConfiguration
- Name="Debug|Win32">
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
- RuntimeLibrary="3"/>
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32">
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
- RuntimeLibrary="2"/>
- </FileConfiguration>
- </File>
- <File
- RelativePath="..\..\src\base\sysinfo.cc">
- <FileConfiguration
- Name="Debug|Win32">
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
- RuntimeLibrary="3"/>
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32">
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
- RuntimeLibrary="2"/>
- </FileConfiguration>
- </File>
- <File
RelativePath="..\..\src\tests\packed-cache_test.cc">
<FileConfiguration
Name="Debug|Win32">
@@ -197,23 +129,6 @@
RuntimeLibrary="2"/>
</FileConfiguration>
</File>
- <File
- RelativePath="..\..\src\windows\port.cc">
- <FileConfiguration
- Name="Debug|Win32">
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
- RuntimeLibrary="3"/>
- </FileConfiguration>
- <FileConfiguration
- Name="Release|Win32">
- <Tool
- Name="VCCLCompilerTool"
- AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
- RuntimeLibrary="2"/>
- </FileConfiguration>
- </File>
</Filter>
<Filter
Name="Header Files"
diff --git a/vsprojects/pagemap_unittest/pagemap_unittest.vcproj b/vsprojects/pagemap_unittest/pagemap_unittest.vcproj
index bed83f1..f3d89ff 100755
--- a/vsprojects/pagemap_unittest/pagemap_unittest.vcproj
+++ b/vsprojects/pagemap_unittest/pagemap_unittest.vcproj
@@ -25,7 +25,6 @@
RuntimeLibrary="5"
UsePrecompiledHeader="0"
WarningLevel="3"
- Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -70,7 +69,6 @@
RuntimeLibrary="4"
UsePrecompiledHeader="0"
WarningLevel="3"
- Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/vsprojects/realloc_unittest/realloc_unittest.vcproj b/vsprojects/realloc_unittest/realloc_unittest.vcproj
index bfeb500..7b19efc 100755
--- a/vsprojects/realloc_unittest/realloc_unittest.vcproj
+++ b/vsprojects/realloc_unittest/realloc_unittest.vcproj
@@ -25,7 +25,6 @@
RuntimeLibrary="5"
UsePrecompiledHeader="0"
WarningLevel="3"
- Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -70,7 +69,6 @@
RuntimeLibrary="4"
UsePrecompiledHeader="0"
WarningLevel="3"
- Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/vsprojects/sampler_test/sampler_test.vcproj b/vsprojects/sampler_test/sampler_test.vcproj
index ffbe7b4..9447f01 100755
--- a/vsprojects/sampler_test/sampler_test.vcproj
+++ b/vsprojects/sampler_test/sampler_test.vcproj
@@ -25,7 +25,6 @@
RuntimeLibrary="5"
UsePrecompiledHeader="0"
WarningLevel="3"
- Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -70,7 +69,6 @@
RuntimeLibrary="4"
UsePrecompiledHeader="0"
WarningLevel="3"
- Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/vsprojects/stack_trace_table_test/stack_trace_table_test.vcproj b/vsprojects/stack_trace_table_test/stack_trace_table_test.vcproj
index 2805bdb..bfac576 100755
--- a/vsprojects/stack_trace_table_test/stack_trace_table_test.vcproj
+++ b/vsprojects/stack_trace_table_test/stack_trace_table_test.vcproj
@@ -25,7 +25,6 @@
RuntimeLibrary="5"
UsePrecompiledHeader="0"
WarningLevel="3"
- Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -71,7 +70,6 @@
RuntimeLibrary="4"
UsePrecompiledHeader="0"
WarningLevel="3"
- Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/vsprojects/tcmalloc_minimal_large/tcmalloc_minimal_large_unittest.vcproj b/vsprojects/tcmalloc_minimal_large/tcmalloc_minimal_large_unittest.vcproj
index b32d722..cd9f007 100755
--- a/vsprojects/tcmalloc_minimal_large/tcmalloc_minimal_large_unittest.vcproj
+++ b/vsprojects/tcmalloc_minimal_large/tcmalloc_minimal_large_unittest.vcproj
@@ -25,7 +25,6 @@
RuntimeLibrary="5"
UsePrecompiledHeader="0"
WarningLevel="3"
- Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -71,7 +70,6 @@
RuntimeLibrary="4"
UsePrecompiledHeader="0"
WarningLevel="3"
- Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/vsprojects/tcmalloc_minimal_unittest/tcmalloc_minimal_unittest.vcproj b/vsprojects/tcmalloc_minimal_unittest/tcmalloc_minimal_unittest.vcproj
index 4fd9a2c..47f6f74 100755
--- a/vsprojects/tcmalloc_minimal_unittest/tcmalloc_minimal_unittest.vcproj
+++ b/vsprojects/tcmalloc_minimal_unittest/tcmalloc_minimal_unittest.vcproj
@@ -25,7 +25,6 @@
RuntimeLibrary="5"
UsePrecompiledHeader="0"
WarningLevel="3"
- Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -71,7 +70,6 @@
RuntimeLibrary="4"
UsePrecompiledHeader="0"
WarningLevel="3"
- Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/vsprojects/thread_dealloc_unittest/thread_dealloc_unittest.vcproj b/vsprojects/thread_dealloc_unittest/thread_dealloc_unittest.vcproj
index 0dcf488..62c0766 100755
--- a/vsprojects/thread_dealloc_unittest/thread_dealloc_unittest.vcproj
+++ b/vsprojects/thread_dealloc_unittest/thread_dealloc_unittest.vcproj
@@ -25,7 +25,6 @@
RuntimeLibrary="5"
UsePrecompiledHeader="0"
WarningLevel="3"
- Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -71,7 +70,6 @@
RuntimeLibrary="4"
UsePrecompiledHeader="0"
WarningLevel="3"
- Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
diff --git a/vsprojects/tmu-static/tmu-static.vcproj b/vsprojects/tmu-static/tmu-static.vcproj
index 66e7bce..a5d6402 100755
--- a/vsprojects/tmu-static/tmu-static.vcproj
+++ b/vsprojects/tmu-static/tmu-static.vcproj
@@ -25,7 +25,6 @@
RuntimeLibrary="5"
UsePrecompiledHeader="0"
WarningLevel="3"
- Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -70,7 +69,6 @@
RuntimeLibrary="4"
UsePrecompiledHeader="0"
WarningLevel="3"
- Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
@@ -170,6 +168,23 @@
</FileConfiguration>
</File>
<File
+ RelativePath="..\..\src\symbolize.cc">
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="3"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\src\windows; ..\..\src"
+ RuntimeLibrary="2"/>
+ </FileConfiguration>
+ </File>
+ <File
RelativePath="..\..\src\windows\ia32_modrm_map.cc">
<FileConfiguration
Name="Debug|Win32">
@@ -711,6 +726,9 @@
RelativePath="..\..\src\heap-profile-table.h">
</File>
<File
+ RelativePath="..\..\src\symbolize.h">
+ </File>
+ <File
RelativePath="..\..\src\google\heap-profiler.h">
</File>
<File
@@ -795,7 +813,7 @@
RelativePath="..\..\src\google\stacktrace_config.h">
</File>
<File
- RelativePath="..\..\src\stacktrace_win32-inl.h.h">
+ RelativePath="..\..\src\stacktrace_win32-inl.h">
</File>
<File
RelativePath="..\..\src\raw_printer.h">