]> granicus.if.org Git - clang/commitdiff
[MinGW] Allow using ASan
authorMartin Storsjo <martin@martin.st>
Mon, 1 Oct 2018 20:53:25 +0000 (20:53 +0000)
committerMartin Storsjo <martin@martin.st>
Mon, 1 Oct 2018 20:53:25 +0000 (20:53 +0000)
Linking to ASan for MinGW is similar to MSVC, but MinGW always links
the MSVCRT dynamically, so there is only one of the MSVC cases to
consider.

When linking to a shared compiler runtime library on MinGW, the suffix
of the import library is .dll.a.

The existing case of .dll as suffix for windows in general doesn't
seem correct (since this is used for linking). As long as callers never
actually set the Shared flag, the default static suffix of .lib also
worked fine for import libraries as well.

Differential Revision: https://reviews.llvm.org/D52538

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@343537 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Driver/ToolChain.cpp
lib/Driver/ToolChains/MinGW.cpp
lib/Driver/ToolChains/MinGW.h
test/Driver/mingw-sanitizers.c [new file with mode: 0644]

index 8933e905fce3f5adc6493923e4bf728ba54e5b32..f05c8a39823b3d5520d38399c1e65fdaa83dec69 100644 (file)
@@ -367,8 +367,10 @@ std::string ToolChain::getCompilerRT(const ArgList &Args, StringRef Component,
       TT.isWindowsMSVCEnvironment() || TT.isWindowsItaniumEnvironment();
 
   const char *Prefix = IsITANMSVCWindows ? "" : "lib";
-  const char *Suffix = Shared ? (Triple.isOSWindows() ? ".dll" : ".so")
+  const char *Suffix = Shared ? (Triple.isOSWindows() ? ".lib" : ".so")
                               : (IsITANMSVCWindows ? ".lib" : ".a");
+  if (Shared && Triple.isWindowsGNUEnvironment())
+    Suffix = ".dll.a";
 
   for (const auto &LibPath : getLibraryPaths()) {
     SmallString<128> P(LibPath);
index a88e00f0c8e85633a862af19931faee48e7c7aba..f9e641e63fffcf037bb446f86484a7308ae8138f 100644 (file)
@@ -14,6 +14,7 @@
 #include "clang/Driver/Driver.h"
 #include "clang/Driver/DriverDiagnostic.h"
 #include "clang/Driver/Options.h"
+#include "clang/Driver/SanitizerArgs.h"
 #include "llvm/Option/ArgList.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Path.h"
@@ -95,7 +96,7 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
                                         const char *LinkingOutput) const {
   const ToolChain &TC = getToolChain();
   const Driver &D = TC.getDriver();
-  // const SanitizerArgs &Sanitize = TC.getSanitizerArgs();
+  const SanitizerArgs &Sanitize = TC.getSanitizerArgs();
 
   ArgStringList CmdArgs;
 
@@ -187,8 +188,6 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
   TC.AddFilePathLibArgs(Args, CmdArgs);
   AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
 
-  // TODO: Add ASan stuff here
-
   // TODO: Add profile stuff here
 
   if (TC.ShouldLinkCXXStdlib(Args)) {
@@ -231,6 +230,24 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
       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", true));
+        CmdArgs.push_back(
+            TC.getCompilerRTArgString(Args, "asan_dynamic_runtime_thunk"));
+        CmdArgs.push_back(Args.MakeArgString("--require-defined"));
+        CmdArgs.push_back(Args.MakeArgString(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(Args.MakeArgString("--whole-archive"));
+        CmdArgs.push_back(Args.MakeArgString(
+            TC.getCompilerRT(Args, "asan_dynamic_runtime_thunk")));
+        CmdArgs.push_back(Args.MakeArgString("--no-whole-archive"));
+      }
+
       if (!HasWindowsApp) {
         // Add system libraries. If linking to libwindowsapp.a, that import
         // library replaces all these and we shouldn't accidentally try to
@@ -407,6 +424,12 @@ toolchains::MinGW::GetExceptionModel(const ArgList &Args) const {
   return llvm::ExceptionHandling::DwarfCFI;
 }
 
+SanitizerMask toolchains::MinGW::getSupportedSanitizers() const {
+  SanitizerMask Res = ToolChain::getSupportedSanitizers();
+  Res |= SanitizerKind::Address;
+  return Res;
+}
+
 void toolchains::MinGW::AddCudaIncludeArgs(const ArgList &DriverArgs,
                                            ArgStringList &CC1Args) const {
   CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args);
index 0c3919d29f77bb1321f57c8e0653d6040688b05d..450044d45127db282eb9a01d2e22136a97451009 100644 (file)
@@ -65,6 +65,8 @@ public:
   bool isPIEDefault() const override;
   bool isPICDefaultForced() const override;
 
+  SanitizerMask getSupportedSanitizers() const override;
+
   llvm::ExceptionHandling GetExceptionModel(
       const llvm::opt::ArgList &Args) const override;
 
diff --git a/test/Driver/mingw-sanitizers.c b/test/Driver/mingw-sanitizers.c
new file mode 100644 (file)
index 0000000..09f28fe
--- /dev/null
@@ -0,0 +1,11 @@
+// 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"
+// 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"