Index: cmake/config-ix.cmake =================================================================== --- cmake/config-ix.cmake +++ cmake/config-ix.cmake @@ -590,7 +590,7 @@ endif() if (COMPILER_RT_HAS_SANITIZER_COMMON AND SCUDO_SUPPORTED_ARCH AND - OS_NAME MATCHES "Linux|Android") + OS_NAME MATCHES "Linux|Android|Windows") set(COMPILER_RT_HAS_SCUDO TRUE) else() set(COMPILER_RT_HAS_SCUDO FALSE) Index: lib/sanitizer_common/sanitizer_win.cc =================================================================== --- lib/sanitizer_common/sanitizer_win.cc +++ lib/sanitizer_common/sanitizer_win.cc @@ -22,6 +22,13 @@ #include #include +// #define needed to link in RtlGenRandom(), a.k.a. SystemFunction036. See the +// "Community Additions" comment on MSDN here: +// http://msdn.microsoft.com/en-us/library/windows/desktop/aa387694.aspx +#define SystemFunction036 NTAPI SystemFunction036 +#include +#undef SystemFunction036 + #include "sanitizer_common.h" #include "sanitizer_dbghelp.h" #include "sanitizer_file.h" @@ -1101,9 +1108,11 @@ // Do nothing. } -// FIXME: implement on this platform. +# pragma comment(lib, "advapi32.lib") bool GetRandom(void *buffer, uptr length, bool blocking) { - UNIMPLEMENTED(); + if (!buffer || !length || length > 256) + return false; + return RtlGenRandom(buffer, length) != FALSE; } u32 GetNumberOfCPUs() { Index: lib/scudo/scudo_allocator.cpp =================================================================== --- lib/scudo/scudo_allocator.cpp +++ lib/scudo/scudo_allocator.cpp @@ -37,6 +37,12 @@ // at compilation or at runtime. static atomic_uint8_t HashAlgorithm = { CRC32Software }; +#if !SANITIZER_SUPPORTS_WEAK_HOOKS +SANITIZER_WEAK_ATTRIBUTE u32 computeHardwareCRC32(u32 Crc, uptr Data) { + return computeSoftwareCRC32(Crc, Data); +} +#endif + INLINE u32 computeCRC32(u32 Crc, uptr Value, uptr *Array, uptr ArraySize) { // If the hardware CRC32 feature is defined here, it was enabled everywhere, // as opposed to only for scudo_crc32.cpp. This means that other hardware @@ -249,7 +255,7 @@ // last size class minus the header size, in multiples of MinAlignment. UnpackedHeader Header = {}; const uptr MaxPrimaryAlignment = - 1 << MostSignificantSetBitIndex(SizeClassMap::kMaxSize - MinAlignment); + 1U << MostSignificantSetBitIndex(SizeClassMap::kMaxSize - MinAlignment); const uptr MaxOffset = (MaxPrimaryAlignment - AlignedChunkHeaderSize) >> MinAlignmentLog; Header.Offset = MaxOffset; @@ -736,6 +742,12 @@ return Instance.getUsableSize(Ptr); } +#if !SANITIZER_SUPPORTS_WEAK_HOOKS +SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_malloc_hook, + void *ptr, uptr size) {} +SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_free_hook, void *ptr) {} +#endif + // Interface functions void __scudo_set_rss_limit(uptr LimitMb, s32 HardLimit) { Index: lib/scudo/scudo_flags.cpp =================================================================== --- lib/scudo/scudo_flags.cpp +++ lib/scudo/scudo_flags.cpp @@ -12,13 +12,12 @@ //===----------------------------------------------------------------------===// #include "scudo_flags.h" +#include "scudo_interface_internal.h" #include "scudo_utils.h" #include "sanitizer_common/sanitizer_flags.h" #include "sanitizer_common/sanitizer_flag_parser.h" -SANITIZER_INTERFACE_WEAK_DEF(const char*, __scudo_default_options, void); - namespace __scudo { static Flags ScudoFlags; // Use via getFlags(). @@ -119,3 +118,9 @@ } } // namespace __scudo + +#if !SANITIZER_SUPPORTS_WEAK_HOOKS +SANITIZER_INTERFACE_WEAK_DEF(const char*, __scudo_default_options, void) { + return ""; +} +#endif Index: lib/scudo/scudo_interface_internal.h =================================================================== --- lib/scudo/scudo_interface_internal.h +++ lib/scudo/scudo_interface_internal.h @@ -20,6 +20,8 @@ using __sanitizer::s32; extern "C" { +SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE +const char *__scudo_default_options(); SANITIZER_INTERFACE_ATTRIBUTE void __scudo_set_rss_limit(uptr LimitMb, s32 HardLimit); } // extern "C" Index: lib/scudo/scudo_new_delete.cpp =================================================================== --- lib/scudo/scudo_new_delete.cpp +++ lib/scudo/scudo_new_delete.cpp @@ -19,7 +19,32 @@ using namespace __scudo; +// C++ operators can't have dllexport attributes on Windows. We export them +// anyway by passing extra -export flags to the linker, which is exactly that +// dllexport would normally do. We need to export them in order to make the +// VS2015 dynamic CRT (MD) work. +#if SANITIZER_WINDOWS +#define CXX_OPERATOR_ATTRIBUTE +#define COMMENT_EXPORT(sym) __pragma(comment(linker, "/export:" sym)) +#ifdef _WIN64 +COMMENT_EXPORT("??2@YAPEAX_K@Z") // operator new +COMMENT_EXPORT("??2@YAPEAX_KAEBUnothrow_t@std@@@Z") // operator new nothrow +COMMENT_EXPORT("??3@YAXPEAX@Z") // operator delete +COMMENT_EXPORT("??3@YAXPEAX_K@Z") // sized operator delete +COMMENT_EXPORT("??_U@YAPEAX_K@Z") // operator new[] +COMMENT_EXPORT("??_V@YAXPEAX@Z") // operator delete[] +#else +COMMENT_EXPORT("??2@YAPAXI@Z") // operator new +COMMENT_EXPORT("??2@YAPAXIABUnothrow_t@std@@@Z") // operator new nothrow +COMMENT_EXPORT("??3@YAXPAX@Z") // operator delete +COMMENT_EXPORT("??3@YAXPAXI@Z") // sized operator delete +COMMENT_EXPORT("??_U@YAPAXI@Z") // operator new[] +COMMENT_EXPORT("??_V@YAXPAX@Z") // operator delete[] +#endif +#undef COMMENT_EXPORT +#else #define CXX_OPERATOR_ATTRIBUTE INTERCEPTOR_ATTRIBUTE +#endif // Fake std::nothrow_t to avoid including . namespace std { Index: lib/scudo/scudo_platform.h =================================================================== --- lib/scudo/scudo_platform.h +++ lib/scudo/scudo_platform.h @@ -17,29 +17,26 @@ #include "sanitizer_common/sanitizer_allocator.h" -#if !SANITIZER_LINUX && !SANITIZER_FUCHSIA +#if !SANITIZER_LINUX && !SANITIZER_FUCHSIA && !SANITIZER_WINDOWS # error "The Scudo hardened allocator is not supported on this platform." #endif -#define SCUDO_TSD_EXCLUSIVE_SUPPORTED (!SANITIZER_ANDROID && !SANITIZER_FUCHSIA) +#define SCUDO_TSD_EXCLUSIVE_SUPPORTED \ + (!SANITIZER_ANDROID && !SANITIZER_FUCHSIA && !SANITIZER_WINDOWS) #ifndef SCUDO_TSD_EXCLUSIVE // SCUDO_TSD_EXCLUSIVE wasn't defined, use a default TSD model for the platform. -# if SANITIZER_ANDROID || SANITIZER_FUCHSIA -// Android and Fuchsia use a pool of TSDs shared between threads. -# define SCUDO_TSD_EXCLUSIVE 0 -# elif SANITIZER_LINUX && !SANITIZER_ANDROID -// Non-Android Linux use an exclusive TSD per thread. +# if SCUDO_TSD_EXCLUSIVE_SUPPORTED # define SCUDO_TSD_EXCLUSIVE 1 # else -# error "No default TSD model defined for this platform." -# endif // SANITIZER_ANDROID || SANITIZER_FUCHSIA -#endif // SCUDO_TSD_EXCLUSIVE - +# define SCUDO_TSD_EXCLUSIVE 0 +# endif // SCUDO_TSD_EXCLUSIVE_SUPPORTED +#else // If the exclusive TSD model is chosen, make sure the platform supports it. -#if SCUDO_TSD_EXCLUSIVE && !SCUDO_TSD_EXCLUSIVE_SUPPORTED +# if SCUDO_TSD_EXCLUSIVE && !SCUDO_TSD_EXCLUSIVE_SUPPORTED # error "The exclusive TSD model is not supported on this platform." -#endif +# endif +#endif // SCUDO_TSD_EXCLUSIVE // Maximum number of TSDs that can be created for the Shared model. #ifndef SCUDO_SHARED_TSD_POOL_SIZE Index: lib/scudo/scudo_tsd.h =================================================================== --- lib/scudo/scudo_tsd.h +++ lib/scudo/scudo_tsd.h @@ -19,7 +19,11 @@ #include "scudo_allocator.h" #include "scudo_utils.h" -#include +#if !SANITIZER_WINDOWS +# include +#else +# include +#endif // SANITIZER_WINDOWS namespace __scudo { Index: lib/scudo/scudo_tsd_shared.cpp =================================================================== --- lib/scudo/scudo_tsd_shared.cpp +++ lib/scudo/scudo_tsd_shared.cpp @@ -17,15 +17,25 @@ namespace __scudo { +#if !SANITIZER_WINDOWS static pthread_once_t GlobalInitialized = PTHREAD_ONCE_INIT; pthread_key_t PThreadKey; +#else +DWORD TlsIndex = TLS_OUT_OF_INDEXES; +static INIT_ONCE InitOnce = INIT_ONCE_STATIC_INIT; +#endif static atomic_uint32_t CurrentIndex; static ScudoTSD *TSDs; static u32 NumberOfTSDs; static void initOnce() { +#if SANITIZER_WINDOWS + TlsIndex = TlsAlloc(); + CHECK_NE(TlsIndex, TLS_OUT_OF_INDEXES); +#elif !SANITIZER_ANDROID CHECK_EQ(pthread_key_create(&PThreadKey, NULL), 0); +#endif initScudo(); NumberOfTSDs = Min(Max(1U, GetNumberOfCPUsCached()), static_cast(SCUDO_SHARED_TSD_POOL_SIZE)); @@ -36,15 +46,29 @@ } ALWAYS_INLINE void setCurrentTSD(ScudoTSD *TSD) { -#if SANITIZER_ANDROID +#if SANITIZER_WINDOWS + CHECK(TlsSetValue(TlsIndex, reinterpret_cast(TSD))); +#elif SANITIZER_ANDROID *get_android_tls_ptr() = reinterpret_cast(TSD); #else CHECK_EQ(pthread_setspecific(PThreadKey, reinterpret_cast(TSD)), 0); #endif // SANITIZER_ANDROID } +#if SANITIZER_WINDOWS +static BOOL CALLBACK handleInit(PINIT_ONCE InitOnce, PVOID Parameter, + PVOID *Context) { + initOnce(); + return TRUE; +} +#endif + void initThread(bool MinimalInit) { +#if SANITIZER_WINDOWS + CHECK(InitOnceExecuteOnce(&InitOnce, handleInit, nullptr, nullptr)); +#else pthread_once(&GlobalInitialized, initOnce); +#endif // Initial context assignment is done in a plain round-robin fashion. u32 Index = atomic_fetch_add(&CurrentIndex, 1, memory_order_relaxed); setCurrentTSD(&TSDs[Index % NumberOfTSDs]); Index: lib/scudo/scudo_tsd_shared.inc =================================================================== --- lib/scudo/scudo_tsd_shared.inc +++ lib/scudo/scudo_tsd_shared.inc @@ -17,10 +17,16 @@ #if !SCUDO_TSD_EXCLUSIVE +#if SANITIZER_WINDOWS +extern DWORD TlsIndex; +#elif !SANITIZER_ANDROID extern pthread_key_t PThreadKey; +#endif ALWAYS_INLINE ScudoTSD* getCurrentTSD() { -#if SANITIZER_ANDROID +#if SANITIZER_WINDOWS + return reinterpret_cast(TlsGetValue(TlsIndex)); +#elif SANITIZER_ANDROID return reinterpret_cast(*get_android_tls_ptr()); #else return reinterpret_cast(pthread_getspecific(PThreadKey)); Index: test/scudo/lit.cfg =================================================================== --- test/scudo/lit.cfg +++ test/scudo/lit.cfg @@ -16,19 +16,22 @@ # C & CXX flags. c_flags = ([config.target_cflags] + - ["-pthread", - "-fPIE", - "-pie", - "-O0", - "-UNDEBUG", - "-ldl", - "-Wl,--gc-sections"]) - -# Android doesn't want -lrt. -if not config.android: - c_flags += ["-lrt"] + ["-O0", + "-UNDEBUG"]) -cxx_flags = (c_flags + config.cxx_mode_flags + ["-std=c++11"]) +if config.host_os != 'Windows': + c_flags += ["-pthread", + "-fPIE", + "-pie", + "-ldl", + "-Wl,--gc-sections"] + # Android doesn't want -lrt. + if not config.android: + c_flags += ["-lrt"] + +cxx_flags = (c_flags + config.cxx_mode_flags) +if config.host_os != 'Windows': + cxx_flags += ["-std=c++11"] scudo_flags = ["-fsanitize=scudo"] @@ -54,5 +57,5 @@ 'env SCUDO_OPTIONS=' + default_scudo_opts)) # Hardened Allocator tests are currently supported on Linux only. -if config.host_os not in ['Linux']: +if config.host_os not in ['Linux', 'Windows']: config.unsupported = True