Index: lib/Transforms/Instrumentation/AddressSanitizer.cpp =================================================================== --- lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -1272,7 +1272,7 @@ ConstantInt::get(IntptrTy, n)); // We also need to unregister globals at the end, e.g. when a shared library - // gets closed. + // gets closed, by using global_dtors. Function *AsanDtorFunction = Function::Create( FunctionType::get(Type::getVoidTy(*C), false), GlobalValue::InternalLinkage, kAsanModuleDtorName, &M); @@ -1281,7 +1281,17 @@ IRB_Dtor.CreateCall2(AsanUnregisterGlobals, IRB.CreatePointerCast(AllGlobals, IntptrTy), ConstantInt::get(IntptrTy, n)); - appendToGlobalDtors(M, AsanDtorFunction, kAsanCtorAndDtorPriority); + // MSVC CRT doesn't call LLVM global_dtors, so we have to use atexit() + // to work around (See PR22545). + if (TargetTriple.isKnownWindowsMSVCEnvironment() || + TargetTriple.isWindowsItaniumEnvironment()) { + 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