diff --git a/clang/lib/Driver/ToolChains/MinGW.cpp b/clang/lib/Driver/ToolChains/MinGW.cpp index 908484fcc0b81..bac486bab8857 100644 --- a/clang/lib/Driver/ToolChains/MinGW.cpp +++ b/clang/lib/Driver/ToolChains/MinGW.cpp @@ -200,6 +200,16 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA, Args.AddAllArgs(CmdArgs, options::OPT_u_Group); Args.AddLastArg(CmdArgs, options::OPT_Z_Flag); + // Add asan_dynamic as the first import lib before other libs. This 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)); + } + 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"))); diff --git a/clang/test/Driver/mingw-sanitizers.c b/clang/test/Driver/mingw-sanitizers.c index 701e9107f4850..d165648a8fdf6 100644 --- a/clang/test/Driver/mingw-sanitizers.c +++ b/clang/test/Driver/mingw-sanitizers.c @@ -1,13 +1,20 @@ -// 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: touch %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-X86_64: "{{[^"]*}}libclang_rt.asan_dynamic-x86_64.dll.a" +// ASAN-ALL: "-lcomponent" +// ASAN-ALL: "[[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" // RUN: %clang -target x86_64-windows-gnu %s -### -fsanitize=vptr