alvinhochun created this revision. alvinhochun added reviewers: mstorsjo, MaskRay. Herald added a project: All. alvinhochun requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
As stated in https://github.com/llvm/llvm-project/issues/61685, by passing LLD the import lib of the asan DLL first, the asan DLL will be listed as the first entry in the Import Directory Table, making it be loaded first before other user DLLs. This allows asan to be initialized as early as possible to increase its instrumentation coverage to include other DLLs not built with asan. This also avoids some false asan reports on `realloc` for memory allocated during initialization of user DLLs being loaded earlier than asan, because after this change they will be loaded later than asan. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D146908 Files: clang/lib/Driver/ToolChains/MinGW.cpp clang/test/Driver/mingw-sanitizers.c Index: clang/test/Driver/mingw-sanitizers.c =================================================================== --- clang/test/Driver/mingw-sanitizers.c +++ 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 Index: clang/lib/Driver/ToolChains/MinGW.cpp =================================================================== --- clang/lib/Driver/ToolChains/MinGW.cpp +++ 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) {
Index: clang/test/Driver/mingw-sanitizers.c =================================================================== --- clang/test/Driver/mingw-sanitizers.c +++ 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 Index: clang/lib/Driver/ToolChains/MinGW.cpp =================================================================== --- clang/lib/Driver/ToolChains/MinGW.cpp +++ 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) {
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits