diff --git a/compiler-rt/lib/asan/asan_flags.inc b/compiler-rt/lib/asan/asan_flags.inc --- a/compiler-rt/lib/asan/asan_flags.inc +++ b/compiler-rt/lib/asan/asan_flags.inc @@ -83,6 +83,10 @@ int, sleep_after_init, 0, "Number of seconds to sleep after AddressSanitizer is initialized. " "Useful for debugging purposes (e.g. when one needs to attach gdb).") +ASAN_FLAG( + int, sleep_before_init, 0, + "Number of seconds to sleep before AddressSanitizer starts initializing. " + "Useful for debugging purposes (e.g. when one needs to attach gdb).") ASAN_FLAG(bool, check_malloc_usable_size, true, "Allows the users to work around the bug in Nvidia drivers prior to " "295.*.") diff --git a/compiler-rt/lib/asan/asan_rtl.cpp b/compiler-rt/lib/asan/asan_rtl.cpp --- a/compiler-rt/lib/asan/asan_rtl.cpp +++ b/compiler-rt/lib/asan/asan_rtl.cpp @@ -51,10 +51,9 @@ } if (common_flags()->print_module_map >= 1) DumpProcessMap(); - if (flags()->sleep_before_dying) { - Report("Sleeping for %d second(s)\n", flags()->sleep_before_dying); - SleepForSeconds(flags()->sleep_before_dying); - } + + WaitForDebugger(flags()->sleep_before_dying, "before dying"); + if (flags()->unmap_shadow_on_exit) { if (kMidMemBeg) { UnmapOrDie((void*)kLowShadowBeg, kMidMemBeg - kLowShadowBeg); @@ -386,6 +385,8 @@ // initialization steps look at flags(). InitializeFlags(); + WaitForDebugger(flags()->sleep_before_init, "before init"); + // Stop performing init at this point if we are being loaded via // dlopen() and the platform supports it. if (SANITIZER_SUPPORTS_INIT_FOR_DLOPEN && UNLIKELY(HandleDlopenInit())) { @@ -497,10 +498,7 @@ VReport(1, "AddressSanitizer Init done\n"); - if (flags()->sleep_after_init) { - Report("Sleeping for %d second(s)\n", flags()->sleep_after_init); - SleepForSeconds(flags()->sleep_after_init); - } + WaitForDebugger(flags()->sleep_after_init, "after init"); } // Initialize as requested from some part of ASan runtime library (interceptors, diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/compiler-rt/lib/sanitizer_common/sanitizer_common.h --- a/compiler-rt/lib/sanitizer_common/sanitizer_common.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.h @@ -294,6 +294,7 @@ uptr GetTlsSize(); // Other +void WaitForDebugger(unsigned seconds, const char *label); void SleepForSeconds(unsigned seconds); void SleepForMillis(unsigned millis); u64 NanoTime(); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_common.cpp --- a/compiler-rt/lib/sanitizer_common/sanitizer_common.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.cpp @@ -351,6 +351,13 @@ } void SleepForMillis(unsigned millis) { internal_usleep((u64)millis * 1000); } +void WaitForDebugger(unsigned seconds, const char *label) { + if (seconds) { + Report("Sleeping for %u second(s) %s\n", seconds, label); + SleepForSeconds(seconds); + } +} + } // namespace __sanitizer using namespace __sanitizer; diff --git a/compiler-rt/test/asan/TestCases/sleep_after_init.c b/compiler-rt/test/asan/TestCases/sleep_after_init.c deleted file mode 100644 --- a/compiler-rt/test/asan/TestCases/sleep_after_init.c +++ /dev/null @@ -1,10 +0,0 @@ -// RUN: %clang_asan -O2 %s -o %t -// RUN: %env_asan_opts=sleep_after_init=1 not %run %t 2>&1 | FileCheck %s - -#include -int main() { - // CHECK: Sleeping for 1 second - char *x = (char*)malloc(10 * sizeof(char)); - free(x); - return x[5]; -} diff --git a/compiler-rt/test/asan/TestCases/sleep_before_dying.c b/compiler-rt/test/asan/TestCases/sleep_before_dying.c deleted file mode 100644 --- a/compiler-rt/test/asan/TestCases/sleep_before_dying.c +++ /dev/null @@ -1,10 +0,0 @@ -// RUN: %clang_asan -O2 %s -o %t -// RUN: %env_asan_opts=sleep_before_dying=1 not %run %t 2>&1 | FileCheck %s - -#include -int main() { - char *x = (char*)malloc(10 * sizeof(char)); - free(x); - return x[5]; - // CHECK: Sleeping for 1 second -} diff --git a/compiler-rt/test/asan/TestCases/sleep_for_debugger.c b/compiler-rt/test/asan/TestCases/sleep_for_debugger.c new file mode 100644 --- /dev/null +++ b/compiler-rt/test/asan/TestCases/sleep_for_debugger.c @@ -0,0 +1,17 @@ +// RUN: %clang_asan -O2 %s -o %t +// RUN: %env_asan_opts=verbosity=1:sleep_before_init=1:sleep_after_init=1:sleep_before_dying=1 not %run %t 2>&1 | FileCheck %s + +#include + +int main() { + char *x = (char*)malloc(10 * sizeof(char)); + free(x); + return x[5]; +} + +// CHECK: Sleeping for 1 second(s) before init +// CHECK: AddressSanitizer Init done +// CHECK: Sleeping for 1 second(s) after init +// CHECK: ERROR: AddressSanitizer +// CHECK: ABORTING +// CHECK: Sleeping for 1 second(s) before dying