From cf5047e7c8c0284bb27a73ea3cd214bbabcd1c1d Mon Sep 17 00:00:00 2001 From: Teresa Johnson Date: Tue, 28 Nov 2023 15:09:54 -0800 Subject: [PATCH 1/2] [MemProf] Add interface for reseting the profile file descriptor Add __memprof_profile_reset() interface which can be used to facilitate dumping multiple rounds of profiles from a single binary run. This closes the current file descriptor and resets the internal file descriptor to invalid (-1), which ensures the underlying writer reopens the recorded profile filename. This can be used once the client is done moving or copying a dumped profile, to prepare for reinvoking profile dumping. --- .../include/sanitizer/memprof_interface.h | 6 +++ compiler-rt/lib/memprof/memprof_allocator.cpp | 8 ++++ .../lib/memprof/memprof_interface_internal.h | 1 + .../test/memprof/TestCases/profile_reset.cpp | 39 +++++++++++++++++++ 4 files changed, 54 insertions(+) create mode 100644 compiler-rt/test/memprof/TestCases/profile_reset.cpp diff --git a/compiler-rt/include/sanitizer/memprof_interface.h b/compiler-rt/include/sanitizer/memprof_interface.h index fe0a2fc5ef025..4660a7818c92b 100644 --- a/compiler-rt/include/sanitizer/memprof_interface.h +++ b/compiler-rt/include/sanitizer/memprof_interface.h @@ -59,6 +59,12 @@ const char *SANITIZER_CDECL __memprof_default_options(void); /// \returns 0 on success. int SANITIZER_CDECL __memprof_profile_dump(void); +/// Closes the existing file descriptor, if it is valid and not stdout or +/// stderr, and resets the internal state such that the profile filename is +/// reopened on the next profile dump attempt. This can be used to enable +/// multiple rounds of profiling on the same binary. +void SANITIZER_CDECL __memprof_profile_reset(void); + #ifdef __cplusplus } // extern "C" #endif diff --git a/compiler-rt/lib/memprof/memprof_allocator.cpp b/compiler-rt/lib/memprof/memprof_allocator.cpp index efdfa5ad04a69..12890fae101c3 100644 --- a/compiler-rt/lib/memprof/memprof_allocator.cpp +++ b/compiler-rt/lib/memprof/memprof_allocator.cpp @@ -738,3 +738,11 @@ int __memprof_profile_dump() { // detected during the dumping process. return 0; } + +void __memprof_profile_reset() { + if (report_file.fd != kInvalidFd && report_file.fd != kStdoutFd && + report_file.fd != kStderrFd) { + CloseFile(report_file.fd); + report_file.fd = kInvalidFd; + } +} diff --git a/compiler-rt/lib/memprof/memprof_interface_internal.h b/compiler-rt/lib/memprof/memprof_interface_internal.h index 0aca4afc9afa9..318bc41044056 100644 --- a/compiler-rt/lib/memprof/memprof_interface_internal.h +++ b/compiler-rt/lib/memprof/memprof_interface_internal.h @@ -49,6 +49,7 @@ extern uptr __memprof_shadow_memory_dynamic_address; SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE extern char __memprof_profile_filename[1]; SANITIZER_INTERFACE_ATTRIBUTE int __memprof_profile_dump(); +SANITIZER_INTERFACE_ATTRIBUTE void __memprof_profile_reset(); SANITIZER_INTERFACE_ATTRIBUTE void __memprof_load(uptr p); SANITIZER_INTERFACE_ATTRIBUTE void __memprof_store(uptr p); diff --git a/compiler-rt/test/memprof/TestCases/profile_reset.cpp b/compiler-rt/test/memprof/TestCases/profile_reset.cpp new file mode 100644 index 0000000000000..0130722eb2cf6 --- /dev/null +++ b/compiler-rt/test/memprof/TestCases/profile_reset.cpp @@ -0,0 +1,39 @@ +// Test to ensure that multiple rounds of dumping, using the +// __memprof_profile_reset interface to close the initial file +// and cause the profile to be reopened, works as expected. + +// RUN: %clangxx_memprof %s -o %t + +// RUN: rm -f %t.log.* +// RUN: %env_memprof_opts=print_text=true:log_path=%t.log %run %t + +// Check both outputs, starting with the renamed initial dump, then remove it so +// that the second glob matches a single file. +// RUN: FileCheck %s --dump-input=always < %t.log.*.sv +// RUN: rm -f %t.log.*.sv +// RUN: FileCheck %s --dump-input=always < %t.log.* +// CHECK: Memory allocation stack id + +#include +#include + +#include +#include +#include +int main(int argc, char **argv) { + char *x = (char *)malloc(10); + memset(x, 0, 10); + free(x); + __memprof_profile_dump(); + // Save the initial dump in a different file. + std::string origname = __sanitizer_get_report_path(); + std::string svname = origname + ".sv"; + rename(origname.c_str(), svname.c_str()); + // This should cause the current file descriptor to be closed and the + // the internal state reset so that the profile filename is reopened + // on the next write. + __memprof_profile_reset(); + // This will dump to origname again. + __memprof_profile_dump(); + return 0; +} From bc416b5d22ea8557e8b3a5b322019027a12accda Mon Sep 17 00:00:00 2001 From: Teresa Johnson Date: Tue, 28 Nov 2023 16:44:09 -0800 Subject: [PATCH 2/2] Address comments. --- compiler-rt/lib/memprof/memprof_allocator.cpp | 2 ++ compiler-rt/test/memprof/TestCases/profile_reset.cpp | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler-rt/lib/memprof/memprof_allocator.cpp b/compiler-rt/lib/memprof/memprof_allocator.cpp index 12890fae101c3..af46ffdb248e2 100644 --- a/compiler-rt/lib/memprof/memprof_allocator.cpp +++ b/compiler-rt/lib/memprof/memprof_allocator.cpp @@ -743,6 +743,8 @@ void __memprof_profile_reset() { if (report_file.fd != kInvalidFd && report_file.fd != kStdoutFd && report_file.fd != kStderrFd) { CloseFile(report_file.fd); + // Setting the file descriptor to kInvalidFd ensures that we will reopen the + // file when invoking Write again. report_file.fd = kInvalidFd; } } diff --git a/compiler-rt/test/memprof/TestCases/profile_reset.cpp b/compiler-rt/test/memprof/TestCases/profile_reset.cpp index 0130722eb2cf6..c9bbc440a29d0 100644 --- a/compiler-rt/test/memprof/TestCases/profile_reset.cpp +++ b/compiler-rt/test/memprof/TestCases/profile_reset.cpp @@ -9,9 +9,9 @@ // Check both outputs, starting with the renamed initial dump, then remove it so // that the second glob matches a single file. -// RUN: FileCheck %s --dump-input=always < %t.log.*.sv +// RUN: FileCheck %s < %t.log.*.sv // RUN: rm -f %t.log.*.sv -// RUN: FileCheck %s --dump-input=always < %t.log.* +// RUN: FileCheck %s < %t.log.* // CHECK: Memory allocation stack id #include