summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/sanitizer/common_interface_defs.h4
-rw-r--r--lib/asan/asan_memory_profile.cc21
-rw-r--r--lib/sanitizer_common/sanitizer_allocator_interface.h5
-rw-r--r--lib/sanitizer_common/sanitizer_common.cc7
-rw-r--r--lib/sanitizer_common/sanitizer_common_interface.inc2
-rw-r--r--lib/sanitizer_common/sanitizer_common_libcdep.cc2
-rw-r--r--test/asan/TestCases/Linux/print_memory_profile_test.cc26
7 files changed, 37 insertions, 30 deletions
diff --git a/include/sanitizer/common_interface_defs.h b/include/sanitizer/common_interface_defs.h
index f9f930223..4a1de968b 100644
--- a/include/sanitizer/common_interface_defs.h
+++ b/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/lib/asan/asan_memory_profile.cc b/lib/asan/asan_memory_profile.cc
index c2678b974..e07f45144 100644
--- a/lib/asan/asan_memory_profile.cc
+++ b/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<uptr>(argument));
+ uptr *Arg = reinterpret_cast<uptr*>(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/lib/sanitizer_common/sanitizer_allocator_interface.h b/lib/sanitizer_common/sanitizer_allocator_interface.h
index 74ee903c3..13910e719 100644
--- a/lib/sanitizer_common/sanitizer_allocator_interface.h
+++ b/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/lib/sanitizer_common/sanitizer_common.cc b/lib/sanitizer_common/sanitizer_common.cc
index 9078a900b..36f391118 100644
--- a/lib/sanitizer_common/sanitizer_common.cc
+++ b/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/lib/sanitizer_common/sanitizer_common_interface.inc b/lib/sanitizer_common/sanitizer_common_interface.inc
index 4f0e940a1..550427c90 100644
--- a/lib/sanitizer_common/sanitizer_common_interface.inc
+++ b/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/lib/sanitizer_common/sanitizer_common_libcdep.cc b/lib/sanitizer_common/sanitizer_common_libcdep.cc
index e96db6dd6..430318863 100644
--- a/lib/sanitizer_common/sanitizer_common_libcdep.cc
+++ b/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/test/asan/TestCases/Linux/print_memory_profile_test.cc b/test/asan/TestCases/Linux/print_memory_profile_test.cc
index 8909ccad0..e7896be40 100644
--- a/test/asan/TestCases/Linux/print_memory_profile_test.cc
+++ b/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 <sanitizer/common_interface_defs.h>
#include <stdio.h>
@@ -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