clemenswasser updated this revision to Diff 391872.
clemenswasser added a comment.

Move `__lsan_init` call inside of `SANITIZER_WINDOWS` ifdef


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D115103/new/

https://reviews.llvm.org/D115103

Files:
  clang/lib/Driver/ToolChains/MSVC.cpp
  compiler-rt/cmake/config-ix.cmake
  compiler-rt/lib/lsan/CMakeLists.txt
  compiler-rt/lib/lsan/lsan.h
  compiler-rt/lib/lsan/lsan_allocator.cpp
  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/CMakeLists.txt
  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
@@ -79,7 +79,8 @@
 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'
+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
===================================================================
--- /dev/null
+++ compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_win.cpp
@@ -0,0 +1,137 @@
+//===-- sanitizer_stoptheworld_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
+//
+//===----------------------------------------------------------------------===//
+//
+// See sanitizer_stoptheworld.h for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common.h"
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_platform.h"
+
+#if SANITIZER_WINDOWS
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#include <tlhelp32.h>
+
+#include "sanitizer_stoptheworld.h"
+
+
+namespace __sanitizer {
+
+struct SuspendedThreadsListWindows final : public SuspendedThreadsList {
+  InternalMmapVector<HANDLE> threadHandles;
+  InternalMmapVector<DWORD> threadIds;
+
+  SuspendedThreadsListWindows() {
+    threadIds.reserve(1024);
+    threadHandles.reserve(1024);
+  }
+
+  PtraceRegistersStatus GetRegistersAndSP(uptr index,
+                                          InternalMmapVector<uptr> *buffer,
+                                          uptr *sp) const override;
+
+  tid_t GetThreadID(uptr index) const override;
+  uptr ThreadCount() const override;
+};
+
+PtraceRegistersStatus SuspendedThreadsListWindows::GetRegistersAndSP(
+    uptr index, InternalMmapVector<uptr> *buffer, uptr *sp) const {
+  CHECK_LT(index, threadHandles.size());
+
+  CONTEXT thread_context;
+  thread_context.ContextFlags = CONTEXT_ALL;
+  CHECK(GetThreadContext(threadHandles[index], &thread_context));
+
+  buffer->resize(RoundUpTo(sizeof(thread_context), sizeof(uptr)) / sizeof(uptr));
+  internal_memcpy(buffer->data(), &thread_context, sizeof(thread_context));
+
+  *sp = thread_context.Rsp;
+
+  return REGISTERS_AVAILABLE;
+}
+
+tid_t SuspendedThreadsListWindows::GetThreadID(uptr index) const {
+  CHECK_LT(index, threadIds.size());
+  return threadIds[index];
+}
+
+uptr SuspendedThreadsListWindows::ThreadCount() const {
+  return threadIds.size();
+}
+
+struct RunThreadArgs {
+  StopTheWorldCallback callback;
+  void *argument;
+};
+
+DWORD WINAPI RunThread(void *argument) {
+  RunThreadArgs *run_args = (RunThreadArgs *)argument;
+  const HANDLE threads = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
+
+  CHECK(threads != INVALID_HANDLE_VALUE);
+
+  const DWORD this_thread = GetCurrentThreadId();
+  const DWORD this_process = GetCurrentProcessId();
+
+  SuspendedThreadsListWindows suspended_threads_list;
+
+  THREADENTRY32 thread_entry;
+  thread_entry.dwSize = sizeof(thread_entry);
+  if (Thread32First(threads, &thread_entry)) {
+    do {
+      if (thread_entry.dwSize >=
+          FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) +
+              sizeof(thread_entry.th32OwnerProcessID)) {
+        if (thread_entry.th32ThreadID == this_thread ||
+            thread_entry.th32OwnerProcessID != this_process)
+          continue;
+
+        const HANDLE thread =
+            OpenThread(THREAD_ALL_ACCESS, FALSE, thread_entry.th32ThreadID);
+        CHECK(thread);
+        SuspendThread(thread);
+
+        suspended_threads_list.threadIds.push_back(thread_entry.th32ThreadID);
+        suspended_threads_list.threadHandles.push_back(thread);
+      }
+      thread_entry.dwSize = sizeof(thread_entry);
+    } while (Thread32Next(threads, &thread_entry));
+  }
+
+  run_args->callback(suspended_threads_list, run_args->argument);
+
+  for (const auto suspended_thread_handle :
+       suspended_threads_list.threadHandles) {
+    ResumeThread(suspended_thread_handle);
+    CloseHandle(suspended_thread_handle);
+  }
+
+  CloseHandle(threads);
+
+  return 0;
+}
+
+void StopTheWorld(StopTheWorldCallback callback, void *argument) {
+  struct RunThreadArgs arg = {callback, argument};
+  DWORD trace_thread_id;
+
+  auto trace_thread =
+      CreateThread(nullptr, 0, RunThread, &arg, 0, &trace_thread_id);
+  CHECK(trace_thread);
+
+  WaitForSingleObject(trace_thread, INFINITE);
+  CloseHandle(trace_thread);
+}
+
+}  // namespace __sanitizer
+
+#endif  // SANITIZER_WINDOWS
Index: compiler-rt/lib/sanitizer_common/CMakeLists.txt
===================================================================
--- compiler-rt/lib/sanitizer_common/CMakeLists.txt
+++ compiler-rt/lib/sanitizer_common/CMakeLists.txt
@@ -34,6 +34,7 @@
   sanitizer_solaris.cpp
   sanitizer_stoptheworld_fuchsia.cpp
   sanitizer_stoptheworld_mac.cpp
+  sanitizer_stoptheworld_win.cpp
   sanitizer_suppressions.cpp
   sanitizer_tls_get_addr.cpp
   sanitizer_thread_registry.cpp
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<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; }
+
+}  // 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
@@ -326,7 +326,7 @@
 
 ///// Thread initialization and finalization. /////
 
-#if !SANITIZER_NETBSD && !SANITIZER_FREEBSD && !SANITIZER_FUCHSIA
+#if !SANITIZER_NETBSD && !SANITIZER_FREEBSD && !SANITIZER_FUCHSIA && !SANITIZER_WINDOWS
 static unsigned g_thread_finalize_key;
 
 static void thread_finalize(void *v) {
@@ -499,7 +499,16 @@
 
 void InitializeInterceptors() {
   // Fuchsia doesn't use interceptors that require any setup.
-#if !SANITIZER_FUCHSIA
+
+#if SANITIZER_WINDOWS
+  INTERCEPT_FUNCTION(malloc);
+  INTERCEPT_FUNCTION(free);
+  INTERCEPT_FUNCTION(calloc);
+  INTERCEPT_FUNCTION(realloc);
+  LSAN_MAYBE_INTERCEPT_MEMALIGN;
+  INTERCEPT_FUNCTION(valloc);
+  LSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC;
+#elif !SANITIZER_FUCHSIA
   InitializeSignalInterceptors();
 
   INTERCEPT_FUNCTION(malloc);
Index: compiler-rt/lib/lsan/lsan_common_win.cpp
===================================================================
--- /dev/null
+++ compiler-rt/lib/lsan/lsan_common_win.cpp
@@ -0,0 +1,55 @@
+//=-- 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 "sanitizer_common/sanitizer_platform.h"
+#include "sanitizer_common/sanitizer_libc.h"
+#include "lsan_common.h"
+
+#if CAN_SANITIZE_LEAKS && SANITIZER_WINDOWS
+
+#include "sanitizer_common/sanitizer_allocator_internal.h"
+#include "lsan_allocator.h"
+
+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--;
+}
+
+void ProcessGlobalRegions(Frontier *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
@@ -408,6 +408,7 @@
                          kReachable);
 }
 
+#if !SANITIZER_WINDOWS
 static void ProcessRootRegion(Frontier *frontier,
                               const RootRegion &root_region) {
   MemoryMappingLayout proc_maps(/*cache_enabled*/ true);
@@ -424,6 +425,7 @@
   for (uptr i = 0; i < root_regions.size(); i++)
     ProcessRootRegion(frontier, root_regions[i]);
 }
+#endif
 
 static void FloodFillTag(Frontier *frontier, ChunkTag tag) {
   while (frontier->size()) {
@@ -551,7 +553,9 @@
   ForEachChunk(CollectIgnoredCb, frontier);
   ProcessGlobalRegions(frontier);
   ProcessThreads(suspended_threads, frontier);
+  #if !SANITIZER_WINDOWS
   ProcessRootRegions(frontier);
+  #endif
   FloodFillTag(frontier, kReachable);
 
   CHECK_EQ(0, frontier->size());
Index: compiler-rt/lib/lsan/lsan_allocator.cpp
===================================================================
--- compiler-rt/lib/lsan/lsan_allocator.cpp
+++ compiler-rt/lib/lsan/lsan_allocator.cpp
@@ -27,11 +27,11 @@
 
 namespace __lsan {
 #if defined(__i386__) || defined(__arm__)
-static const uptr kMaxAllowedMallocSize = 1UL << 30;
+static const uptr kMaxAllowedMallocSize = static_cast<uptr>(1) << 30;
 #elif defined(__mips64) || defined(__aarch64__)
-static const uptr kMaxAllowedMallocSize = 4UL << 30;
+static const uptr kMaxAllowedMallocSize = static_cast<uptr>(4) << 30;
 #else
-static const uptr kMaxAllowedMallocSize = 8UL << 30;
+static const uptr kMaxAllowedMallocSize = static_cast<uptr>(8) << 30;
 #endif
 
 static Allocator allocator;
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: compiler-rt/cmake/config-ix.cmake
===================================================================
--- compiler-rt/cmake/config-ix.cmake
+++ compiler-rt/cmake/config-ix.cmake
@@ -709,7 +709,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: clang/lib/Driver/ToolChains/MSVC.cpp
===================================================================
--- clang/lib/Driver/ToolChains/MSVC.cpp
+++ clang/lib/Driver/ToolChains/MSVC.cpp
@@ -1416,6 +1416,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