diff --git a/compiler-rt/lib/memprof/memprof_interface_internal.h b/compiler-rt/lib/memprof/memprof_interface_internal.h --- a/compiler-rt/lib/memprof/memprof_interface_internal.h +++ b/compiler-rt/lib/memprof/memprof_interface_internal.h @@ -46,6 +46,9 @@ SANITIZER_INTERFACE_ATTRIBUTE extern uptr __memprof_shadow_memory_dynamic_address; +SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE extern char + __memprof_profile_filename[1]; + SANITIZER_INTERFACE_ATTRIBUTE void __memprof_load(uptr p); SANITIZER_INTERFACE_ATTRIBUTE void __memprof_store(uptr p); diff --git a/compiler-rt/lib/memprof/memprof_rtl.cpp b/compiler-rt/lib/memprof/memprof_rtl.cpp --- a/compiler-rt/lib/memprof/memprof_rtl.cpp +++ b/compiler-rt/lib/memprof/memprof_rtl.cpp @@ -27,6 +27,9 @@ uptr __memprof_shadow_memory_dynamic_address; // Global interface symbol. +// Allow the user to specify a profile output file via the binary. +SANITIZER_WEAK_ATTRIBUTE char __memprof_profile_filename[1] = {0}; + namespace __memprof { static void MemprofDie() { @@ -174,7 +177,12 @@ AddDieCallback(MemprofDie); SetCheckFailedCallback(MemprofCheckFailed); - __sanitizer_set_report_path(common_flags()->log_path); + // Use profile name specified via the binary itself if it exists, and hasn't + // been overrriden by a flag at runtime. + if (__memprof_profile_filename[0] != 0 && !common_flags()->log_path) + __sanitizer_set_report_path(__memprof_profile_filename); + else + __sanitizer_set_report_path(common_flags()->log_path); __sanitizer::InitializePlatformEarly(); diff --git a/compiler-rt/lib/memprof/weak_symbols.txt b/compiler-rt/lib/memprof/weak_symbols.txt --- a/compiler-rt/lib/memprof/weak_symbols.txt +++ b/compiler-rt/lib/memprof/weak_symbols.txt @@ -1 +1 @@ -___memprof_default_options +___memprof_default_options __memprof_profile_filename diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_file.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_file.cpp --- a/compiler-rt/lib/sanitizer_common/sanitizer_file.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_file.cpp @@ -69,24 +69,23 @@ } void ReportFile::SetReportPath(const char *path) { - if (!path) - return; - uptr len = internal_strlen(path); - if (len > sizeof(path_prefix) - 100) { - Report("ERROR: Path is too long: %c%c%c%c%c%c%c%c...\n", - path[0], path[1], path[2], path[3], - path[4], path[5], path[6], path[7]); - Die(); + if (path) { + uptr len = internal_strlen(path); + if (len > sizeof(path_prefix) - 100) { + Report("ERROR: Path is too long: %c%c%c%c%c%c%c%c...\n", path[0], path[1], + path[2], path[3], path[4], path[5], path[6], path[7]); + Die(); + } } SpinMutexLock l(mu); if (fd != kStdoutFd && fd != kStderrFd && fd != kInvalidFd) CloseFile(fd); fd = kInvalidFd; - if (internal_strcmp(path, "stdout") == 0) { - fd = kStdoutFd; - } else if (internal_strcmp(path, "stderr") == 0) { + if (!path || internal_strcmp(path, "stderr") == 0) { fd = kStderrFd; + } else if (internal_strcmp(path, "stdout") == 0) { + fd = kStdoutFd; } else { internal_snprintf(path_prefix, kMaxPathLength, "%s", path); } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc b/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc --- a/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc @@ -47,9 +47,9 @@ COMMON_FLAG(int, malloc_context_size, 1, "Max number of stack frames kept for each allocation/deallocation.") COMMON_FLAG( - const char *, log_path, "stderr", + const char *, log_path, nullptr, "Write logs to \"log_path.pid\". The special values are \"stdout\" and " - "\"stderr\". The default is \"stderr\".") + "\"stderr\". If unspecified, defaults to \"stderr\".") COMMON_FLAG( bool, log_exe_name, false, "Mention name of executable when reporting error and " diff --git a/compiler-rt/test/memprof/TestCases/atexit_stats.cpp b/compiler-rt/test/memprof/TestCases/atexit_stats.cpp --- a/compiler-rt/test/memprof/TestCases/atexit_stats.cpp +++ b/compiler-rt/test/memprof/TestCases/atexit_stats.cpp @@ -1,8 +1,8 @@ // Check atexit option. // RUN: %clangxx_memprof -O0 %s -o %t -// RUN: %env_memprof_opts=atexit=1 %run %t 2>&1 | FileCheck %s -// RUN: %env_memprof_opts=atexit=0 %run %t 2>&1 | FileCheck %s --check-prefix=NOATEXIT +// RUN: %env_memprof_opts=log_path=stderr:atexit=1 %run %t 2>&1 | FileCheck %s +// RUN: %env_memprof_opts=log_path=stderr:atexit=0 %run %t 2>&1 | FileCheck %s --check-prefix=NOATEXIT // CHECK: MemProfiler exit stats: // CHECK: Stats: {{[0-9]+}}M malloced ({{[0-9]+}}M for overhead) by {{[0-9]+}} calls diff --git a/compiler-rt/test/memprof/TestCases/dump_process_map.cpp b/compiler-rt/test/memprof/TestCases/dump_process_map.cpp --- a/compiler-rt/test/memprof/TestCases/dump_process_map.cpp +++ b/compiler-rt/test/memprof/TestCases/dump_process_map.cpp @@ -1,8 +1,8 @@ // Check dump_process_map option. // RUN: %clangxx_memprof -O0 %s -o %t -// RUN: %env_memprof_opts=dump_process_map=1 %run %t 2>&1 | FileCheck %s -// RUN: %env_memprof_opts=dump_process_map=0 %run %t 2>&1 | FileCheck %s --check-prefix=NOMAP +// RUN: %env_memprof_opts=log_path=stderr:dump_process_map=1 %run %t 2>&1 | FileCheck %s +// RUN: %env_memprof_opts=log_path=stderr:dump_process_map=0 %run %t 2>&1 | FileCheck %s --check-prefix=NOMAP // CHECK: Process memory map follows: // CHECK: dump_process_map.cpp.tmp diff --git a/compiler-rt/test/memprof/TestCases/log_path_test.cpp b/compiler-rt/test/memprof/TestCases/log_path_test.cpp --- a/compiler-rt/test/memprof/TestCases/log_path_test.cpp +++ b/compiler-rt/test/memprof/TestCases/log_path_test.cpp @@ -3,8 +3,8 @@ // // RUN: %clangxx_memprof %s -o %t -// Regular run. -// RUN: %run %t 2> %t.out +// stderr log_path +// RUN: %env_memprof_opts=log_path=stderr %run %t 2> %t.out // RUN: FileCheck %s --check-prefix=CHECK-GOOD < %t.out // Good log_path. @@ -21,6 +21,24 @@ // RUN: not %run %t 2> %t.out // RUN: FileCheck %s --check-prefix=CHECK-LONG < %t.out +// Specifying the log name via the __memprof_profile_filename variable. +// RUN: %clangxx_memprof %s -o %t -DPROFILE_NAME_VAR="%t.log2" +// RUN: rm -f %t.log2.* +// RUN: %run %t 2> %t.out +// RUN: FileCheck %s --check-prefix=CHECK-GOOD < %t.log2.* + +// Check that the log_path option overrides the log name set via the +// __memprof_profile_filename variable. +// RUN: rm -f %t.log.* +// RUN: %env_memprof_opts=log_path=%t.log %run %t 2> %t.out +// RUN: FileCheck %s --check-prefix=CHECK-GOOD < %t.log.* + +#ifdef PROFILE_NAME_VAR +#define xstr(s) str(s) +#define str(s) #s +char __memprof_profile_filename[] = xstr(PROFILE_NAME_VAR); +#endif + #include #include int main(int argc, char **argv) { diff --git a/compiler-rt/test/memprof/TestCases/malloc-size-too-big.cpp b/compiler-rt/test/memprof/TestCases/malloc-size-too-big.cpp --- a/compiler-rt/test/memprof/TestCases/malloc-size-too-big.cpp +++ b/compiler-rt/test/memprof/TestCases/malloc-size-too-big.cpp @@ -1,8 +1,8 @@ // RUN: %clangxx_memprof -O0 %s -o %t -// RUN: %env_memprof_opts=allocator_may_return_null=0 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-SUMMARY -// RUN: %env_memprof_opts=allocator_may_return_null=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NULL +// RUN: %env_memprof_opts=log_path=stderr:allocator_may_return_null=0 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-SUMMARY +// RUN: %env_memprof_opts=log_path=stderr:allocator_may_return_null=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NULL // Test print_summary -// RUN: %env_memprof_opts=allocator_may_return_null=0:print_summary=0 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NOSUMMARY +// RUN: %env_memprof_opts=log_path=stderr:allocator_may_return_null=0:print_summary=0 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NOSUMMARY #include #include diff --git a/compiler-rt/test/memprof/TestCases/mem_info_cache_entries.cpp b/compiler-rt/test/memprof/TestCases/mem_info_cache_entries.cpp --- a/compiler-rt/test/memprof/TestCases/mem_info_cache_entries.cpp +++ b/compiler-rt/test/memprof/TestCases/mem_info_cache_entries.cpp @@ -1,6 +1,6 @@ // Check mem_info_cache_entries option. -// RUN: %clangxx_memprof -O0 %s -o %t && %env_memprof_opts=mem_info_cache_entries=15:print_mem_info_cache_miss_rate=1:print_mem_info_cache_miss_rate_details=1 %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_memprof -O0 %s -o %t && %env_memprof_opts=log_path=stderr:mem_info_cache_entries=15:print_mem_info_cache_miss_rate=1:print_mem_info_cache_miss_rate_details=1 %run %t 2>&1 | FileCheck %s // CHECK: Set 14 miss rate: 0 / {{.*}} = 0.00% // CHECK-NOT: Set diff --git a/compiler-rt/test/memprof/TestCases/print_miss_rate.cpp b/compiler-rt/test/memprof/TestCases/print_miss_rate.cpp --- a/compiler-rt/test/memprof/TestCases/print_miss_rate.cpp +++ b/compiler-rt/test/memprof/TestCases/print_miss_rate.cpp @@ -2,8 +2,8 @@ // print_mem_info_cache_miss_rate_details options. // RUN: %clangxx_memprof -O0 %s -o %t -// RUN: %env_memprof_opts=print_mem_info_cache_miss_rate=1 %run %t 2>&1 | FileCheck %s -// RUN: %env_memprof_opts=print_mem_info_cache_miss_rate=1:print_mem_info_cache_miss_rate_details=1 %run %t 2>&1 | FileCheck %s --check-prefix=DETAILS +// RUN: %env_memprof_opts=log_path=stderr:print_mem_info_cache_miss_rate=1 %run %t 2>&1 | FileCheck %s +// RUN: %env_memprof_opts=log_path=stderr:print_mem_info_cache_miss_rate=1:print_mem_info_cache_miss_rate_details=1 %run %t 2>&1 | FileCheck %s --check-prefix=DETAILS // CHECK: Overall miss rate: 0 / {{.*}} = 0.00% // DETAILS: Set 0 miss rate: 0 / {{.*}} = 0.00% diff --git a/compiler-rt/test/memprof/TestCases/stress_dtls.c b/compiler-rt/test/memprof/TestCases/stress_dtls.c --- a/compiler-rt/test/memprof/TestCases/stress_dtls.c +++ b/compiler-rt/test/memprof/TestCases/stress_dtls.c @@ -7,9 +7,9 @@ // RUN: %clangxx_memprof %s -ldl -pthread -o %t // RUN: %run %t 0 3 // RUN: %run %t 2 3 -// RUN: %env_memprof_opts=verbosity=2 %run %t 10 2 2>&1 | FileCheck %s -// RUN: %env_memprof_opts=verbosity=2:intercept_tls_get_addr=1 %run %t 10 2 2>&1 | FileCheck %s -// RUN: %env_memprof_opts=verbosity=2:intercept_tls_get_addr=0 %run %t 10 2 2>&1 | FileCheck %s --check-prefix=CHECK0 +// RUN: %env_memprof_opts=log_path=stderr:verbosity=2 %run %t 10 2 2>&1 | FileCheck %s +// RUN: %env_memprof_opts=log_path=stderr:verbosity=2:intercept_tls_get_addr=1 %run %t 10 2 2>&1 | FileCheck %s +// RUN: %env_memprof_opts=log_path=stderr:verbosity=2:intercept_tls_get_addr=0 %run %t 10 2 2>&1 | FileCheck %s --check-prefix=CHECK0 // CHECK: __tls_get_addr // CHECK: Creating thread 0 // CHECK: __tls_get_addr diff --git a/compiler-rt/test/memprof/TestCases/test_malloc_load_store.c b/compiler-rt/test/memprof/TestCases/test_malloc_load_store.c --- a/compiler-rt/test/memprof/TestCases/test_malloc_load_store.c +++ b/compiler-rt/test/memprof/TestCases/test_malloc_load_store.c @@ -3,10 +3,10 @@ // before exit. // RUN: %clangxx_memprof -O0 %s -o %t -// RUN: %env_memprof_opts= %run %t 2>&1 | FileCheck %s +// RUN: %env_memprof_opts=log_path=stderr %run %t 2>&1 | FileCheck %s // RUN: %clangxx_memprof -DFREE -O0 %s -o %t -// RUN: %env_memprof_opts= %run %t 2>&1 | FileCheck %s +// RUN: %env_memprof_opts=log_path=stderr %run %t 2>&1 | FileCheck %s // This is actually: // Memory allocation stack id = STACKID diff --git a/compiler-rt/test/memprof/TestCases/test_memintrin.cpp b/compiler-rt/test/memprof/TestCases/test_memintrin.cpp --- a/compiler-rt/test/memprof/TestCases/test_memintrin.cpp +++ b/compiler-rt/test/memprof/TestCases/test_memintrin.cpp @@ -1,6 +1,6 @@ // Check profile with calls to memory intrinsics. -// RUN: %clangxx_memprof -O0 %s -o %t && %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_memprof -O0 %s -o %t && %env_memprof_opts=log_path=stderr %run %t 2>&1 | FileCheck %s // This is actually: // Memory allocation stack id = STACKIDP diff --git a/compiler-rt/test/memprof/TestCases/test_new_load_store.cpp b/compiler-rt/test/memprof/TestCases/test_new_load_store.cpp --- a/compiler-rt/test/memprof/TestCases/test_new_load_store.cpp +++ b/compiler-rt/test/memprof/TestCases/test_new_load_store.cpp @@ -3,14 +3,14 @@ // before exit. // RUN: %clangxx_memprof -O0 %s -o %t -// RUN: %env_memprof_opts= %run %t 2>&1 | FileCheck %s +// RUN: %env_memprof_opts=log_path=stderr %run %t 2>&1 | FileCheck %s // RUN: %clangxx_memprof -DFREE -O0 %s -o %t -// RUN: %env_memprof_opts= %run %t 2>&1 | FileCheck %s +// RUN: %env_memprof_opts=log_path=stderr %run %t 2>&1 | FileCheck %s // Try again with callbacks instead of inline sequences // RUN: %clangxx_memprof -mllvm -memprof-use-callbacks -O0 %s -o %t -// RUN: %env_memprof_opts= %run %t 2>&1 | FileCheck %s +// RUN: %env_memprof_opts=log_path=stderr %run %t 2>&1 | FileCheck %s // This is actually: // Memory allocation stack id = STACKID diff --git a/compiler-rt/test/memprof/TestCases/test_terse.cpp b/compiler-rt/test/memprof/TestCases/test_terse.cpp --- a/compiler-rt/test/memprof/TestCases/test_terse.cpp +++ b/compiler-rt/test/memprof/TestCases/test_terse.cpp @@ -3,10 +3,10 @@ // deallocated before exit. // RUN: %clangxx_memprof -O0 %s -o %t -// RUN: %env_memprof_opts=print_terse=1 %run %t 2>&1 | FileCheck %s +// RUN: %env_memprof_opts=log_path=stderr:print_terse=1 %run %t 2>&1 | FileCheck %s // RUN: %clangxx_memprof -DFREE -O0 %s -o %t -// RUN: %env_memprof_opts=print_terse=1 %run %t 2>&1 | FileCheck %s +// RUN: %env_memprof_opts=log_path=stderr:print_terse=1 %run %t 2>&1 | FileCheck %s // CHECK: MIB:[[STACKID:[0-9]+]]/1/40.00/40/40/20.00/20/20/[[AVELIFETIME:[0-9]+]].00/[[AVELIFETIME]]/[[AVELIFETIME]]/0/0/0/0 // CHECK: Stack for id [[STACKID]]: diff --git a/compiler-rt/test/memprof/TestCases/unaligned_loads_and_stores.cpp b/compiler-rt/test/memprof/TestCases/unaligned_loads_and_stores.cpp --- a/compiler-rt/test/memprof/TestCases/unaligned_loads_and_stores.cpp +++ b/compiler-rt/test/memprof/TestCases/unaligned_loads_and_stores.cpp @@ -1,4 +1,4 @@ -// RUN: %clangxx_memprof -O0 %s -o %t && %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_memprof -O0 %s -o %t && %env_memprof_opts=log_path=stderr %run %t 2>&1 | FileCheck %s // This is actually: // Memory allocation stack id = STACKID