clemenswasser updated this revision to Diff 424702. clemenswasser added a comment.
I have now split the lsan TestCases chages into https://reviews.llvm.org/D124322 and managed to get the lsan+asan TestCases nearly to work. The current problem is, that during the start of the `RunThread` in `StopTheWorld`, we are intercepting a call to `calloc` done by the ucrt in `ucrtbase!DllMainDispatch`, which somehow results in a deadlock. If someone has an idea, how we could avoid/fix this, I would be very happy to hear it. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D115103/new/ https://reviews.llvm.org/D115103 Files: clang/lib/Driver/ToolChains/MSVC.cpp compiler-rt/lib/lsan/CMakeLists.txt compiler-rt/lib/lsan/lsan.h compiler-rt/lib/lsan/lsan_allocator.h compiler-rt/lib/lsan/lsan_common.cpp compiler-rt/lib/lsan/lsan_common.h compiler-rt/lib/lsan/lsan_common_win.cpp compiler-rt/lib/lsan/lsan_interceptors.cpp compiler-rt/lib/lsan/lsan_win.cpp compiler-rt/lib/lsan/lsan_win.h compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_win.cpp compiler-rt/test/lsan/lit.common.cfg.py
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 @@ -74,12 +74,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 Index: compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_win.cpp =================================================================== --- compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_win.cpp +++ compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_win.cpp @@ -19,8 +19,13 @@ // windows.h needs to be included before tlhelp32.h # include <tlhelp32.h> +# include "interception/interception.h" # include "sanitizer_stoptheworld.h" +DECLARE_REAL(HANDLE, CreateThread, LPSECURITY_ATTRIBUTES lpThreadAttributes, + SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, + LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId); + namespace __sanitizer { namespace { @@ -163,7 +168,7 @@ DWORD trace_thread_id; auto trace_thread = - CreateThread(nullptr, 0, RunThread, &arg, 0, &trace_thread_id); + REAL(CreateThread)(nullptr, 0, RunThread, &arg, 0, &trace_thread_id); CHECK(trace_thread); WaitForSingleObject(trace_thread, INFINITE); Index: compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h =================================================================== --- compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -485,13 +485,15 @@ #define SANITIZER_INTERCEPT_MMAP SI_POSIX #define SANITIZER_INTERCEPT_MMAP64 SI_LINUX_NOT_ANDROID || SI_SOLARIS #define SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO (SI_GLIBC || SI_ANDROID) -#define SANITIZER_INTERCEPT_MEMALIGN (!SI_FREEBSD && !SI_MAC && !SI_NETBSD) +#define SANITIZER_INTERCEPT_MEMALIGN \ + (!SI_FREEBSD && !SI_MAC && !SI_NETBSD && !SI_WINDOWS) #define SANITIZER_INTERCEPT___LIBC_MEMALIGN SI_GLIBC #define SANITIZER_INTERCEPT_PVALLOC (SI_GLIBC || SI_ANDROID) #define SANITIZER_INTERCEPT_CFREE (SI_GLIBC && !SANITIZER_RISCV64) #define SANITIZER_INTERCEPT_REALLOCARRAY SI_POSIX #define SANITIZER_INTERCEPT_ALIGNED_ALLOC (!SI_MAC) -#define SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE (!SI_MAC && !SI_NETBSD) +#define SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE \ + (!SI_MAC && !SI_NETBSD && !SI_WINDOWS) #define SANITIZER_INTERCEPT_MCHECK_MPROBE SI_LINUX_NOT_ANDROID #define SANITIZER_INTERCEPT_WCSCAT SI_POSIX #define SANITIZER_INTERCEPT_WCSDUP SI_POSIX 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,111 @@ +//=-- 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<const OnStartedArgs *>(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<ThreadContext *>( + 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; } + +void InstallAtExitCheckLeaks() { + if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit) + Atexit(DoLeakCheck); +} + +} // 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/lib/lsan/lsan_interceptors.cpp =================================================================== --- compiler-rt/lib/lsan/lsan_interceptors.cpp +++ compiler-rt/lib/lsan/lsan_interceptors.cpp @@ -24,15 +24,20 @@ #include "sanitizer_common/sanitizer_platform_limits_netbsd.h" #include "sanitizer_common/sanitizer_platform_limits_posix.h" #if SANITIZER_POSIX -#include "sanitizer_common/sanitizer_posix.h" +# include "sanitizer_common/sanitizer_posix.h" #endif -#include "sanitizer_common/sanitizer_tls_get_addr.h" + +#if SANITIZER_WINDOWS +# include <Windows.h> +#endif + +#include <stddef.h> + #include "lsan.h" #include "lsan_allocator.h" #include "lsan_common.h" #include "lsan_thread.h" - -#include <stddef.h> +#include "sanitizer_common/sanitizer_tls_get_addr.h" using namespace __lsan; @@ -99,6 +104,11 @@ return lsan_realloc(ptr, size, stack); } +# if SANITIZER_WINDOWS +# define LSAN_MAYBE_INTERCEPT_POSIX_MEMALIGN +# define LSAN_MAYBE_INTERCEPT_VALLOC +# else + INTERCEPTOR(void*, reallocarray, void *q, uptr nmemb, uptr size) { ENSURE_LSAN_INITED; GET_STACK_TRACE_MALLOC; @@ -111,11 +121,19 @@ return lsan_posix_memalign(memptr, alignment, size, stack); } +# define LSAN_MAYBE_INTERCEPT_POSIX_MEMALIGN \ + INTERCEPT_FUNCTION(posix_memalign) + 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 @@ -143,12 +161,19 @@ #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 #endif @@ -244,9 +269,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 +298,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 +510,26 @@ return res; } +# define LSAN_MAYBE_INTERCEPT_PTHREAD_CREATE INTERCEPT_FUNCTION(pthread_create) + +#else +# define LSAN_MAYBE_INTERCEPT_PTHREAD_CREATE +#endif + +#if SANITIZER_POSIX + INTERCEPTOR(int, pthread_join, void *t, void **arg) { return REAL(pthread_join)(t, arg); } +# define LSAN_MAYBE_INTERCEPT_PTHREAD_CREATE INTERCEPT_FUNCTION(pthread_join) + +#else +# define LSAN_MAYBE_INTERCEPT_PTHREAD_JOIN +#endif + +#if SANITIZER_POSIX + DEFINE_REAL_PTHREAD_FUNCTIONS INTERCEPTOR(void, _exit, int status) { @@ -490,17 +537,71 @@ REAL(_exit)(status); } -#define COMMON_INTERCEPT_FUNCTION(name) INTERCEPT_FUNCTION(name) -#include "sanitizer_common/sanitizer_signal_interceptors.inc" +# define LSAN_MAYBE_INTERCEPT__EXIT INTERCEPT_FUNCTION(_exit) + +#else +# define LSAN_MAYBE_INTERCEPT__EXIT +#endif +#if SANITIZER_POSIX +# define COMMON_INTERCEPT_FUNCTION(name) INTERCEPT_FUNCTION(name) +# include "sanitizer_common/sanitizer_signal_interceptors.inc" #endif // SANITIZER_POSIX +#if SANITIZER_WINDOWS + +INTERCEPTOR_WINAPI(void, ExitProcess, UINT uExitCode) { + if (HasReportedLeaks()) { + uExitCode = common_flags()->exitcode; + } + return REAL(ExitProcess)(uExitCode); +} + +# define LSAN_MAYBE_INTERCEPT_EXIT_PROCESS INTERCEPT_FUNCTION(ExitProcess) +#else +# define LSAN_MAYBE_INTERCEPT_EXIT_PROCESS +#endif + +#if SANITIZER_WINDOWS +INTERCEPTOR_WINAPI(int, TerminateProcess, HANDLE hProcess, UINT uExitCode) { + if (HasReportedLeaks()) { + uExitCode = common_flags()->exitcode; + } + return REAL(TerminateProcess)(hProcess, uExitCode); +} + +# define LSAN_MAYBE_INTERCEPT_TERMINATE_PROCESS \ + INTERCEPT_FUNCTION(TerminateProcess) + +#else +# define LSAN_MAYBE_INTERCEPT_TERMINATE_PROCESS +#endif + +#if SANITIZER_WINDOWS +INTERCEPTOR_WINAPI(HANDLE, CreateThread, + LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, + LPTHREAD_START_ROUTINE lpStartAddress, + __drv_aliasesMem LPVOID lpParameter, DWORD dwCreationFlags, + LPDWORD lpThreadId) { + // TODO + return REAL(CreateThread)(lpThreadAttributes, dwStackSize, lpStartAddress, + lpParameter, dwCreationFlags, lpThreadId); +} + +# define LSAN_MAYBE_INTERCEPT_CREATE_THREAD INTERCEPT_FUNCTION(CreateThread) + +#else +# define LSAN_MAYBE_INTERCEPT_CREATE_THREAD +#endif + namespace __lsan { 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 +611,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,14 +630,18 @@ LSAN_MAYBE_INTERCEPT_STRERROR; -#if !SANITIZER_NETBSD && !SANITIZER_FREEBSD + LSAN_MAYBE_INTERCEPT_EXIT_PROCESS; + LSAN_MAYBE_INTERCEPT_TERMINATE_PROCESS; + LSAN_MAYBE_INTERCEPT_CREATE_THREAD; + +# 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(); } -#endif +# endif #endif // !SANITIZER_FUCHSIA } -} // namespace __lsan +} // namespace __lsan Index: compiler-rt/lib/lsan/lsan_common_win.cpp =================================================================== --- /dev/null +++ compiler-rt/lib/lsan/lsan_common_win.cpp @@ -0,0 +1,99 @@ +//=-- 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> + +// `windows.h` needs to be included before `dbghelp.h` +# include <DbgHelp.h> +# pragma comment(lib, "Dbghelp.lib") + +namespace __lsan { + +// TODO: Intercepting `ExitProcess` doesn't currently work +void HandleLeaks() { + if (common_flags()->exitcode) + Die(); +} + +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<Frontier *>(user_context); + + // Parse the PE Headers of all loaded Modules + const auto *module_nt_header = + ImageNtHeader(reinterpret_cast<PVOID>(module_base)); + + CHECK(module_nt_header); + + const auto *section_header = + reinterpret_cast<const IMAGE_SECTION_HEADER *>(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<const char *>(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_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 @@ -246,12 +246,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 @@ -502,12 +502,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_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 <typename AddressSpaceViewTy> struct AP32 { static const uptr kSpaceBeg = 0; @@ -65,17 +65,17 @@ template <typename AddressSpaceView> using PrimaryAllocatorASVT = SizeClassAllocator32<AP32<AddressSpaceView>>; using PrimaryAllocator = PrimaryAllocatorASVT<LocalAddressSpaceView>; -#elif defined(__x86_64__) || defined(__powerpc64__) || defined(__s390x__) -# if SANITIZER_FUCHSIA || defined(__powerpc64__) +#elif SANITIZER_X64 || defined(__powerpc64__) || defined(__s390x__) +# if SANITIZER_FUCHSIA || defined(__powerpc64__) const uptr kAllocatorSpace = ~(uptr)0; const uptr kAllocatorSize = 0x40000000000ULL; // 4T. -#elif defined(__s390x__) +# elif defined(__s390x__) const uptr kAllocatorSpace = 0x40000000000ULL; const uptr kAllocatorSize = 0x40000000000ULL; // 4T. -# else +# else const uptr kAllocatorSpace = 0x600000000000ULL; const uptr kAllocatorSize = 0x40000000000ULL; // 4T. -# endif +# endif template <typename AddressSpaceViewTy> struct AP64 { // Allocator64 parameters. Deliberately using a short name. static const uptr kSpaceBeg = kAllocatorSpace; @@ -90,6 +90,8 @@ template <typename AddressSpaceView> using PrimaryAllocatorASVT = SizeClassAllocator64<AP64<AddressSpaceView>>; using PrimaryAllocator = PrimaryAllocatorASVT<LocalAddressSpaceView>; +#else +# error Architecture not supported! #endif template <typename AddressSpaceView> 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/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: clang/lib/Driver/ToolChains/MSVC.cpp =================================================================== --- clang/lib/Driver/ToolChains/MSVC.cpp +++ clang/lib/Driver/ToolChains/MSVC.cpp @@ -215,6 +215,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 @@ -773,6 +778,7 @@ Res |= SanitizerKind::PointerSubtract; Res |= SanitizerKind::Fuzzer; Res |= SanitizerKind::FuzzerNoLink; + Res |= SanitizerKind::Leak; Res &= ~SanitizerKind::CFIMFCall; return Res; }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits