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

Reply via email to