diff options
author | csilvers <csilvers@6b5cf1ce-ec42-a296-1ba9-69fdba395a50> | 2009-09-11 18:42:32 +0000 |
---|---|---|
committer | csilvers <csilvers@6b5cf1ce-ec42-a296-1ba9-69fdba395a50> | 2009-09-11 18:42:32 +0000 |
commit | 19dfa9e3733155e57406fbd082273eb53cb2750e (patch) | |
tree | 8c000b5035acf1bd01cb7208972e128bbd98e4b2 | |
parent | 2197cc670204c583bba3903b765c77620f349609 (diff) | |
download | gperftools-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
101 files changed, 5519 insertions, 1343 deletions
@@ -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} @@ -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]) @@ -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]; } @@ -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">
|