Index: clang/lib/Driver/ToolChains/MSVC.cpp =================================================================== --- clang/lib/Driver/ToolChains/MSVC.cpp +++ clang/lib/Driver/ToolChains/MSVC.cpp @@ -572,6 +572,11 @@ } } + if (TC.getSanitizerArgs(Args).needsLsanRt()) { + // TODO: Is this all? Asan looks way more complicated + CmdArgs.push_back(TC.getCompilerRTArgString(Args, "lsan")); + } + Args.AddAllArgValues(CmdArgs, options::OPT__SLASH_link); // Control Flow Guard checks @@ -1408,6 +1413,7 @@ Res |= SanitizerKind::PointerSubtract; Res |= SanitizerKind::Fuzzer; Res |= SanitizerKind::FuzzerNoLink; + Res |= SanitizerKind::Leak; Res &= ~SanitizerKind::CFIMFCall; return Res; } Index: compiler-rt/cmake/config-ix.cmake =================================================================== --- compiler-rt/cmake/config-ix.cmake +++ compiler-rt/cmake/config-ix.cmake @@ -713,7 +713,7 @@ endif() if (COMPILER_RT_HAS_SANITIZER_COMMON AND LSAN_SUPPORTED_ARCH AND - OS_NAME MATCHES "Android|Darwin|Linux|NetBSD|Fuchsia") + OS_NAME MATCHES "Android|Darwin|Linux|NetBSD|Fuchsia|Windows") set(COMPILER_RT_HAS_LSAN TRUE) else() set(COMPILER_RT_HAS_LSAN FALSE) Index: compiler-rt/lib/lsan/CMakeLists.txt =================================================================== --- compiler-rt/lib/lsan/CMakeLists.txt +++ compiler-rt/lib/lsan/CMakeLists.txt @@ -11,6 +11,7 @@ lsan_common_fuchsia.cpp lsan_common_linux.cpp lsan_common_mac.cpp + lsan_common_win.cpp ) set(LSAN_SOURCES @@ -24,6 +25,7 @@ lsan_posix.cpp lsan_preinit.cpp lsan_thread.cpp + lsan_win.cpp ) set(LSAN_HEADERS Index: compiler-rt/lib/lsan/lsan.h =================================================================== --- compiler-rt/lib/lsan/lsan.h +++ compiler-rt/lib/lsan/lsan.h @@ -16,6 +16,8 @@ # include "lsan_posix.h" #elif SANITIZER_FUCHSIA # include "lsan_fuchsia.h" +#elif SANITIZER_WINDOWS +# include "lsan_win.h" #endif #include "sanitizer_common/sanitizer_flags.h" #include "sanitizer_common/sanitizer_stacktrace.h" Index: compiler-rt/lib/lsan/lsan_allocator.h =================================================================== --- compiler-rt/lib/lsan/lsan_allocator.h +++ compiler-rt/lib/lsan/lsan_allocator.h @@ -49,8 +49,8 @@ u32 stack_trace_id; }; -#if defined(__mips64) || defined(__aarch64__) || defined(__i386__) || \ - defined(__arm__) || SANITIZER_RISCV64 || defined(__hexagon__) +#if defined(__mips64) || SANITIZER_ARM64 || SANITIZER_I386 || SANITIZER_ARM || \ + SANITIZER_RISCV64 || defined(__hexagon__) template struct AP32 { static const uptr kSpaceBeg = 0; @@ -65,20 +65,20 @@ template using PrimaryAllocatorASVT = SizeClassAllocator32>; using PrimaryAllocator = PrimaryAllocatorASVT; -#elif defined(__x86_64__) || defined(__powerpc64__) || defined(__s390x__) -# if SANITIZER_FUCHSIA +#elif SANITIZER_X64 || defined(__powerpc64__) || defined(__s390x__) +# if SANITIZER_FUCHSIA const uptr kAllocatorSpace = ~(uptr)0; -const uptr kAllocatorSize = 0x40000000000ULL; // 4T. -# elif defined(__powerpc64__) +const uptr kAllocatorSize = 0x40000000000ULL; // 4T. +# elif defined(__powerpc64__) const uptr kAllocatorSpace = 0xa0000000000ULL; -const uptr kAllocatorSize = 0x20000000000ULL; // 2T. -#elif defined(__s390x__) +const uptr kAllocatorSize = 0x20000000000ULL; // 2T. +# elif defined(__s390x__) const uptr kAllocatorSpace = 0x40000000000ULL; const uptr kAllocatorSize = 0x40000000000ULL; // 4T. -# else +# else const uptr kAllocatorSpace = 0x600000000000ULL; -const uptr kAllocatorSize = 0x40000000000ULL; // 4T. -# endif +const uptr kAllocatorSize = 0x40000000000ULL; // 4T. +# endif template struct AP64 { // Allocator64 parameters. Deliberately using a short name. static const uptr kSpaceBeg = kAllocatorSpace; @@ -93,6 +93,8 @@ template using PrimaryAllocatorASVT = SizeClassAllocator64>; using PrimaryAllocator = PrimaryAllocatorASVT; +#else +# error Architecture not supported! #endif template Index: compiler-rt/lib/lsan/lsan_common.h =================================================================== --- compiler-rt/lib/lsan/lsan_common.h +++ compiler-rt/lib/lsan/lsan_common.h @@ -44,7 +44,7 @@ # define CAN_SANITIZE_LEAKS 1 #elif SANITIZER_RISCV64 && SANITIZER_LINUX # define CAN_SANITIZE_LEAKS 1 -#elif SANITIZER_NETBSD || SANITIZER_FUCHSIA +#elif SANITIZER_NETBSD || SANITIZER_FUCHSIA || SANITIZER_WINDOWS # define CAN_SANITIZE_LEAKS 1 #else # define CAN_SANITIZE_LEAKS 0 Index: compiler-rt/lib/lsan/lsan_common.cpp =================================================================== --- compiler-rt/lib/lsan/lsan_common.cpp +++ compiler-rt/lib/lsan/lsan_common.cpp @@ -245,12 +245,12 @@ const uptr kMinAddress = 4 * 4096; if (p < kMinAddress) return false; -# if defined(__x86_64__) +# if SANITIZER_X64 // Accept only canonical form user-space addresses. return ((p >> 47) == 0); # elif defined(__mips64) return ((p >> 40) == 0); -# elif defined(__aarch64__) +# elif SANITIZER_ARM64 unsigned runtimeVMA = (MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1); return ((p >> runtimeVMA) == 0); # else @@ -501,12 +501,16 @@ static void ProcessRootRegion(Frontier *frontier, const RootRegion &root_region) { +# if SANITIZER_WINDOWS + // TODO +# else MemoryMappingLayout proc_maps(/*cache_enabled*/ true); MemoryMappedSegment segment; while (proc_maps.Next(&segment)) { ScanRootRegion(frontier, root_region, segment.start, segment.end, segment.IsReadable()); } +# endif } // Scans root regions for heap pointers. Index: compiler-rt/lib/lsan/lsan_common_win.cpp =================================================================== --- /dev/null +++ compiler-rt/lib/lsan/lsan_common_win.cpp @@ -0,0 +1,95 @@ +//=-- lsan_common_win.cpp -------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file is a part of LeakSanitizer. +// Implementation of common leak checking functionality. Darwin-specific code. +// +//===----------------------------------------------------------------------===// + +#include "lsan_common.h" +#include "sanitizer_common/sanitizer_platform.h" + +#if CAN_SANITIZE_LEAKS && SANITIZER_WINDOWS + +# define WIN32_LEAN_AND_MEAN +# include + +// `windows.h` needs to be included before `dbghelp.h` +# include +# pragma comment(lib, "Dbghelp.lib") + +namespace __lsan { + +void HandleLeaks() {} + +void InitializePlatformSpecificModules() {} + +void LockStuffAndStopTheWorld(StopTheWorldCallback callback, + CheckForLeaksParam *argument) { + LockThreadRegistry(); + LockAllocator(); + StopTheWorld(callback, argument); + UnlockAllocator(); + UnlockThreadRegistry(); +} + +THREADLOCAL int disable_counter; +bool DisabledInThisThread() { return disable_counter > 0; } +void DisableInThisThread() { disable_counter++; } +void EnableInThisThread() { + if (disable_counter == 0) { + DisableCounterUnderflow(); + } + disable_counter--; +} + +BOOL CALLBACK EnumLoadedModulesCallback(PCSTR module_name, DWORD64 module_base, + ULONG module_size, PVOID user_context) { + auto *frontier = reinterpret_cast(user_context); + + // Parse the PE Headers of all loaded Modules + const auto *module_nt_header = + ImageNtHeader(reinterpret_cast(module_base)); + + CHECK(module_nt_header); + + const auto *section_header = + reinterpret_cast(module_nt_header + 1); + + // Find the `.data` section + for (WORD i = 0; i < module_nt_header->FileHeader.NumberOfSections; + ++i, ++section_header) { + const char data_section_name[6] = ".data"; + const auto is_data_section = + internal_strncmp(reinterpret_cast(section_header->Name), + data_section_name, sizeof(data_section_name)) == 0; + + if (!is_data_section) + continue; + + ScanGlobalRange(module_base + section_header->VirtualAddress, + module_base + section_header->VirtualAddress + + section_header->Misc.VirtualSize - 1, + frontier); + } + + return TRUE; +} + +void ProcessGlobalRegions(Frontier *frontier) { + HANDLE this_process = GetCurrentProcess(); + + EnumerateLoadedModules(this_process, EnumLoadedModulesCallback, frontier); +} +void ProcessPlatformSpecificAllocations(Frontier *frontier) {} + +LoadedModule *GetLinker() { return nullptr; } + +} // namespace __lsan + +#endif // CAN_SANITIZE_LEAKS && SANITIZER_WINDOWS Index: compiler-rt/lib/lsan/lsan_interceptors.cpp =================================================================== --- compiler-rt/lib/lsan/lsan_interceptors.cpp +++ compiler-rt/lib/lsan/lsan_interceptors.cpp @@ -99,26 +99,30 @@ return lsan_realloc(ptr, size, stack); } -INTERCEPTOR(void*, reallocarray, void *q, uptr nmemb, uptr size) { - ENSURE_LSAN_INITED; - GET_STACK_TRACE_MALLOC; - return lsan_reallocarray(q, nmemb, size, stack); -} - +# if SANITIZER_WINDOWS +# define LSAN_MAYBE_INTERCEPT_REALLOCARRY +# define LSAN_MAYBE_INTERCEPT_POSIX_MEMALIGN +# define LSAN_MAYBE_INTERCEPT_VALLOC +# else INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) { ENSURE_LSAN_INITED; GET_STACK_TRACE_MALLOC; return lsan_posix_memalign(memptr, alignment, size, stack); } +# define LSAN_MAYBE_INTERCEPT_POSIX_MEMALIGN \ + INTERCEPT_FUNCTION(posix_memalign) -INTERCEPTOR(void*, valloc, uptr size) { +INTERCEPTOR(void *, valloc, uptr size) { ENSURE_LSAN_INITED; GET_STACK_TRACE_MALLOC; return lsan_valloc(size, stack); } +# define LSAN_MAYBE_INTERCEPT_VALLOC INTERCEPT_FUNCTION(valloc) +# endif + #endif // !SANITIZER_MAC -#if SANITIZER_INTERCEPT_MEMALIGN +#if SANITIZER_INTERCEPT_MEMALIGN && !SANITIZER_WINDOWS INTERCEPTOR(void*, memalign, uptr alignment, uptr size) { ENSURE_LSAN_INITED; GET_STACK_TRACE_MALLOC; @@ -143,17 +147,24 @@ #endif // SANITIZER_INTERCEPT___LIBC_MEMALIGN #if SANITIZER_INTERCEPT_ALIGNED_ALLOC -INTERCEPTOR(void*, aligned_alloc, uptr alignment, uptr size) { +# if SANITIZER_WINDOWS +# define LSAN_ALIGNED_ALLOC_NAME _aligned_malloc +# else +# define LSAN_ALIGNED_ALLOC_NAME aligned_alloc +# endif + +INTERCEPTOR(void *, LSAN_ALIGNED_ALLOC_NAME, uptr alignment, uptr size) { ENSURE_LSAN_INITED; GET_STACK_TRACE_MALLOC; return lsan_aligned_alloc(alignment, size, stack); } -#define LSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC INTERCEPT_FUNCTION(aligned_alloc) +# define LSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC \ + INTERCEPT_FUNCTION(LSAN_ALIGNED_ALLOC_NAME) #else -#define LSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC +# define LSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC #endif -#if SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE +#if SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE && !SANITIZER_WINDOWS INTERCEPTOR(uptr, malloc_usable_size, void *ptr) { ENSURE_LSAN_INITED; return GetMallocUsableSize(ptr); @@ -244,9 +255,15 @@ // OS X we need to intercept them using their mangled names. #if !SANITIZER_MAC -INTERCEPTOR_ATTRIBUTE +# if SANITIZER_WINDOWS +# define INTERCEPTOR_ATTRIBUTE_DIFFERENT_LINKAGE +# else +# define INTERCEPTOR_ATTRIBUTE_DIFFERENT_LINKAGE INTERCEPTOR_ATTRIBUTE +# endif + +INTERCEPTOR_ATTRIBUTE_DIFFERENT_LINKAGE void *operator new(size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); } -INTERCEPTOR_ATTRIBUTE +INTERCEPTOR_ATTRIBUTE_DIFFERENT_LINKAGE void *operator new[](size_t size) { OPERATOR_NEW_BODY(false /*nothrow*/); } INTERCEPTOR_ATTRIBUTE void *operator new(size_t size, std::nothrow_t const&) @@ -267,19 +284,19 @@ void *operator new[](size_t size, std::align_val_t align, std::nothrow_t const&) { OPERATOR_NEW_BODY_ALIGN(true /*nothrow*/); } -INTERCEPTOR_ATTRIBUTE +INTERCEPTOR_ATTRIBUTE_DIFFERENT_LINKAGE void operator delete(void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; } -INTERCEPTOR_ATTRIBUTE +INTERCEPTOR_ATTRIBUTE_DIFFERENT_LINKAGE void operator delete[](void *ptr) NOEXCEPT { OPERATOR_DELETE_BODY; } INTERCEPTOR_ATTRIBUTE void operator delete(void *ptr, std::nothrow_t const&) { OPERATOR_DELETE_BODY; } INTERCEPTOR_ATTRIBUTE void operator delete[](void *ptr, std::nothrow_t const &) { OPERATOR_DELETE_BODY; } -INTERCEPTOR_ATTRIBUTE +INTERCEPTOR_ATTRIBUTE_DIFFERENT_LINKAGE void operator delete(void *ptr, size_t size) NOEXCEPT { OPERATOR_DELETE_BODY; } -INTERCEPTOR_ATTRIBUTE +INTERCEPTOR_ATTRIBUTE_DIFFERENT_LINKAGE void operator delete[](void *ptr, size_t size) NOEXCEPT { OPERATOR_DELETE_BODY; } INTERCEPTOR_ATTRIBUTE @@ -479,10 +496,14 @@ return res; } +#define LSAN_MAYBE_INTERCEPT_PTHREAD_CREATE INTERCEPT_FUNCTION(pthread_create) + INTERCEPTOR(int, pthread_join, void *t, void **arg) { return REAL(pthread_join)(t, arg); } +#define LSAN_MAYBE_INTERCEPT_PTHREAD_CREATE INTERCEPT_FUNCTION(pthread_join) + DEFINE_REAL_PTHREAD_FUNCTIONS INTERCEPTOR(void, _exit, int status) { @@ -490,9 +511,15 @@ REAL(_exit)(status); } +#define LSAN_MAYBE_INTERCEPT__EXIT INTERCEPT_FUNCTION(_exit) + #define COMMON_INTERCEPT_FUNCTION(name) INTERCEPT_FUNCTION(name) #include "sanitizer_common/sanitizer_signal_interceptors.inc" +#else +# define LSAN_MAYBE_INTERCEPT_PTHREAD_CREATE +# define LSAN_MAYBE_INTERCEPT_PTHREAD_JOIN +# define LSAN_MAYBE_INTERCEPT__EXIT #endif // SANITIZER_POSIX namespace __lsan { @@ -500,7 +527,9 @@ void InitializeInterceptors() { // Fuchsia doesn't use interceptors that require any setup. #if !SANITIZER_FUCHSIA +# if SANITIZER_POSIX InitializeSignalInterceptors(); +# endif INTERCEPT_FUNCTION(malloc); INTERCEPT_FUNCTION(free); @@ -510,15 +539,15 @@ LSAN_MAYBE_INTERCEPT_MEMALIGN; LSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN; LSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC; - INTERCEPT_FUNCTION(posix_memalign); - INTERCEPT_FUNCTION(valloc); + LSAN_MAYBE_INTERCEPT_POSIX_MEMALIGN; + LSAN_MAYBE_INTERCEPT_VALLOC; LSAN_MAYBE_INTERCEPT_PVALLOC; LSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE; LSAN_MAYBE_INTERCEPT_MALLINFO; LSAN_MAYBE_INTERCEPT_MALLOPT; - INTERCEPT_FUNCTION(pthread_create); - INTERCEPT_FUNCTION(pthread_join); - INTERCEPT_FUNCTION(_exit); + LSAN_MAYBE_INTERCEPT_PTHREAD_CREATE; + LSAN_MAYBE_INTERCEPT_PTHREAD_JOIN; + LSAN_MAYBE_INTERCEPT__EXIT; LSAN_MAYBE_INTERCEPT__LWP_EXIT; LSAN_MAYBE_INTERCEPT_THR_EXIT; @@ -529,7 +558,7 @@ LSAN_MAYBE_INTERCEPT_STRERROR; -#if !SANITIZER_NETBSD && !SANITIZER_FREEBSD +#if !SANITIZER_NETBSD && !SANITIZER_FREEBSD && !SANITIZER_WINDOWS if (pthread_key_create(&g_thread_finalize_key, &thread_finalize)) { Report("LeakSanitizer: failed to create thread key.\n"); Die(); Index: compiler-rt/lib/lsan/lsan_win.h =================================================================== --- /dev/null +++ compiler-rt/lib/lsan/lsan_win.h @@ -0,0 +1,41 @@ +//=-- lsan_win.h -----------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===---------------------------------------------------------------------===// +// +// This file is a part of LeakSanitizer. +// Standalone LSan RTL code common to Windows systems. +// +//===---------------------------------------------------------------------===// + +#ifndef LSAN_WINDOWS_H +#define LSAN_WINDOWS_H + +#include "lsan_thread.h" +#include "sanitizer_common/sanitizer_platform.h" + +#if !SANITIZER_WINDOWS +# error "lsan_win.h is used only on Windows systems (SANITIZER_WINDOWS)" +#endif + +namespace __sanitizer { +struct DTLS; +} + +namespace __lsan { + +class ThreadContext final : public ThreadContextLsanBase { + public: + explicit ThreadContext(int tid); + void OnStarted(void *arg) override; +}; + +void ThreadStart(u32 tid, tid_t os_id, + ThreadType thread_type = ThreadType::Regular); + +} // namespace __lsan + +#endif // LSAN_WINDOWS_H Index: compiler-rt/lib/lsan/lsan_win.cpp =================================================================== --- /dev/null +++ compiler-rt/lib/lsan/lsan_win.cpp @@ -0,0 +1,106 @@ +//=-- lsan_win.cpp -------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===---------------------------------------------------------------------===// +// +// This file is a part of LeakSanitizer. +// Standalone LSan RTL code common to POSIX-like systems. +// +//===---------------------------------------------------------------------===// + +#include "sanitizer_common/sanitizer_platform.h" + +#if SANITIZER_WINDOWS +# include "lsan.h" +# include "lsan_allocator.h" +# include "sanitizer_common/sanitizer_stacktrace.h" +# include "sanitizer_common/sanitizer_tls_get_addr.h" + +namespace __lsan { + +ThreadContext::ThreadContext(int tid) : ThreadContextLsanBase(tid) {} + +struct OnStartedArgs { + uptr stack_begin; + uptr stack_end; + uptr cache_begin; + uptr cache_end; + uptr tls_begin; + uptr tls_end; +}; + +void ThreadContext::OnStarted(void *arg) { + auto args = reinterpret_cast(arg); + stack_begin_ = args->stack_begin; + stack_end_ = args->stack_end; + cache_begin_ = args->cache_begin; + cache_end_ = args->cache_end; +} + +void ThreadStart(u32 tid, tid_t os_id, ThreadType thread_type) { + OnStartedArgs args; + uptr stack_size = 0; + uptr tls_size = 0; + GetThreadStackAndTls(tid == kMainTid, &args.stack_begin, &stack_size, + &args.tls_begin, &tls_size); + args.stack_end = args.stack_begin + stack_size; + args.tls_end = args.tls_begin + tls_size; + GetAllocatorCacheRange(&args.cache_begin, &args.cache_end); + ThreadContextLsanBase::ThreadStart(tid, os_id, thread_type, &args); +} + +bool GetThreadRangesLocked(tid_t os_id, uptr *stack_begin, uptr *stack_end, + uptr *tls_begin, uptr *tls_end, uptr *cache_begin, + uptr *cache_end, DTLS **dtls) { + ThreadContext *context = static_cast( + GetThreadRegistryLocked()->FindThreadContextByOsIDLocked(os_id)); + if (!context) + return false; + *stack_begin = context->stack_begin(); + *stack_end = context->stack_end(); + *cache_begin = context->cache_begin(); + *cache_end = context->cache_end(); + *dtls = 0; + return true; +} + +void InitializeMainThread() { + u32 tid = ThreadCreate(kMainTid, true); + CHECK_EQ(tid, kMainTid); + ThreadStart(tid, GetTid()); +} + +static void OnStackUnwind(const SignalContext &sig, const void *, + BufferedStackTrace *stack) { + stack->Unwind(StackTrace::GetNextInstructionPc(sig.pc), sig.bp, sig.context, + common_flags()->fast_unwind_on_fatal); +} + +void LsanOnDeadlySignal(int signo, void *siginfo, void *context) { + HandleDeadlySignal(siginfo, context, GetCurrentThread(), &OnStackUnwind, + nullptr); +} + +void ReplaceSystemMalloc() {} + +static THREADLOCAL u32 current_thread_tid = kInvalidTid; +u32 GetCurrentThread() { return current_thread_tid; } +void SetCurrentThread(u32 tid) { current_thread_tid = tid; } + +static THREADLOCAL AllocatorCache allocator_cache; +AllocatorCache *GetAllocatorCache() { return &allocator_cache; } + +} // namespace __lsan + +int lsan_win_init() { + __lsan_init(); + return 0; +} + +# pragma section(".CRT$XIB", long, read) +__declspec(allocate(".CRT$XIB")) int (*__lsan_preinit)() = lsan_win_init; + +#endif // SANITIZER_WINDOWS Index: compiler-rt/test/lsan/TestCases/Darwin/dispatch.mm =================================================================== --- compiler-rt/test/lsan/TestCases/Darwin/dispatch.mm +++ compiler-rt/test/lsan/TestCases/Darwin/dispatch.mm @@ -1,9 +1,8 @@ // Test for threads spawned with wqthread_start -// RUN: LSAN_BASE="report_objects=1:use_stacks=0:use_registers=0" // RUN: %clangxx_lsan %s -DDISPATCH_ASYNC -o %t-async -framework Foundation // RUN: %clangxx_lsan %s -DDISPATCH_SYNC -o %t-sync -framework Foundation -// RUN: %env_lsan_opts=$LSAN_BASE not %run %t-async 2>&1 | FileCheck %s -// RUN: %env_lsan_opts=$LSAN_BASE not %run %t-sync 2>&1 | FileCheck %s +// RUN: %env_lsan_opts="report_objects=1:use_stacks=0:use_registers=0" not %run %t-async 2>&1 | FileCheck %s +// RUN: %env_lsan_opts="report_objects=1:use_stacks=0:use_registers=0" not %run %t-sync 2>&1 | FileCheck %s #include #include Index: compiler-rt/test/lsan/TestCases/Linux/cleanup_in_tsd_destructor.c =================================================================== --- compiler-rt/test/lsan/TestCases/Linux/cleanup_in_tsd_destructor.c +++ compiler-rt/test/lsan/TestCases/Linux/cleanup_in_tsd_destructor.c @@ -3,10 +3,9 @@ // user-installed TSD destructors have finished running (since they may contain // additional cleanup tasks). LSan doesn't actually meet that goal 100%, but it // makes its best effort. -// RUN: LSAN_BASE="report_objects=1:use_registers=0:use_stacks=0" // RUN: %clang_lsan %s -o %t -// RUN: %env_lsan_opts=$LSAN_BASE:use_tls=1 %run %t -// RUN: %env_lsan_opts=$LSAN_BASE:use_tls=0 not %run %t 2>&1 | FileCheck %s +// RUN: %env_lsan_opts="report_objects=1:use_registers=0:use_stacks=0:use_tls=1" %run %t +// RUN: %env_lsan_opts="report_objects=1:use_registers=0:use_stacks=0:use_tls=0" not %run %t 2>&1 | FileCheck %s // Investigate why it does not fail with use_stack=0 // UNSUPPORTED: arm-linux || armhf-linux Index: compiler-rt/test/lsan/TestCases/Linux/disabler_in_tsd_destructor.c =================================================================== --- compiler-rt/test/lsan/TestCases/Linux/disabler_in_tsd_destructor.c +++ compiler-rt/test/lsan/TestCases/Linux/disabler_in_tsd_destructor.c @@ -1,7 +1,6 @@ // Regression test. Disabler should not depend on TSD validity. -// RUN: LSAN_BASE="report_objects=1:use_registers=0:use_stacks=0:use_tls=1:use_ld_allocations=0" // RUN: %clang_lsan %s -o %t -// RUN: %env_lsan_opts=$LSAN_BASE %run %t +// RUN: %env_lsan_opts="report_objects=1:use_registers=0:use_stacks=0:use_tls=1:use_ld_allocations=0" %run %t #include #include Index: compiler-rt/test/lsan/TestCases/Linux/use_tls_dynamic.cpp =================================================================== --- compiler-rt/test/lsan/TestCases/Linux/use_tls_dynamic.cpp +++ compiler-rt/test/lsan/TestCases/Linux/use_tls_dynamic.cpp @@ -4,11 +4,10 @@ // https://bugs.llvm.org/show_bug.cgi?id=37804 // XFAIL: glibc-2.27 -// RUN: LSAN_BASE="report_objects=1:use_stacks=0:use_registers=0:use_ld_allocations=0" // RUN: %clangxx %s -DBUILD_DSO -fPIC -shared -o %t-so.so // RUN: %clangxx_lsan %s -o %t -// RUN: %env_lsan_opts=$LSAN_BASE:"use_tls=0" not %run %t 2>&1 | FileCheck %s -// RUN: %env_lsan_opts=$LSAN_BASE:"use_tls=1" %run %t 2>&1 +// RUN: %env_lsan_opts="report_objects=1:use_stacks=0:use_registers=0:use_ld_allocations=0:use_tls=0" not %run %t 2>&1 | FileCheck %s +// RUN: %env_lsan_opts="report_objects=1:use_stacks=0:use_registers=0:use_ld_allocations=0:use_tls=1" %run %t 2>&1 // RUN: %env_lsan_opts="" %run %t 2>&1 // UNSUPPORTED: arm,powerpc,i386-linux && !android Index: compiler-rt/test/lsan/TestCases/Linux/use_tls_pthread_specific_dynamic.cpp =================================================================== --- compiler-rt/test/lsan/TestCases/Linux/use_tls_pthread_specific_dynamic.cpp +++ compiler-rt/test/lsan/TestCases/Linux/use_tls_pthread_specific_dynamic.cpp @@ -1,8 +1,7 @@ // Test that dynamically allocated thread-specific storage is included in the root set. -// RUN: LSAN_BASE="report_objects=1:use_stacks=0:use_registers=0" // RUN: %clangxx_lsan %s -o %t -// RUN: %env_lsan_opts=$LSAN_BASE:"use_tls=0" not %run %t 2>&1 | FileCheck %s -// RUN: %env_lsan_opts=$LSAN_BASE:"use_tls=1" %run %t 2>&1 +// RUN: %env_lsan_opts="report_objects=1:use_stacks=0:use_registers=0:use_tls=0" not %run %t 2>&1 | FileCheck %s +// RUN: %env_lsan_opts="report_objects=1:use_stacks=0:use_registers=0:use_tls=1" %run %t 2>&1 // RUN: %env_lsan_opts="" %run %t 2>&1 // Investigate why it does not fail with use_tls=0 Index: compiler-rt/test/lsan/TestCases/Linux/use_tls_pthread_specific_static.cpp =================================================================== --- compiler-rt/test/lsan/TestCases/Linux/use_tls_pthread_specific_static.cpp +++ compiler-rt/test/lsan/TestCases/Linux/use_tls_pthread_specific_static.cpp @@ -1,8 +1,7 @@ // Test that statically allocated thread-specific storage is included in the root set. -// RUN: LSAN_BASE="report_objects=1:use_stacks=0:use_registers=0" // RUN: %clangxx_lsan %s -o %t -// RUN: %env_lsan_opts=$LSAN_BASE:"use_tls=0" not %run %t 2>&1 | FileCheck %s -// RUN: %env_lsan_opts=$LSAN_BASE:"use_tls=1" %run %t 2>&1 +// RUN: %env_lsan_opts="report_objects=1:use_stacks=0:use_registers=0:use_tls=0" not %run %t 2>&1 | FileCheck %s +// RUN: %env_lsan_opts="report_objects=1:use_stacks=0:use_registers=0:use_tls=1" %run %t 2>&1 // RUN: %env_lsan_opts="" %run %t 2>&1 #include Index: compiler-rt/test/lsan/TestCases/Linux/use_tls_static.cpp =================================================================== --- compiler-rt/test/lsan/TestCases/Linux/use_tls_static.cpp +++ compiler-rt/test/lsan/TestCases/Linux/use_tls_static.cpp @@ -1,8 +1,7 @@ // Test that statically allocated TLS space is included in the root set. -// RUN: LSAN_BASE="report_objects=1:use_stacks=0:use_registers=0" // RUN: %clangxx_lsan %s -o %t -// RUN: %env_lsan_opts=$LSAN_BASE:"use_tls=0" not %run %t 2>&1 | FileCheck %s -// RUN: %env_lsan_opts=$LSAN_BASE:"use_tls=1" %run %t 2>&1 +// RUN: %env_lsan_opts="report_objects=1:use_stacks=0:use_registers=0:use_tls=0" not %run %t 2>&1 | FileCheck %s +// RUN: %env_lsan_opts="report_objects=1:use_stacks=0:use_registers=0:use_tls=1" %run %t 2>&1 // RUN: %env_lsan_opts="" %run %t 2>&1 #include Index: compiler-rt/test/lsan/TestCases/disabler.c =================================================================== --- compiler-rt/test/lsan/TestCases/disabler.c +++ compiler-rt/test/lsan/TestCases/disabler.c @@ -1,7 +1,6 @@ // Test for __lsan_disable() / __lsan_enable(). -// RUN: LSAN_BASE="report_objects=1:use_registers=0:use_stacks=0:use_tls=0" // RUN: %clang_lsan %s -o %t -// RUN: %env_lsan_opts=$LSAN_BASE not %run %t 2>&1 | FileCheck %s +// RUN: %env_lsan_opts=report_objects=1:use_registers=0:use_stacks=0:use_tls=0 not %run %t 2>&1 | FileCheck %s // Investigate why it does not fail with use_tls=0 // UNSUPPORTED: arm-linux || armhf-linux Index: compiler-rt/test/lsan/TestCases/disabler.cpp =================================================================== --- compiler-rt/test/lsan/TestCases/disabler.cpp +++ compiler-rt/test/lsan/TestCases/disabler.cpp @@ -1,7 +1,6 @@ // Test for ScopedDisabler. -// RUN: LSAN_BASE="report_objects=1:use_registers=0:use_stacks=0:use_tls=0" // RUN: %clangxx_lsan %s -o %t -// RUN: %env_lsan_opts=$LSAN_BASE not %run %t 2>&1 | FileCheck %s +// RUN: %env_lsan_opts=report_objects=1:use_registers=0:use_stacks=0:use_tls=0 not %run %t 2>&1 | FileCheck %s #include #include Index: compiler-rt/test/lsan/TestCases/do_leak_check_override.cpp =================================================================== --- compiler-rt/test/lsan/TestCases/do_leak_check_override.cpp +++ compiler-rt/test/lsan/TestCases/do_leak_check_override.cpp @@ -1,10 +1,9 @@ // Test for __lsan_do_leak_check(). We test it by making the leak check run // before global destructors, which also tests compatibility with HeapChecker's // "normal" mode (LSan runs in "strict" mode by default). -// RUN: LSAN_BASE="use_stacks=0:use_registers=0" // RUN: %clangxx_lsan %s -o %t -// RUN: %env_lsan_opts=$LSAN_BASE not %run %t 2>&1 | FileCheck --check-prefix=CHECK-strict %s -// RUN: %env_lsan_opts=$LSAN_BASE not %run %t foo 2>&1 | FileCheck --check-prefix=CHECK-normal %s +// RUN: %env_lsan_opts=use_stacks=0:use_registers=0 not %run %t 2>&1 | FileCheck --check-prefix=CHECK-strict %s +// RUN: %env_lsan_opts=use_stacks=0:use_registers=0 not %run %t foo 2>&1 | FileCheck --check-prefix=CHECK-normal %s // Investigate why LeakyGlobal leak does show // UNSUPPORTED: arm-linux || armhf-linux Index: compiler-rt/test/lsan/TestCases/high_allocator_contention.cpp =================================================================== --- compiler-rt/test/lsan/TestCases/high_allocator_contention.cpp +++ compiler-rt/test/lsan/TestCases/high_allocator_contention.cpp @@ -1,8 +1,7 @@ // A benchmark that executes malloc/free pairs in parallel. // Usage: ./a.out number_of_threads total_number_of_allocations -// RUN: LSAN_BASE="use_ld_allocations=0" // RUN: %clangxx_lsan %s -o %t -// RUN: %env_lsan_opts=$LSAN_BASE %run %t 5 1000000 2>&1 +// RUN: %env_lsan_opts=use_ld_allocations=0 %run %t 5 1000000 2>&1 #include #include #include Index: compiler-rt/test/lsan/TestCases/ignore_object.c =================================================================== --- compiler-rt/test/lsan/TestCases/ignore_object.c +++ compiler-rt/test/lsan/TestCases/ignore_object.c @@ -1,7 +1,6 @@ // Test for __lsan_ignore_object(). -// RUN: LSAN_BASE="report_objects=1:use_registers=0:use_stacks=0:use_tls=0" // RUN: %clang_lsan %s -o %t -// RUN: %env_lsan_opts=$LSAN_BASE not %run %t 2>&1 | FileCheck %s +// RUN: %env_lsan_opts=report_objects=1:use_registers=0:use_stacks=0:use_tls=0 not %run %t 2>&1 | FileCheck %s // Investigate why it does not fail with use_stack=0 // UNSUPPORTED: arm-linux || armhf-linux Index: compiler-rt/test/lsan/TestCases/large_allocation_leak.cpp =================================================================== --- compiler-rt/test/lsan/TestCases/large_allocation_leak.cpp +++ compiler-rt/test/lsan/TestCases/large_allocation_leak.cpp @@ -1,7 +1,6 @@ // Test that LargeMmapAllocator's chunks aren't reachable via some internal data structure. -// RUN: LSAN_BASE="report_objects=1:use_stacks=0:use_registers=0" // RUN: %clangxx_lsan %s -o %t -// RUN: %env_lsan_opts=$LSAN_BASE not %run %t 2>&1 | FileCheck %s +// RUN: %env_lsan_opts=report_objects=1:use_stacks=0:use_registers=0 not %run %t 2>&1 | FileCheck %s // For 32 bit LSan it's pretty likely that large chunks are "reachable" from some // internal data structures (e.g. Glibc global data). Index: compiler-rt/test/lsan/TestCases/leak_check_at_exit.cpp =================================================================== --- compiler-rt/test/lsan/TestCases/leak_check_at_exit.cpp +++ compiler-rt/test/lsan/TestCases/leak_check_at_exit.cpp @@ -1,10 +1,9 @@ // Test for the leak_check_at_exit flag. -// RUN: LSAN_BASE="use_stacks=0:use_registers=0" // RUN: %clangxx_lsan %s -o %t -// RUN: %env_lsan_opts=$LSAN_BASE not %run %t foo 2>&1 | FileCheck %s --check-prefix=CHECK-do -// RUN: %env_lsan_opts=$LSAN_BASE not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-do -// RUN: %env_lsan_opts=$LSAN_BASE:"leak_check_at_exit=0" not %run %t foo 2>&1 | FileCheck %s --check-prefix=CHECK-do -// RUN: %env_lsan_opts=$LSAN_BASE:"leak_check_at_exit=0" %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-dont +// RUN: %env_lsan_opts=use_stacks=0:use_registers=0 not %run %t foo 2>&1 | FileCheck %s --check-prefix=CHECK-do +// RUN: %env_lsan_opts=use_stacks=0:use_registers=0 not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-do +// RUN: %env_lsan_opts=use_stacks=0:use_registers=0:leak_check_at_exit=0 not %run %t foo 2>&1 | FileCheck %s --check-prefix=CHECK-do +// RUN: %env_lsan_opts=use_stacks=0:use_registers=0:leak_check_at_exit=0 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-dont #include #include Index: compiler-rt/test/lsan/TestCases/link_turned_off.cpp =================================================================== --- compiler-rt/test/lsan/TestCases/link_turned_off.cpp +++ compiler-rt/test/lsan/TestCases/link_turned_off.cpp @@ -1,8 +1,7 @@ // Test for disabling LSan at link-time. -// RUN: LSAN_BASE="use_stacks=0:use_registers=0" // RUN: %clangxx_lsan %s -o %t -// RUN: %env_lsan_opts=$LSAN_BASE %run %t -// RUN: %env_lsan_opts=$LSAN_BASE not %run %t foo 2>&1 | FileCheck %s +// RUN: %env_lsan_opts=use_stacks=0:use_registers=0 %run %t +// RUN: %env_lsan_opts=use_stacks=0:use_registers=0 not %run %t foo 2>&1 | FileCheck %s // // UNSUPPORTED: darwin Index: compiler-rt/test/lsan/TestCases/many_tls_keys_pthread.cpp =================================================================== --- compiler-rt/test/lsan/TestCases/many_tls_keys_pthread.cpp +++ compiler-rt/test/lsan/TestCases/many_tls_keys_pthread.cpp @@ -1,8 +1,7 @@ // Test that lsan handles tls correctly for many threads -// RUN: LSAN_BASE="report_objects=1:use_stacks=0:use_registers=0" // RUN: %clangxx_lsan %s -o %t -// RUN: %env_lsan_opts=$LSAN_BASE:"use_tls=0" not %run %t 2>&1 | FileCheck %s -// RUN: %env_lsan_opts=$LSAN_BASE:"use_tls=1" %run %t 2>&1 +// RUN: %env_lsan_opts="report_objects=1:use_stacks=0:use_registers=0:use_tls=0" not %run %t 2>&1 | FileCheck %s +// RUN: %env_lsan_opts="report_objects=1:use_stacks=0:use_registers=0:use_tls=1" %run %t 2>&1 // RUN: %env_lsan_opts="" %run %t 2>&1 // On glibc, this requires the range returned by GetTLS to include Index: compiler-rt/test/lsan/TestCases/many_tls_keys_thread.cpp =================================================================== --- compiler-rt/test/lsan/TestCases/many_tls_keys_thread.cpp +++ compiler-rt/test/lsan/TestCases/many_tls_keys_thread.cpp @@ -1,8 +1,7 @@ // Test that lsan handles tls correctly for many threads -// RUN: LSAN_BASE="report_objects=1:use_stacks=0:use_registers=0" // RUN: %clangxx_lsan %s -o %t -// RUN: %env_lsan_opts=$LSAN_BASE:"use_tls=0" not %run %t 2>&1 | FileCheck %s -// RUN: %env_lsan_opts=$LSAN_BASE:"use_tls=1" %run %t 2>&1 +// RUN: %env_lsan_opts="report_objects=1:use_stacks=0:use_registers=0:use_tls=0" not %run %t 2>&1 | FileCheck %s +// RUN: %env_lsan_opts="report_objects=1:use_stacks=0:use_registers=0:use_tls=1" %run %t 2>&1 // RUN: %env_lsan_opts="" %run %t 2>&1 // Patch r303906 did not fix all the problems. Index: compiler-rt/test/lsan/TestCases/pointer_to_self.cpp =================================================================== --- compiler-rt/test/lsan/TestCases/pointer_to_self.cpp +++ compiler-rt/test/lsan/TestCases/pointer_to_self.cpp @@ -1,8 +1,7 @@ // Regression test: pointers to self should not confuse LSan into thinking the // object is indirectly leaked. Only external pointers count. -// RUN: LSAN_BASE="report_objects=1:use_registers=0" // RUN: %clangxx_lsan %s -o %t -// RUN: %env_lsan_opts=$LSAN_BASE:"use_stacks=0" not %run %t 2>&1 | FileCheck %s +// RUN: %env_lsan_opts="report_objects=1:use_registers=0:use_stacks=0" not %run %t 2>&1 | FileCheck %s #include #include Index: compiler-rt/test/lsan/TestCases/print_suppressions.cpp =================================================================== --- compiler-rt/test/lsan/TestCases/print_suppressions.cpp +++ compiler-rt/test/lsan/TestCases/print_suppressions.cpp @@ -1,11 +1,10 @@ // Print matched suppressions only if print_suppressions=1 AND at least one is // matched. Default is print_suppressions=true. -// RUN: LSAN_BASE="use_registers=0:use_stacks=0" // RUN: %clangxx_lsan %s -o %t -// RUN: %env_lsan_opts=$LSAN_BASE:print_suppressions=0 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-dont-print -// RUN: %env_lsan_opts=$LSAN_BASE %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-dont-print -// RUN: %env_lsan_opts=$LSAN_BASE:print_suppressions=0 %run %t foo 2>&1 | FileCheck %s --check-prefix=CHECK-dont-print -// RUN: %env_lsan_opts=$LSAN_BASE %run %t foo 2>&1 | FileCheck %s --check-prefix=CHECK-print +// RUN: %env_lsan_opts=use_registers=0:use_stacks=0:print_suppressions=0 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-dont-print +// RUN: %env_lsan_opts=use_registers=0:use_stacks=0 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-dont-print +// RUN: %env_lsan_opts=use_registers=0:use_stacks=0:print_suppressions=0 %run %t foo 2>&1 | FileCheck %s --check-prefix=CHECK-dont-print +// RUN: %env_lsan_opts=use_registers=0:use_stacks=0 %run %t foo 2>&1 | FileCheck %s --check-prefix=CHECK-print #include #include Index: compiler-rt/test/lsan/TestCases/recoverable_leak_check.cpp =================================================================== --- compiler-rt/test/lsan/TestCases/recoverable_leak_check.cpp +++ compiler-rt/test/lsan/TestCases/recoverable_leak_check.cpp @@ -1,8 +1,7 @@ // Test for on-demand leak checking. -// RUN: LSAN_BASE="use_stacks=0:use_registers=0" // RUN: %clangxx_lsan %s -o %t -// RUN: %env_lsan_opts=$LSAN_BASE %run %t foo 2>&1 | FileCheck %s -// RUN: %env_lsan_opts=$LSAN_BASE %run %t 2>&1 | FileCheck %s +// RUN: %env_lsan_opts=use_stacks=0:use_registers=0 %run %t foo 2>&1 | FileCheck %s +// RUN: %env_lsan_opts=use_stacks=0:use_registers=0 %run %t 2>&1 | FileCheck %s // // UNSUPPORTED: darwin Index: compiler-rt/test/lsan/TestCases/register_root_region.cpp =================================================================== --- compiler-rt/test/lsan/TestCases/register_root_region.cpp +++ compiler-rt/test/lsan/TestCases/register_root_region.cpp @@ -1,9 +1,8 @@ // Test for __lsan_(un)register_root_region(). -// RUN: LSAN_BASE="use_stacks=0:use_registers=0" // RUN: %clangxx_lsan %s -o %t -// RUN: %env_lsan_opts=$LSAN_BASE %run %t -// RUN: %env_lsan_opts=$LSAN_BASE not %run %t foo 2>&1 | FileCheck %s -// RUN: %env_lsan_opts=$LSAN_BASE:use_root_regions=0 not %run %t 2>&1 | FileCheck %s +// RUN: %env_lsan_opts=use_stacks=0:use_registers=0 %run %t +// RUN: %env_lsan_opts=use_stacks=0:use_registers=0 not %run %t foo 2>&1 | FileCheck %s +// RUN: %env_lsan_opts=use_stacks=0:use_registers=0:use_root_regions=0 not %run %t 2>&1 | FileCheck %s #include #include Index: compiler-rt/test/lsan/TestCases/stale_stack_leak.cpp =================================================================== --- compiler-rt/test/lsan/TestCases/stale_stack_leak.cpp +++ compiler-rt/test/lsan/TestCases/stale_stack_leak.cpp @@ -1,5 +1,4 @@ // Test that out-of-scope local variables are ignored by LSan. -// RUN: LSAN_BASE="report_objects=1:use_registers=0:use_stacks=1" // LSan-in-ASan fails at -O0 on aarch64, because the stack use-after-return // instrumentation stashes the argument to `PutPointerOnStaleStack` on the stack @@ -10,8 +9,8 @@ // callee-saved register for rematerialization instead. // RUN: %clangxx_lsan -O1 %s -o %t -// RUN: %env_lsan_opts=$LSAN_BASE not %run %t 2>&1 | FileCheck %s -// RUN: %env_lsan_opts=$LSAN_BASE":exitcode=0" %run %t 2>&1 | FileCheck --check-prefix=CHECK-sanity %s +// RUN: %env_lsan_opts="report_objects=1:use_registers=0:use_stacks=1" not %run %t 2>&1 | FileCheck %s +// RUN: %env_lsan_opts="report_objects=1:use_registers=0:use_stacks=1:exitcode=0" %run %t 2>&1 | FileCheck --check-prefix=CHECK-sanity %s // // x86 passes parameters through stack that may lead to false negatives // The same applies to s390x register save areas. Index: compiler-rt/test/lsan/TestCases/suppressions_default.cpp =================================================================== --- compiler-rt/test/lsan/TestCases/suppressions_default.cpp +++ compiler-rt/test/lsan/TestCases/suppressions_default.cpp @@ -1,6 +1,5 @@ -// RUN: LSAN_BASE="use_registers=0:use_stacks=0" // RUN: %clangxx_lsan %s -o %t -// RUN: %env_lsan_opts=$LSAN_BASE not %run %t 2>&1 | FileCheck %s +// RUN: %env_lsan_opts=use_registers=0:use_stacks=0 not %run %t 2>&1 | FileCheck %s #include #include Index: compiler-rt/test/lsan/TestCases/suppressions_file.cpp =================================================================== --- compiler-rt/test/lsan/TestCases/suppressions_file.cpp +++ compiler-rt/test/lsan/TestCases/suppressions_file.cpp @@ -1,18 +1,17 @@ -// RUN: LSAN_BASE="use_registers=0:use_stacks=0" // RUN: %clangxx_lsan %s -o %t // RUN: rm -f %t.supp // RUN: touch %t.supp // RUN: %push_to_device %t.supp %device_rundir/%t.supp -// RUN: %env_lsan_opts="$LSAN_BASE:suppressions='%device_rundir/%t.supp'" not %run %t 2>&1 | FileCheck %s --check-prefix=NOSUPP +// RUN: %env_lsan_opts="use_registers=0:use_stacks=0:suppressions='%device_rundir/%t.supp'" not %run %t 2>&1 | FileCheck %s --check-prefix=NOSUPP // RUN: echo "leak:*LSanTestLeakingFunc*" > %t.supp // RUN: %push_to_device %t.supp %device_rundir/%t.supp -// RUN: %env_lsan_opts="$LSAN_BASE:suppressions='%device_rundir/%t.supp'" not %run %t 2>&1 | FileCheck %s +// RUN: %env_lsan_opts="use_registers=0:use_stacks=0:suppressions='%device_rundir/%t.supp'" not %run %t 2>&1 | FileCheck %s // // RUN: echo "leak:%t" > %t.supp // RUN: %push_to_device %t.supp %device_rundir/%t.supp -// RUN: %env_lsan_opts="$LSAN_BASE:suppressions='%device_rundir/%t.supp':symbolize=false" %run %t +// RUN: %env_lsan_opts="use_registers=0:use_stacks=0:suppressions='%device_rundir/%t.supp':symbolize=false" %run %t #include #include Index: compiler-rt/test/lsan/TestCases/use_after_return.cpp =================================================================== --- compiler-rt/test/lsan/TestCases/use_after_return.cpp +++ compiler-rt/test/lsan/TestCases/use_after_return.cpp @@ -1,10 +1,9 @@ // Test that fake stack (introduced by ASan's use-after-return mode) is included // in the root set. -// RUN: LSAN_BASE="report_objects=1:use_registers=0" // RUN: %clangxx_lsan %s -O2 -o %t -// RUN: ASAN_OPTIONS=detect_stack_use_after_return=1 %env_lsan_opts=$LSAN_BASE:"use_stacks=0" not %run %t 2>&1 | FileCheck %s -// RUN: ASAN_OPTIONS=detect_stack_use_after_return=1 %env_lsan_opts=$LSAN_BASE:"use_stacks=1" %run %t 2>&1 -// RUN: ASAN_OPTIONS=detect_stack_use_after_return=1 %env_lsan_opts="" %run %t 2>&1 +// RUN: env ASAN_OPTIONS=detect_stack_use_after_return=1 %env_lsan_opts="report_objects=1:use_registers=0:use_stacks=0" not %run %t 2>&1 | FileCheck %s +// RUN: env ASAN_OPTIONS=detect_stack_use_after_return=1 %env_lsan_opts="report_objects=1:use_registers=0:use_stacks=1" %run %t 2>&1 +// RUN: env ASAN_OPTIONS=detect_stack_use_after_return=1 %env_lsan_opts="" %run %t 2>&1 // Investigate why it does not fail with use_stack=0 // UNSUPPORTED: arm-linux || armhf-linux Index: compiler-rt/test/lsan/TestCases/use_globals_initialized.cpp =================================================================== --- compiler-rt/test/lsan/TestCases/use_globals_initialized.cpp +++ compiler-rt/test/lsan/TestCases/use_globals_initialized.cpp @@ -1,8 +1,7 @@ // Test that initialized globals are included in the root set. -// RUN: LSAN_BASE="report_objects=1:use_stacks=0:use_registers=0" // RUN: %clangxx_lsan %s -o %t -// RUN: %env_lsan_opts=$LSAN_BASE:"use_globals=0" not %run %t 2>&1 | FileCheck %s -// RUN: %env_lsan_opts=$LSAN_BASE:"use_globals=1" %run %t 2>&1 +// RUN: %env_lsan_opts="report_objects=1:use_stacks=0:use_registers=0:use_globals=0" not %run %t 2>&1 | FileCheck %s +// RUN: %env_lsan_opts="report_objects=1:use_stacks=0:use_registers=0:use_globals=1" %run %t 2>&1 // RUN: %env_lsan_opts="" %run %t 2>&1 #include Index: compiler-rt/test/lsan/TestCases/use_globals_uninitialized.cpp =================================================================== --- compiler-rt/test/lsan/TestCases/use_globals_uninitialized.cpp +++ compiler-rt/test/lsan/TestCases/use_globals_uninitialized.cpp @@ -1,8 +1,7 @@ // Test that uninitialized globals are included in the root set. -// RUN: LSAN_BASE="report_objects=1:use_stacks=0:use_registers=0" // RUN: %clangxx_lsan %s -o %t -// RUN: %env_lsan_opts=$LSAN_BASE:"use_globals=0" not %run %t 2>&1 | FileCheck %s -// RUN: %env_lsan_opts=$LSAN_BASE:"use_globals=1" %run %t 2>&1 +// RUN: %env_lsan_opts="report_objects=1:use_stacks=0:use_registers=0:use_globals=0" not %run %t 2>&1 | FileCheck %s +// RUN: %env_lsan_opts="report_objects=1:use_stacks=0:use_registers=0:use_globals=1" %run %t 2>&1 // RUN: %env_lsan_opts="" %run %t 2>&1 #include Index: compiler-rt/test/lsan/TestCases/use_globals_unused.cpp =================================================================== --- compiler-rt/test/lsan/TestCases/use_globals_unused.cpp +++ compiler-rt/test/lsan/TestCases/use_globals_unused.cpp @@ -1,12 +1,11 @@ // Test that unused globals are included in the root set. // RUN: %clangxx_lsan -O2 %s -DTEST_LIB -c -o %t.o // RUN: %clangxx_lsan -O2 %s %t.o -o %t -// RUN: LSAN_BASE="use_stacks=0:use_registers=0" -// RUN: %env_lsan_opts=$LSAN_BASE:"use_globals=1" %run %t 2>&1 | FileCheck %s --implicit-check-not=leak +// RUN: %env_lsan_opts="use_stacks=0:use_registers=0:use_globals=1" %run %t 2>&1 | FileCheck %s --implicit-check-not=leak // RUN: %env_lsan_opts="" %run %t 2>&1 | FileCheck %s --implicit-check-not=leak // FIXME: This check is not very important and fails on arm7. -// %env_lsan_opts=$LSAN_BASE:"use_globals=0" not %run %t 2>&1 | FileCheck %s --check-prefixes=LEAK +// %env_lsan_opts="use_stacks=0:use_registers=0:use_globals=0" not %run %t 2>&1 | FileCheck %s --check-prefixes=LEAK #include #include Index: compiler-rt/test/lsan/TestCases/use_poisoned_asan.cpp =================================================================== --- compiler-rt/test/lsan/TestCases/use_poisoned_asan.cpp +++ compiler-rt/test/lsan/TestCases/use_poisoned_asan.cpp @@ -1,9 +1,8 @@ // ASan-poisoned memory should be ignored if use_poisoned is false. // REQUIRES: asan -// RUN: LSAN_BASE="report_objects=1:use_stacks=0:use_registers=0" // RUN: %clangxx_lsan %s -o %t -// RUN: %env_lsan_opts=$LSAN_BASE:"use_poisoned=0" not %run %t 2>&1 | FileCheck %s -// RUN: %env_lsan_opts=$LSAN_BASE:"use_poisoned=1" %run %t 2>&1 +// RUN: %env_lsan_opts="report_objects=1:use_stacks=0:use_registers=0:use_poisoned=0" not %run %t 2>&1 | FileCheck %s +// RUN: %env_lsan_opts="report_objects=1:use_stacks=0:use_registers=0:use_poisoned=1" %run %t 2>&1 #include #include Index: compiler-rt/test/lsan/TestCases/use_registers.cpp =================================================================== --- compiler-rt/test/lsan/TestCases/use_registers.cpp +++ compiler-rt/test/lsan/TestCases/use_registers.cpp @@ -1,8 +1,7 @@ // Test that registers of running threads are included in the root set. -// RUN: LSAN_BASE="report_objects=1:use_stacks=0" // RUN: %clangxx_lsan -pthread %s -o %t -// RUN: %env_lsan_opts=$LSAN_BASE:"use_registers=0" not %run %t 2>&1 | FileCheck %s -// RUN: %env_lsan_opts=$LSAN_BASE:"use_registers=1" %run %t 2>&1 +// RUN: %env_lsan_opts="report_objects=1:use_stacks=0:use_registers=0" not %run %t 2>&1 | FileCheck %s +// RUN: %env_lsan_opts="report_objects=1:use_stacks=0:use_registers=1" %run %t 2>&1 // RUN: %env_lsan_opts="" %run %t 2>&1 #include "sanitizer_common/print_address.h" Index: compiler-rt/test/lsan/TestCases/use_registers_extra.cpp =================================================================== --- compiler-rt/test/lsan/TestCases/use_registers_extra.cpp +++ compiler-rt/test/lsan/TestCases/use_registers_extra.cpp @@ -1,8 +1,7 @@ // Test that registers of running threads are included in the root set. -// RUN: LSAN_BASE="report_objects=1:use_stacks=0" // RUN: %clangxx_lsan -pthread %s -o %t -// RUN: %env_lsan_opts=$LSAN_BASE:"use_registers=0" not %run %t 2>&1 | FileCheck %s -// RUN: %env_lsan_opts=$LSAN_BASE:"use_registers=1" %run %t 2>&1 +// RUN: %env_lsan_opts="report_objects=1:use_stacks=0:use_registers=0" not %run %t 2>&1 | FileCheck %s +// RUN: %env_lsan_opts="report_objects=1:use_stacks=0:use_registers=1" %run %t 2>&1 // RUN: %env_lsan_opts="" %run %t 2>&1 // FIXME: Support more platforms. Index: compiler-rt/test/lsan/TestCases/use_stacks.cpp =================================================================== --- compiler-rt/test/lsan/TestCases/use_stacks.cpp +++ compiler-rt/test/lsan/TestCases/use_stacks.cpp @@ -1,8 +1,7 @@ // Test that stack of main thread is included in the root set. -// RUN: LSAN_BASE="report_objects=1:use_registers=0" // RUN: %clangxx_lsan %s -o %t -// RUN: %env_lsan_opts=$LSAN_BASE:"use_stacks=0" not %run %t 2>&1 | FileCheck %s -// RUN: %env_lsan_opts=$LSAN_BASE:"use_stacks=1" %run %t 2>&1 +// RUN: %env_lsan_opts="report_objects=1:use_registers=0:use_stacks=0" not %run %t 2>&1 | FileCheck %s +// RUN: %env_lsan_opts="report_objects=1:use_registers=0:use_stacks=1" %run %t 2>&1 // RUN: %env_lsan_opts="" %run %t 2>&1 #include Index: compiler-rt/test/lsan/TestCases/use_stacks_threaded.cpp =================================================================== --- compiler-rt/test/lsan/TestCases/use_stacks_threaded.cpp +++ compiler-rt/test/lsan/TestCases/use_stacks_threaded.cpp @@ -1,8 +1,7 @@ // Test that stacks of non-main threads are included in the root set. -// RUN: LSAN_BASE="report_objects=1:use_registers=0" // RUN: %clangxx_lsan -pthread %s -o %t -// RUN: %env_lsan_opts=$LSAN_BASE:"use_stacks=0" not %run %t 2>&1 | FileCheck %s -// RUN: %env_lsan_opts=$LSAN_BASE:"use_stacks=1" %run %t 2>&1 +// RUN: %env_lsan_opts="report_objects=1:use_registers=0:use_stacks=0" not %run %t 2>&1 | FileCheck %s +// RUN: %env_lsan_opts="report_objects=1:use_registers=0:use_stacks=1" %run %t 2>&1 // RUN: %env_lsan_opts="" %run %t 2>&1 #include Index: compiler-rt/test/lsan/TestCases/use_unaligned.cpp =================================================================== --- compiler-rt/test/lsan/TestCases/use_unaligned.cpp +++ compiler-rt/test/lsan/TestCases/use_unaligned.cpp @@ -1,8 +1,7 @@ // Test that unaligned pointers are detected correctly. -// RUN: LSAN_BASE="report_objects=1:use_stacks=0:use_registers=0" // RUN: %clangxx_lsan %s -o %t -// RUN: %env_lsan_opts=$LSAN_BASE:"use_unaligned=0" not %run %t 2>&1 | FileCheck %s -// RUN: %env_lsan_opts=$LSAN_BASE:"use_unaligned=1" %run %t 2>&1 +// RUN: %env_lsan_opts="report_objects=1:use_stacks=0:use_registers=0:use_unaligned=0" not %run %t 2>&1 | FileCheck %s +// RUN: %env_lsan_opts="report_objects=1:use_stacks=0:use_registers=0:use_unaligned=1" %run %t 2>&1 #include #include Index: compiler-rt/test/lsan/lit.common.cfg.py =================================================================== --- compiler-rt/test/lsan/lit.common.cfg.py +++ compiler-rt/test/lsan/lit.common.cfg.py @@ -22,7 +22,8 @@ # Choose between standalone and LSan+ASan modes. lsan_lit_test_mode = get_required_attr(config, 'lsan_lit_test_mode') -if lsan_lit_test_mode == "Standalone": +# FIXME: All tests are Standalone on Windows for now. Since all win32 function calls in lsan get intercepted by asan :( +if lsan_lit_test_mode == "Standalone" or config.host_os == 'Windows': config.name = "LeakSanitizer-Standalone" lsan_cflags = ["-fsanitize=leak"] elif lsan_lit_test_mode == "AddressSanitizer": @@ -74,12 +75,13 @@ config.substitutions.append( ("%clangxx_lsan ", build_invocation(clang_lsan_cxxflags)) ) # LeakSanitizer tests are currently supported on -# Android{aarch64, x86, x86_64}, x86-64 Linux, PowerPC64 Linux, arm Linux, mips64 Linux, s390x Linux and x86_64 Darwin. +# Windows{x86_64, x86, aarch64, arm}, Android{aarch64, x86, x86_64}, x86-64 Linux, PowerPC64 Linux, arm Linux, mips64 Linux, s390x Linux and x86_64 Darwin. supported_android = config.android and config.target_arch in ['x86_64', 'i386', 'aarch64'] and 'android-thread-properties-api' in config.available_features supported_linux = (not config.android) and config.host_os == 'Linux' and config.host_arch in ['aarch64', 'x86_64', 'ppc64', 'ppc64le', 'mips64', 'riscv64', 'arm', 'armhf', 'armv7l', 's390x'] supported_darwin = config.host_os == 'Darwin' and config.target_arch in ['x86_64'] supported_netbsd = config.host_os == 'NetBSD' and config.target_arch in ['x86_64', 'i386'] -if not (supported_android or supported_linux or supported_darwin or supported_netbsd): +supported_windows = config.host_os == 'Windows' and config.target_arch in ['x86_64', 'i386', 'aarch64', 'arm'] +if not (supported_android or supported_linux or supported_darwin or supported_netbsd or supported_windows): config.unsupported = True # Don't support Thumb due to broken fast unwinder