Index: lib/Transforms/Instrumentation/AddressSanitizer.cpp =================================================================== --- lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -1281,7 +1281,16 @@ IRB_Dtor.CreateCall2(AsanUnregisterGlobals, IRB.CreatePointerCast(AllGlobals, IntptrTy), ConstantInt::get(IntptrTy, n)); - appendToGlobalDtors(M, AsanDtorFunction, kAsanCtorAndDtorPriority); + // On Windows, we have to use atexit(), otherwise the MD CRT won't call us. + // On other platforms, just append a call to the module dtors. + if (Triple(M.getTargetTriple()).isOSWindows()) { + Function *AtExit = checkInterfaceFunction(M.getOrInsertFunction( + "atexit", IRB.getInt32Ty(), AsanDtorFunction->getType(), nullptr)); + AtExit->setLinkage(Function::ExternalLinkage); + IRB.CreateCall(AtExit, AsanDtorFunction); + } else { + appendToGlobalDtors(M, AsanDtorFunction, kAsanCtorAndDtorPriority); + } DEBUG(dbgs() << M); return true; Index: test/Instrumentation/AddressSanitizer/instrument_global.ll =================================================================== --- test/Instrumentation/AddressSanitizer/instrument_global.ll +++ test/Instrumentation/AddressSanitizer/instrument_global.ll @@ -1,6 +1,6 @@ -; RUN: opt < %s -asan -asan-module -S | FileCheck %s +; RUN: opt < %s -mtriple x86_64-unknown-linux-gnu -asan -asan-module -S | FileCheck %s --check-prefix=CHECK --check-prefix=LINUX +; RUN: opt < %s -mtriple i686-pc-windows-msvc -asan -asan-module -S | FileCheck %s --check-prefix=CHECK --check-prefix=WIN32 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" -target triple = "x86_64-unknown-linux-gnu" @xxx = global i32 0, align 4 ; If a global is present, __asan_[un]register_globals should be called from @@ -8,7 +8,8 @@ ; CHECK: llvm.global_ctors ; CHECK: @__asan_gen_ = private constant [8 x i8] c"\00", align 1 -; CHECK: llvm.global_dtors +; LINUX: llvm.global_dtors +; WIN32-NOT: llvm.global_dtors ; Test that we don't instrument global arrays with static initializer ; indexed with constants in-bounds. But instrument all other cases. @@ -74,9 +75,9 @@ ; CHECK-LABEL: define internal void @asan.module_ctor ; CHECK-NOT: ret ; CHECK: call void @__asan_register_globals -; CHECK: ret +; WIN32-NEXT: call i32 @atexit(void ()* @asan.module_dtor) +; CHECK-NEXT: ret ; CHECK-LABEL: define internal void @asan.module_dtor -; CHECK-NOT: ret -; CHECK: call void @__asan_unregister_globals -; CHECK: ret +; CHECK-NEXT: call void @__asan_unregister_globals +; CHECK-NEXT: ret