diff options
-rw-r--r-- | include/sanitizer/lsan_interface.h | 4 | ||||
-rw-r--r-- | lib/lsan/lit_tests/TestCases/link_turned_off.cc | 23 | ||||
-rw-r--r-- | lib/lsan/lsan_common.cc | 9 | ||||
-rw-r--r-- | lib/lsan/lsan_common.h | 5 |
4 files changed, 41 insertions, 0 deletions
diff --git a/include/sanitizer/lsan_interface.h b/include/sanitizer/lsan_interface.h index c82632335..97a88a502 100644 --- a/include/sanitizer/lsan_interface.h +++ b/include/sanitizer/lsan_interface.h @@ -25,6 +25,10 @@ extern "C" { void __lsan_enable(); // The heap object into which p points will be treated as a non-leak. void __lsan_ignore_object(const void *p); + // The user may optionally provide this function to disallow leak checking + // for the program it is linked into. Note: this function may be called late, + // after all the global destructors. + int __lsan_is_turned_off(); #ifdef __cplusplus } // extern "C" diff --git a/lib/lsan/lit_tests/TestCases/link_turned_off.cc b/lib/lsan/lit_tests/TestCases/link_turned_off.cc new file mode 100644 index 000000000..e744673de --- /dev/null +++ b/lib/lsan/lit_tests/TestCases/link_turned_off.cc @@ -0,0 +1,23 @@ +// Test for disabling LSan at link-time. +// RUN: %clangxx_lsan %s -o %t +// RUN: %t +// RUN: %t foo 2>&1 | FileCheck %s + +#include <sanitizer/lsan_interface.h> + +int argc_copy; + +extern "C" { +int __lsan_is_turned_off() { + return (argc_copy == 1); +} +} + +int main(int argc, char *argv[]) { + volatile int *x = new int; + *x = 42; + argc_copy = argc; + return 0; +} + +// CHECK: SUMMARY: LeakSanitizer: 4 byte(s) leaked in 1 allocation(s) diff --git a/lib/lsan/lsan_common.cc b/lib/lsan/lsan_common.cc index 5e936cdf4..1f0bf970c 100644 --- a/lib/lsan/lsan_common.cc +++ b/lib/lsan/lsan_common.cc @@ -314,6 +314,8 @@ void DoLeakCheck() { static bool already_done; CHECK(!already_done); already_done = true; + if (&__lsan_is_turned_off && __lsan_is_turned_off()) + return; DoLeakCheckParam param; param.success = false; @@ -442,4 +444,11 @@ void __lsan_enable() { __lsan::disable_counter--; #endif } + +#if !SANITIZER_SUPPORTS_WEAK_HOOKS +SANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE +int __lsan_is_turned_off() { + return 0; +} +#endif } // extern "C" diff --git a/lib/lsan/lsan_common.h b/lib/lsan/lsan_common.h index e5f0a22d5..0ff596cee 100644 --- a/lib/lsan/lsan_common.h +++ b/lib/lsan/lsan_common.h @@ -154,4 +154,9 @@ class LsanMetadata { } // namespace __lsan +extern "C" { +int __lsan_is_turned_off() SANITIZER_WEAK_ATTRIBUTE + SANITIZER_INTERFACE_ATTRIBUTE; +} // extern "C" + #endif // LSAN_COMMON_H |