[PATCH] Add compiler support for dynamic Asan runtime

Yury Gribov tetra2005 at gmail.com
Thu Mar 20 09:41:27 PDT 2014


  Based on Alexey's comments. Tests still tbd.

Hi kcc, eugenis, samsonov,

http://llvm-reviews.chandlerc.com/D3043

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D3043?vs=7935&id=7990#toc

Files:
  include/clang/Driver/Options.td
  include/clang/Driver/SanitizerArgs.h
  lib/Driver/SanitizerArgs.cpp
  lib/Driver/Tools.cpp

Index: include/clang/Driver/Options.td
===================================================================
--- include/clang/Driver/Options.td
+++ include/clang/Driver/Options.td
@@ -359,6 +359,7 @@
   HelpText<"Enable Apple gcc-compatible #pragma pack handling">;
 def faddress_sanitizer : Flag<["-"], "faddress-sanitizer">, Group<f_Group>;
 def fno_address_sanitizer : Flag<["-"], "fno-address-sanitizer">, Group<f_Group>;
+def shared_libasan : Flag<["-"], "shared-libasan">;
 def fthread_sanitizer : Flag<["-"], "fthread-sanitizer">, Group<f_Group>;
 def fno_thread_sanitizer : Flag<["-"], "fno-thread-sanitizer">, Group<f_Group>;
 def fasm : Flag<["-"], "fasm">, Group<f_Group>;
Index: include/clang/Driver/SanitizerArgs.h
===================================================================
--- include/clang/Driver/SanitizerArgs.h
+++ include/clang/Driver/SanitizerArgs.h
@@ -51,13 +51,15 @@
   bool MsanTrackOrigins;
   bool AsanZeroBaseShadow;
   bool UbsanTrapOnError;
+  bool AsanSharedRuntime;
 
  public:
   SanitizerArgs();
   /// Parses the sanitizer arguments from an argument list.
   SanitizerArgs(const ToolChain &TC, const llvm::opt::ArgList &Args);
 
   bool needsAsanRt() const { return Kind & NeedsAsanRt; }
+  bool needsSharedAsanRt() const { return AsanSharedRuntime; }
   bool needsTsanRt() const { return Kind & NeedsTsanRt; }
   bool needsMsanRt() const { return Kind & NeedsMsanRt; }
   bool needsLeakDetection() const { return Kind & NeedsLeakDetection; }
Index: lib/Driver/SanitizerArgs.cpp
===================================================================
--- lib/Driver/SanitizerArgs.cpp
+++ lib/Driver/SanitizerArgs.cpp
@@ -26,6 +26,7 @@
   MsanTrackOrigins = false;
   AsanZeroBaseShadow = false;
   UbsanTrapOnError = false;
+  AsanSharedRuntime = false;
 }
 
 SanitizerArgs::SanitizerArgs() {
@@ -168,9 +169,12 @@
       Args.hasFlag(options::OPT_fsanitize_memory_track_origins,
                    options::OPT_fno_sanitize_memory_track_origins,
                    /* Default */false);
-  if (NeedsAsan)
+
+  if (NeedsAsan) {
+    AsanSharedRuntime = Args.hasArg(options::OPT_shared_libasan);
     AsanZeroBaseShadow =
         (TC.getTriple().getEnvironment() == llvm::Triple::Android);
+  }
 }
 
 void SanitizerArgs::addArgs(const llvm::opt::ArgList &Args,
Index: lib/Driver/Tools.cpp
===================================================================
--- lib/Driver/Tools.cpp
+++ lib/Driver/Tools.cpp
@@ -1809,57 +1809,87 @@
 static void addSanitizerRTLinkFlags(
     const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs,
     const StringRef Sanitizer, bool BeforeLibStdCXX,
-    bool ExportSymbols = true) {
+    bool ExportSymbols = true,
+    bool NeedsSharedRT = false) {
+  bool Executable = !Args.hasArg(options::OPT_shared);
+
   // Sanitizer runtime has name "libclang_rt.<Sanitizer>-<ArchName>.a".
   SmallString<128> LibSanitizer = getCompilerRTLibDir(TC);
   llvm::sys::path::append(LibSanitizer,
-                          (Twine("libclang_rt.") + Sanitizer + "-" +
-                           getArchNameForCompilerRTLib(TC) + ".a"));
+                          Twine("libclang_rt.") + Sanitizer + "-" +
+                           getArchNameForCompilerRTLib(TC) +
+                           (NeedsSharedRT ? "-dynamic.so" : ".a"));
+  SmallString<128> LibSanitizerPreinit = getCompilerRTLibDir(TC);
+  llvm::sys::path::append(LibSanitizerPreinit,
+                          Twine("libclang_rt." + Sanitizer + "-" +
+                          getArchNameForCompilerRTLib(TC) +
+                          "-preinit.a"));
 
   // Sanitizer runtime may need to come before -lstdc++ (or -lc++, libstdc++.a,
   // etc.) so that the linker picks custom versions of the global 'operator
   // new' and 'operator delete' symbols. We take the extreme (but simple)
-  // strategy of inserting it at the front of the link command. It also
-  // needs to be forced to end up in the executable, so wrap it in
-  // whole-archive.
-  SmallVector<const char *, 3> LibSanitizerArgs;
-  LibSanitizerArgs.push_back("-whole-archive");
-  LibSanitizerArgs.push_back(Args.MakeArgString(LibSanitizer));
-  LibSanitizerArgs.push_back("-no-whole-archive");
+  // strategy of inserting it at the front of the link command.
 
-  CmdArgs.insert(BeforeLibStdCXX ? CmdArgs.begin() : CmdArgs.end(),
-                 LibSanitizerArgs.begin(), LibSanitizerArgs.end());
+  SmallVector<const char *, 4> LibSanitizerArgs;
 
-  CmdArgs.push_back("-lpthread");
-  CmdArgs.push_back("-lrt");
-  CmdArgs.push_back("-ldl");
-  CmdArgs.push_back("-lm");
-
-  // If possible, use a dynamic symbols file to export the symbols from the
-  // runtime library. If we can't do so, use -export-dynamic instead to export
-  // all symbols from the binary.
-  if (ExportSymbols) {
-    if (llvm::sys::fs::exists(LibSanitizer + ".syms"))
-      CmdArgs.push_back(
-          Args.MakeArgString("--dynamic-list=" + LibSanitizer + ".syms"));
-    else
-      CmdArgs.push_back("-export-dynamic");
+  if (Executable) {
+    // Force initialization code to end up in the executable
+    // by wrapping it in whole-archive.
+    LibSanitizerArgs.push_back("-whole-archive");
+    LibSanitizerArgs.push_back(Args.MakeArgString(LibSanitizerPreinit));
+    LibSanitizerArgs.push_back("-no-whole-archive");
+
+    if (NeedsSharedRT) {
+      LibSanitizerArgs.push_back(Args.MakeArgString(LibSanitizer));
+    } else {
+      // Force static runtime to end up in the executable
+      // by wrapping it in whole-archive.
+      LibSanitizerArgs.push_back("-whole-archive");
+      LibSanitizerArgs.push_back(Args.MakeArgString(LibSanitizer));
+      LibSanitizerArgs.push_back("-no-whole-archive");
+
+      // If possible, use a dynamic symbols file to export the symbols from the
+      // runtime library. If we can't do so, use -export-dynamic instead to export
+      // all symbols from the binary.
+      if (ExportSymbols) {
+        if (llvm::sys::fs::exists(LibSanitizer + ".syms"))
+          CmdArgs.push_back(
+            Args.MakeArgString("--dynamic-list=" + LibSanitizer + ".syms"));
+        else
+          CmdArgs.push_back("-export-dynamic");
+      }
+    }
+  } else {
+    if (NeedsSharedRT)
+      LibSanitizerArgs.push_back(Args.MakeArgString(LibSanitizer));
   }
+
+  CmdArgs.insert(BeforeLibStdCXX ? CmdArgs.begin() : CmdArgs.end(),
+                 LibSanitizerArgs.begin(), LibSanitizerArgs.end());
 }
 
 /// If AddressSanitizer is enabled, add appropriate linker flags (Linux).
 /// This needs to be called before we add the C run-time (malloc, etc).
 static void addAsanRT(const ToolChain &TC, const ArgList &Args,
-                      ArgStringList &CmdArgs) {
+                      ArgStringList &CmdArgs, bool NeedsSharedRT) {
   if (TC.getTriple().getEnvironment() == llvm::Triple::Android) {
     SmallString<128> LibAsan = getCompilerRTLibDir(TC);
     llvm::sys::path::append(LibAsan,
                             (Twine("libclang_rt.asan-") +
                              getArchNameForCompilerRTLib(TC) + "-android.so"));
     CmdArgs.insert(CmdArgs.begin(), Args.MakeArgString(LibAsan));
   } else {
-    if (!Args.hasArg(options::OPT_shared))
-      addSanitizerRTLinkFlags(TC, Args, CmdArgs, "asan", true);
+    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "asan", true, true, NeedsSharedRT);
+
+    bool Executable = !Args.hasArg(options::OPT_shared);
+    if (Executable && !NeedsSharedRT) {
+      // FIXME: this is not quite portable but we shouldn't force user
+      // to manually include these silly libs.
+      CmdArgs.push_back("-lpthread");
+      CmdArgs.push_back("-lrt");
+      CmdArgs.push_back("-ldl");
+      CmdArgs.push_back("-lm");
+    }
   }
 }
 
@@ -1921,7 +1951,7 @@
                     Sanitize.needsAsanRt() || Sanitize.needsTsanRt() ||
                     Sanitize.needsMsanRt() || Sanitize.needsLsanRt());
   if (Sanitize.needsAsanRt())
-    addAsanRT(TC, Args, CmdArgs);
+    addAsanRT(TC, Args, CmdArgs, Sanitize.needsSharedAsanRt());
   if (Sanitize.needsTsanRt())
     addTsanRT(TC, Args, CmdArgs);
   if (Sanitize.needsMsanRt())
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D3043.3.patch
Type: text/x-patch
Size: 8124 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140320/a9e12331/attachment.bin>


More information about the llvm-commits mailing list