diff --git a/clang/lib/Driver/ToolChains/MinGW.cpp b/clang/lib/Driver/ToolChains/MinGW.cpp --- a/clang/lib/Driver/ToolChains/MinGW.cpp +++ b/clang/lib/Driver/ToolChains/MinGW.cpp @@ -200,6 +200,29 @@ Args.AddAllArgs(CmdArgs, options::OPT_u_Group); Args.AddLastArg(CmdArgs, options::OPT_Z_Flag); + // Add asan flags before other libs and objects. Making asan_dynamic the first + // import lib allows asan to be initialized as early as possible to increase + // its instrumentation coverage to include other user DLLs which has not been + // built with asan. + if (Sanitize.needsAsanRt() && !Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nodefaultlibs)) { + // MinGW always links against a shared MSVCRT. + CmdArgs.push_back( + TC.getCompilerRTArgString(Args, "asan_dynamic", ToolChain::FT_Shared)); + CmdArgs.push_back( + TC.getCompilerRTArgString(Args, "asan_dynamic_runtime_thunk")); + CmdArgs.push_back("--require-defined"); + CmdArgs.push_back(TC.getArch() == llvm::Triple::x86 + ? "___asan_seh_interceptor" + : "__asan_seh_interceptor"); + // Make sure the linker consider all object files from the dynamic + // runtime thunk. + CmdArgs.push_back("--whole-archive"); + CmdArgs.push_back( + TC.getCompilerRTArgString(Args, "asan_dynamic_runtime_thunk")); + CmdArgs.push_back("--no-whole-archive"); + } + if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_mdll)) { CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("dllcrt2.o"))); @@ -292,24 +315,6 @@ if (Args.hasArg(options::OPT_pthread)) CmdArgs.push_back("-lpthread"); - if (Sanitize.needsAsanRt()) { - // MinGW always links against a shared MSVCRT. - CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dynamic", - ToolChain::FT_Shared)); - CmdArgs.push_back( - TC.getCompilerRTArgString(Args, "asan_dynamic_runtime_thunk")); - CmdArgs.push_back("--require-defined"); - CmdArgs.push_back(TC.getArch() == llvm::Triple::x86 - ? "___asan_seh_interceptor" - : "__asan_seh_interceptor"); - // Make sure the linker consider all object files from the dynamic - // runtime thunk. - CmdArgs.push_back("--whole-archive"); - CmdArgs.push_back( - TC.getCompilerRTArgString(Args, "asan_dynamic_runtime_thunk")); - CmdArgs.push_back("--no-whole-archive"); - } - TC.addProfileRTLibs(Args, CmdArgs); if (!HasWindowsApp) { diff --git a/clang/test/Driver/mingw-sanitizers.c b/clang/test/Driver/mingw-sanitizers.c --- a/clang/test/Driver/mingw-sanitizers.c +++ b/clang/test/Driver/mingw-sanitizers.c @@ -1,13 +1,18 @@ -// RUN: %clang -target i686-windows-gnu %s -### -fsanitize=address 2>&1 | FileCheck --check-prefix=ASAN-I686 %s -// ASAN-I686: "{{.*}}libclang_rt.asan_dynamic-i386.dll.a" -// ASAN-I686: "{{[^"]*}}libclang_rt.asan_dynamic_runtime_thunk-i386.a" -// ASAN-I686: "--require-defined" "___asan_seh_interceptor" -// ASAN-I686: "--whole-archive" "{{.*}}libclang_rt.asan_dynamic_runtime_thunk-i386.a" "--no-whole-archive" - -// RUN: %clang -target x86_64-windows-gnu %s -### -fsanitize=address 2>&1 | FileCheck --check-prefix=ASAN-X86_64 %s -// ASAN-X86_64: "{{.*}}libclang_rt.asan_dynamic-x86_64.dll.a" +// RUN: echo -n > %t.a +// RUN: %clang -target i686-windows-gnu %s -### -fsanitize=address -lcomponent %t.a 2>&1 | FileCheck --check-prefixes=ASAN-ALL,ASAN-I686 -DINPUT=%t.a %s +// RUN: %clang -target x86_64-windows-gnu %s -### -fsanitize=address -lcomponent %t.a 2>&1 | FileCheck --check-prefixes=ASAN-ALL,ASAN-X86_64 -DINPUT=%t.a %s +// +// ASAN-ALL-NOT:"-l{{[^"]+"]}}" +// ASAN-ALL-NOT:"[[INPUT]]" +// ASAN-I686: "{{[^"]*}}libclang_rt.asan_dynamic-i386.dll.a" +// ASAN-I686: "{{[^"]*}}libclang_rt.asan_dynamic_runtime_thunk-i386.a" +// ASAN-I686: "--require-defined" "___asan_seh_interceptor" +// ASAN-I686: "--whole-archive" "{{[^"]*}}libclang_rt.asan_dynamic_runtime_thunk-i386.a" "--no-whole-archive" +// ASAN-X86_64: "{{[^"]*}}libclang_rt.asan_dynamic-x86_64.dll.a" // ASAN-X86_64: "{{[^"]*}}libclang_rt.asan_dynamic_runtime_thunk-x86_64.a" // ASAN-X86_64: "--require-defined" "__asan_seh_interceptor" -// ASAN-X86_64: "--whole-archive" "{{.*}}libclang_rt.asan_dynamic_runtime_thunk-x86_64.a" "--no-whole-archive" +// ASAN-X86_64: "--whole-archive" "{{[^"]*}}libclang_rt.asan_dynamic_runtime_thunk-x86_64.a" "--no-whole-archive" +// ASAN-ALL: "-lcomponent" +// ASAN-ALL: "[[INPUT]]" // RUN: %clang -target x86_64-windows-gnu %s -### -fsanitize=vptr