From 82a41dd6c4e5d9347c2d4e957be8fa0811984f3c Mon Sep 17 00:00:00 2001 From: Kostya Serebryany Date: Wed, 15 Mar 2017 23:27:14 +0000 Subject: [PATCH] [asan] add one more argument to __sanitizer_print_memory_profile, remove a redundant weak definition. llvm-svn: 297914 --- .../include/sanitizer/common_interface_defs.h | 4 ++- compiler-rt/lib/asan/asan_memory_profile.cc | 21 ++++++++++----- .../sanitizer_allocator_interface.h | 5 ++-- .../lib/sanitizer_common/sanitizer_common.cc | 7 ----- .../sanitizer_common_interface.inc | 2 +- .../sanitizer_common_libcdep.cc | 2 +- .../Linux/print_memory_profile_test.cc | 26 ++++++++++++------- 7 files changed, 37 insertions(+), 30 deletions(-) diff --git a/compiler-rt/include/sanitizer/common_interface_defs.h b/compiler-rt/include/sanitizer/common_interface_defs.h index f9f93022353a..4a1de968b0ee 100644 --- a/compiler-rt/include/sanitizer/common_interface_defs.h +++ b/compiler-rt/include/sanitizer/common_interface_defs.h @@ -158,8 +158,10 @@ extern "C" { // Prints stack traces for all live heap allocations ordered by total // allocation size until `top_percent` of total live heap is shown. // `top_percent` should be between 1 and 100. + // At most `max_number_of_contexts` contexts (stack traces) is printed. // Experimental feature currently available only with asan on Linux/x86_64. - void __sanitizer_print_memory_profile(size_t top_percent); + void __sanitizer_print_memory_profile(size_t top_percent, + size_t max_number_of_contexts); // Fiber annotation interface. // Before switching to a different stack, one must call diff --git a/compiler-rt/lib/asan/asan_memory_profile.cc b/compiler-rt/lib/asan/asan_memory_profile.cc index c2678b974fe6..e07f45144105 100644 --- a/compiler-rt/lib/asan/asan_memory_profile.cc +++ b/compiler-rt/lib/asan/asan_memory_profile.cc @@ -48,7 +48,7 @@ class HeapProfile { } } - void Print(uptr top_percent) { + void Print(uptr top_percent, uptr max_number_of_contexts) { InternalSort(&allocations_, allocations_.size(), [](const AllocationSite &a, const AllocationSite &b) { return a.total_size > b.total_size; @@ -57,12 +57,14 @@ class HeapProfile { uptr total_shown = 0; Printf("Live Heap Allocations: %zd bytes in %zd chunks; quarantined: " "%zd bytes in %zd chunks; %zd other chunks; total chunks: %zd; " - "showing top %zd%%\n", + "showing top %zd%% (at most %zd unique contexts)\n", total_allocated_user_size_, total_allocated_count_, total_quarantined_user_size_, total_quarantined_count_, total_other_count_, total_allocated_count_ + - total_quarantined_count_ + total_other_count_, top_percent); - for (uptr i = 0; i < allocations_.size(); i++) { + total_quarantined_count_ + total_other_count_, top_percent, + max_number_of_contexts); + for (uptr i = 0; i < Min(allocations_.size(), max_number_of_contexts); + i++) { auto &a = allocations_[i]; Printf("%zd byte(s) (%zd%%) in %zd allocation(s)\n", a.total_size, a.total_size * 100 / total_allocated_user_size_, a.count); @@ -103,15 +105,20 @@ static void MemoryProfileCB(const SuspendedThreadsList &suspended_threads_list, void *argument) { HeapProfile hp; __lsan::ForEachChunk(ChunkCallback, &hp); - hp.Print(reinterpret_cast(argument)); + uptr *Arg = reinterpret_cast(argument); + hp.Print(Arg[0], Arg[1]); } } // namespace __asan extern "C" { SANITIZER_INTERFACE_ATTRIBUTE -void __sanitizer_print_memory_profile(uptr top_percent) { - __sanitizer::StopTheWorld(__asan::MemoryProfileCB, (void*)top_percent); +void __sanitizer_print_memory_profile(uptr top_percent, + uptr max_number_of_contexts) { + uptr Arg[2]; + Arg[0] = top_percent; + Arg[1] = max_number_of_contexts; + __sanitizer::StopTheWorld(__asan::MemoryProfileCB, Arg); } } // extern "C" diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_interface.h b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_interface.h index 74ee903c355f..13910e719e78 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_interface.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_interface.h @@ -38,9 +38,8 @@ SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void __sanitizer_free_hook(void *ptr); - -SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE - void __sanitizer_print_memory_profile(int top_percent); +SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void +__sanitizer_print_memory_profile(uptr top_percent, uptr max_number_of_contexts); } // extern "C" #endif // SANITIZER_ALLOCATOR_INTERFACE_H diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.cc b/compiler-rt/lib/sanitizer_common/sanitizer_common.cc index 9078a900b591..36f391118f6d 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.cc @@ -505,11 +505,4 @@ int __sanitizer_install_malloc_and_free_hooks(void (*malloc_hook)(const void *, void (*free_hook)(const void *)) { return InstallMallocFreeHooks(malloc_hook, free_hook); } - -#if !SANITIZER_GO -SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_print_memory_profile, - int top_percent) { - (void)top_percent; -} -#endif } // extern "C" diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interface.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interface.inc index 4f0e940a131b..550427c906a6 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interface.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interface.inc @@ -34,6 +34,6 @@ INTERFACE_FUNCTION(__sanitizer_get_heap_size) INTERFACE_FUNCTION(__sanitizer_get_ownership) INTERFACE_FUNCTION(__sanitizer_get_unmapped_bytes) INTERFACE_FUNCTION(__sanitizer_install_malloc_and_free_hooks) +INTERFACE_FUNCTION(__sanitizer_print_memory_profile) INTERFACE_WEAK_FUNCTION(__sanitizer_free_hook) INTERFACE_WEAK_FUNCTION(__sanitizer_malloc_hook) -INTERFACE_WEAK_FUNCTION(__sanitizer_print_memory_profile) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cc b/compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cc index e96db6dd61b7..430318863f6d 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cc @@ -123,7 +123,7 @@ void BackgroundThread(void *arg) { if (heap_profile && current_rss_mb > rss_during_last_reported_profile * 1.1) { Printf("\n\nHEAP PROFILE at RSS %zdMb\n", current_rss_mb); - __sanitizer_print_memory_profile(90); + __sanitizer_print_memory_profile(90, 20); rss_during_last_reported_profile = current_rss_mb; } } diff --git a/compiler-rt/test/asan/TestCases/Linux/print_memory_profile_test.cc b/compiler-rt/test/asan/TestCases/Linux/print_memory_profile_test.cc index 8909ccad08d4..e7896be4059b 100644 --- a/compiler-rt/test/asan/TestCases/Linux/print_memory_profile_test.cc +++ b/compiler-rt/test/asan/TestCases/Linux/print_memory_profile_test.cc @@ -3,8 +3,9 @@ // REQUIRES: leak-detection // // RUN: %clangxx_asan %s -o %t -// RUN: %run %t 100 2>&1 | FileCheck %s --check-prefix=CHECK-100 -// RUN: %run %t 50 2>&1 | FileCheck %s --check-prefix=CHECK-50 +// RUN: %run %t 100 10 2>&1 | FileCheck %s --check-prefix=CHECK-100-10 +// RUN: %run %t 100 1 2>&1 | FileCheck %s --check-prefix=CHECK-100-1 +// RUN: %run %t 50 10 2>&1 | FileCheck %s --check-prefix=CHECK-50-10 #include #include @@ -13,7 +14,7 @@ char *sink[1000]; int main(int argc, char **argv) { - if (argc < 2) + if (argc < 3) return 1; int idx = 0; @@ -22,12 +23,17 @@ int main(int argc, char **argv) { for (int i = 0; i < 28; i++) sink[idx++] = new char[24000]; - __sanitizer_print_memory_profile(atoi(argv[1])); + __sanitizer_print_memory_profile(atoi(argv[1]), atoi(argv[2])); } -// CHECK-100: Live Heap Allocations: {{.*}}; showing top 100% -// CHECK-100: 2227000 byte(s) ({{.*}}%) in 17 allocation(s) -// CHECK-100: 672000 byte(s) ({{.*}}%) in 28 allocation(s) -// CHECK-50: Live Heap Allocations: {{.*}}; showing top 50% -// CHECK-50: 2227000 byte(s) ({{.*}}%) in 17 allocation(s) -// CHECK-50-NOT: allocation +// CHECK-100-10: Live Heap Allocations: {{.*}}; showing top 100% (at most 10 unique contexts) +// CHECK-100-10: 2227000 byte(s) ({{.*}}%) in 17 allocation(s) +// CHECK-100-10: 672000 byte(s) ({{.*}}%) in 28 allocation(s) + +// CHECK-100-1: Live Heap Allocations: {{.*}}; showing top 100% (at most 1 unique contexts) +// CHECK-100-1: 2227000 byte(s) ({{.*}}%) in 17 allocation(s) +// CHECK-100-1-NOT: allocation + +// CHECK-50-10: Live Heap Allocations: {{.*}}; showing top 50% (at most 10 unique contexts) +// CHECK-50-10: 2227000 byte(s) ({{.*}}%) in 17 allocation(s) +// CHECK-50-10-NOT: allocation