diff options
author | Alexander Potapenko <glider@google.com> | 2012-09-12 15:29:50 +0000 |
---|---|---|
committer | Alexander Potapenko <glider@google.com> | 2012-09-12 15:29:50 +0000 |
commit | ca2cdd989076d091d8c4d4c277f8b47d9b5903ad (patch) | |
tree | 8f4bc4213fea8c3fea18c2106d4f0c35040e4091 | |
parent | 0fb4069dd0d0ef4c105105affea821f516a353a5 (diff) | |
download | compiler-rt-ca2cdd989076d091d8c4d4c277f8b47d9b5903ad.tar.gz |
Give more accurate malloc statistics to malloc_zone_statistics().
Fix a warning in macros instantiation.
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@163716 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/asan/asan_malloc_mac.cc | 12 | ||||
-rw-r--r-- | lib/asan/asan_stats.h | 8 | ||||
-rw-r--r-- | lib/asan/asan_thread_registry.cc | 18 | ||||
-rw-r--r-- | lib/asan/asan_thread_registry.h | 4 | ||||
-rw-r--r-- | lib/asan/tests/asan_test.cc | 14 |
5 files changed, 50 insertions, 6 deletions
diff --git a/lib/asan/asan_malloc_mac.cc b/lib/asan/asan_malloc_mac.cc index 0243bf991..5cd63304e 100644 --- a/lib/asan/asan_malloc_mac.cc +++ b/lib/asan/asan_malloc_mac.cc @@ -25,6 +25,8 @@ #include "asan_mac.h" #include "asan_report.h" #include "asan_stack.h" +#include "asan_stats.h" +#include "asan_thread_registry.h" // Similar code is used in Google Perftools, // http://code.google.com/p/google-perftools. @@ -276,7 +278,6 @@ void mz_free_definite_size(malloc_zone_t* zone, void *ptr, size_t size) { #endif #endif -// malloc_introspection callbacks. I'm not clear on what all of these do. kern_return_t mi_enumerator(task_t task, void *, unsigned type_mask, vm_address_t zone_address, memory_reader_t reader, @@ -313,11 +314,10 @@ void mi_force_unlock(malloc_zone_t *zone) { } void mi_statistics(malloc_zone_t *zone, malloc_statistics_t *stats) { - // TODO(glider): fill these correctly. - stats->blocks_in_use = 0; - stats->size_in_use = 0; - stats->max_size_in_use = 0; - stats->size_allocated = 0; + AsanMallocStats malloc_stats; + asanThreadRegistry().FillMallocStatistics(&malloc_stats); + CHECK(sizeof(malloc_statistics_t) == sizeof(AsanMallocStats)); + internal_memcpy(stats, &malloc_stats, sizeof(malloc_statistics_t)); } #if defined(MAC_OS_X_VERSION_10_6) && \ diff --git a/lib/asan/asan_stats.h b/lib/asan/asan_stats.h index b4c63f44f..0c02b3a59 100644 --- a/lib/asan/asan_stats.h +++ b/lib/asan/asan_stats.h @@ -54,6 +54,14 @@ struct AsanStats { void Print(); }; +// A cross-platform equivalent of malloc_statistics_t on Mac OS. +struct AsanMallocStats { + uptr blocks_in_use; + uptr size_in_use; + uptr max_size_in_use; + uptr size_allocated; +}; + } // namespace __asan #endif // ASAN_STATS_H diff --git a/lib/asan/asan_thread_registry.cc b/lib/asan/asan_thread_registry.cc index 99552f048..877d32b9a 100644 --- a/lib/asan/asan_thread_registry.cc +++ b/lib/asan/asan_thread_registry.cc @@ -30,6 +30,7 @@ AsanThreadRegistry::AsanThreadRegistry(LinkerInitialized x) : main_thread_(x), main_thread_summary_(x), accumulated_stats_(x), + max_malloced_memory_(x), mu_(x) { } void AsanThreadRegistry::Init() { @@ -131,6 +132,17 @@ uptr AsanThreadRegistry::GetFreeBytes() { + accumulated_stats_.really_freed_redzones; } +// Return several stats counters with a single call to +// UpdateAccumulatedStatsUnlocked(). +void AsanThreadRegistry::FillMallocStatistics(AsanMallocStats *malloc_stats) { + ScopedLock lock(&mu_); + UpdateAccumulatedStatsUnlocked(); + malloc_stats->blocks_in_use = accumulated_stats_.mallocs; + malloc_stats->size_in_use = accumulated_stats_.malloced; + malloc_stats->max_size_in_use = max_malloced_memory_; + malloc_stats->size_allocated = accumulated_stats_.mmaped; +} + AsanThreadSummary *AsanThreadRegistry::FindByTid(u32 tid) { CHECK(tid < n_threads_); CHECK(thread_summaries_[tid]); @@ -156,6 +168,12 @@ void AsanThreadRegistry::UpdateAccumulatedStatsUnlocked() { FlushToAccumulatedStatsUnlocked(&t->stats()); } } + // This is not very accurate: we may miss allocation peaks that happen + // between two updates of accumulated_stats_. For more accurate bookkeeping + // the maximum should be updated on every malloc(), which is unacceptable. + if (max_malloced_memory_ < accumulated_stats_.malloced) { + max_malloced_memory_ = accumulated_stats_.malloced; + } } void AsanThreadRegistry::FlushToAccumulatedStatsUnlocked(AsanStats *stats) { diff --git a/lib/asan/asan_thread_registry.h b/lib/asan/asan_thread_registry.h index 7037b9edc..3ad55f5d5 100644 --- a/lib/asan/asan_thread_registry.h +++ b/lib/asan/asan_thread_registry.h @@ -53,6 +53,7 @@ class AsanThreadRegistry { uptr GetCurrentAllocatedBytes(); uptr GetHeapSize(); uptr GetFreeBytes(); + void FillMallocStatistics(AsanMallocStats *malloc_stats); AsanThreadSummary *FindByTid(u32 tid); AsanThread *FindThreadByStackAddress(uptr addr); @@ -68,6 +69,9 @@ class AsanThreadRegistry { AsanThread main_thread_; AsanThreadSummary main_thread_summary_; AsanStats accumulated_stats_; + // Required for malloc_zone_statistics() on OS X. This can't be stored in + // per-thread AsanStats. + uptr max_malloced_memory_; u32 n_threads_; AsanLock mu_; bool inited_; diff --git a/lib/asan/tests/asan_test.cc b/lib/asan/tests/asan_test.cc index 16ca2ecd0..e34c240aa 100644 --- a/lib/asan/tests/asan_test.cc +++ b/lib/asan/tests/asan_test.cc @@ -30,6 +30,7 @@ #ifndef __APPLE__ #include <malloc.h> #else +#include <malloc/malloc.h> #include <AvailabilityMacros.h> // For MAC_OS_X_VERSION_* #include <CoreFoundation/CFString.h> #endif // __APPLE__ @@ -2093,6 +2094,19 @@ TEST(AddressSanitizerMac, NSObjectOOB) { TEST(AddressSanitizerMac, NSURLDeallocation) { TestNSURLDeallocation(); } + +// See http://code.google.com/p/address-sanitizer/issues/detail?id=109. +TEST(AddressSanitizerMac, Mstats) { + malloc_statistics_t stats1, stats2; + malloc_zone_statistics(/*all zones*/NULL, &stats1); + const int kMallocSize = 100000; + void *alloc = Ident(malloc(kMallocSize)); + malloc_zone_statistics(/*all zones*/NULL, &stats2); + EXPECT_GT(stats2.blocks_in_use, stats1.blocks_in_use); + EXPECT_GE(stats2.size_in_use - stats1.size_in_use, kMallocSize); + free(alloc); + // Even the default OSX allocator may not change the stats after free(). +} #endif // __APPLE__ // Test that instrumentation of stack allocations takes into account |