r215940 - Update link strategy for sanitizer runtime libraries on Linux:

Alexey Samsonov vonosmas at gmail.com
Mon Aug 18 15:10:42 PDT 2014


Author: samsonov
Date: Mon Aug 18 17:10:42 2014
New Revision: 215940

URL: http://llvm.org/viewvc/llvm-project?rev=215940&view=rev
Log:
Update link strategy for sanitizer runtime libraries on Linux:

1. Always put static sanitizer runtimes to the front of the linker
invocation line. This was already done for all sanitizers except UBSan:
in case user provides static libstdc++ we need to make sure that new/delete
operator definitions are picked from sanitizer runtimes instead of libstdc++.
We have to put UBSan runtime first for similar reasons: it depends on some
libstdc++ parts (e.g. __dynamic_cast function), and has to go first in
link line to ensure these functions will be picked up from libstdc++.

2. Put sanitizer libraries system dependencies (-ldl, -lpthread etc.) right
after sanitizer runtimes. This will ensure these libraries participate in
the link even if user provided -Wl,-as-needed flag. This should fix PR15823.

3. In case we link in several sanitizer runtimes (e.g. "ubsan", "ubsan_cxx"
and "san"), add system dependencies (-ldl, -lpthread, ...) only once.

Modified:
    cfe/trunk/lib/Driver/Tools.cpp
    cfe/trunk/test/Driver/sanitizer-ld.c

Modified: cfe/trunk/lib/Driver/Tools.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=215940&r1=215939&r2=215940&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/Tools.cpp (original)
+++ cfe/trunk/lib/Driver/Tools.cpp Mon Aug 18 17:10:42 2014
@@ -2152,9 +2152,7 @@ static SmallString<128> getSanitizerRTLi
 static void addSanitizerRTLinkFlags(const ToolChain &TC, const ArgList &Args,
                                     ArgStringList &CmdArgs,
                                     const StringRef Sanitizer,
-                                    bool BeforeLibStdCXX,
-                                    bool ExportSymbols = true,
-                                    bool LinkDeps = true) {
+                                    bool ExportSymbols, bool LinkDeps) {
   SmallString<128> LibSanitizer =
       getSanitizerRTLibName(TC, Sanitizer, /*Shared*/ false);
 
@@ -2164,34 +2162,34 @@ static void addSanitizerRTLinkFlags(cons
   // 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;
+  SmallVector<const char *, 8> LibSanitizerArgs;
   LibSanitizerArgs.push_back("-whole-archive");
   LibSanitizerArgs.push_back(Args.MakeArgString(LibSanitizer));
   LibSanitizerArgs.push_back("-no-whole-archive");
-
-  CmdArgs.insert(BeforeLibStdCXX ? CmdArgs.begin() : CmdArgs.end(),
-                 LibSanitizerArgs.begin(), LibSanitizerArgs.end());
-
   if (LinkDeps) {
-    // Link sanitizer dependencies explicitly
-    CmdArgs.push_back("-lpthread");
-    CmdArgs.push_back("-lrt");
-    CmdArgs.push_back("-lm");
+    // Link sanitizer dependencies explicitly. These libraries should be added
+    // at the front of the link command, so that they will definitely
+    // participate in link even if user specified -Wl,-as-needed (see PR15823).
+    LibSanitizerArgs.push_back("-lpthread");
+    LibSanitizerArgs.push_back("-lrt");
+    LibSanitizerArgs.push_back("-lm");
     // There's no libdl on FreeBSD.
     if (TC.getTriple().getOS() != llvm::Triple::FreeBSD)
-      CmdArgs.push_back("-ldl");
+      LibSanitizerArgs.push_back("-ldl");
   }
-
   // 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(
+      LibSanitizerArgs.push_back(
           Args.MakeArgString("--dynamic-list=" + LibSanitizer + ".syms"));
     else
-      CmdArgs.push_back("-export-dynamic");
+      LibSanitizerArgs.push_back("-export-dynamic");
   }
+
+  CmdArgs.insert(CmdArgs.begin(), LibSanitizerArgs.begin(),
+                 LibSanitizerArgs.end());
 }
 
 /// If AddressSanitizer is enabled, add appropriate linker flags (Linux).
@@ -2212,12 +2210,14 @@ static void addAsanRT(const ToolChain &T
 
   if (Shared) {
     addSanitizerRTLinkFlags(TC, Args, CmdArgs, "asan-preinit",
-                            /*BeforeLibStdCXX*/ true, /*ExportSymbols*/ false,
+                            /*ExportSymbols*/ false,
                             /*LinkDeps*/ false);
   } else {
-    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "asan", true);
+    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "asan", /*ExportSymbols*/ true,
+                            /*LinkDeps*/ true);
     if (IsCXX)
-      addSanitizerRTLinkFlags(TC, Args, CmdArgs, "asan_cxx", true);
+      addSanitizerRTLinkFlags(TC, Args, CmdArgs, "asan_cxx",
+                              /*ExportSymbols*/ true, /*LinkDeps*/ false);
   }
 }
 
@@ -2226,7 +2226,8 @@ static void addAsanRT(const ToolChain &T
 static void addTsanRT(const ToolChain &TC, const ArgList &Args,
                       ArgStringList &CmdArgs) {
   if (!Args.hasArg(options::OPT_shared))
-    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "tsan", true);
+    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "tsan", /*ExportSymbols*/ true,
+                            /*LinkDeps*/ true);
 }
 
 /// If MemorySanitizer is enabled, add appropriate linker flags (Linux).
@@ -2234,7 +2235,8 @@ static void addTsanRT(const ToolChain &T
 static void addMsanRT(const ToolChain &TC, const ArgList &Args,
                       ArgStringList &CmdArgs) {
   if (!Args.hasArg(options::OPT_shared))
-    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "msan", true);
+    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "msan", /*ExportSymbols*/ true,
+                            /*LinkDeps*/ true);
 }
 
 /// If LeakSanitizer is enabled, add appropriate linker flags (Linux).
@@ -2242,7 +2244,8 @@ static void addMsanRT(const ToolChain &T
 static void addLsanRT(const ToolChain &TC, const ArgList &Args,
                       ArgStringList &CmdArgs) {
   if (!Args.hasArg(options::OPT_shared))
-    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "lsan", true);
+    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "lsan", /*ExportSymbols */ true,
+                            /*LinkDeps*/ true);
 }
 
 /// If UndefinedBehaviorSanitizer is enabled, add appropriate linker flags
@@ -2257,20 +2260,24 @@ static void addUbsanRT(const ToolChain &
   // Need a copy of sanitizer_common. This could come from another sanitizer
   // runtime; if we're not including one, include our own copy.
   if (!HasOtherSanitizerRt)
-    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "san", true, false);
+    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "san", /*ExportSymbols*/ false,
+                            /*LinkDeps*/ false);
 
-  addSanitizerRTLinkFlags(TC, Args, CmdArgs, "ubsan", false, true);
+  addSanitizerRTLinkFlags(TC, Args, CmdArgs, "ubsan", /*ExportSymbols*/ true,
+                          /*LinkDeps*/ true);
 
   // Only include the bits of the runtime which need a C++ ABI library if
   // we're linking in C++ mode.
   if (IsCXX)
-    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "ubsan_cxx", false, true);
+    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "ubsan_cxx",
+                            /*ExportSymbols*/ true, /*LinkDeps*/ false);
 }
 
 static void addDfsanRT(const ToolChain &TC, const ArgList &Args,
                        ArgStringList &CmdArgs) {
   if (!Args.hasArg(options::OPT_shared))
-    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "dfsan", true);
+    addSanitizerRTLinkFlags(TC, Args, CmdArgs, "dfsan", /*ExportSymbols*/ true,
+                            /*LinkDeps*/ true);
 }
 
 // Should be called before we add C++ ABI library.

Modified: cfe/trunk/test/Driver/sanitizer-ld.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/sanitizer-ld.c?rev=215940&r1=215939&r2=215940&view=diff
==============================================================================
--- cfe/trunk/test/Driver/sanitizer-ld.c (original)
+++ cfe/trunk/test/Driver/sanitizer-ld.c Mon Aug 18 17:10:42 2014
@@ -188,11 +188,16 @@
 // RUN:   | FileCheck --check-prefix=CHECK-UBSAN-LINUX %s
 // CHECK-UBSAN-LINUX: "{{.*}}ld{{(.exe)?}}"
 // CHECK-UBSAN-LINUX-NOT: libclang_rt.asan
-// CHECK-UBSAN-LINUX: "-whole-archive" "{{.*}}libclang_rt.san-i386.a" "-no-whole-archive"
-// CHECK-UBSAN-LINUX-NOT: libclang_rt.asan
+// CHECK-UBSAN-LINUX-NOT: libclang_rt.ubsan_cxx
 // CHECK-UBSAN-LINUX: "-whole-archive" "{{.*}}libclang_rt.ubsan-i386.a" "-no-whole-archive"
+// CHECK-UBSAN-LINUX-NOT: libclang_rt.asan
 // CHECK-UBSAN-LINUX-NOT: libclang_rt.ubsan_cxx
 // CHECK-UBSAN-LINUX: "-lpthread"
+// CHECK-UBSAN-LINUX-NOT: libclang_rt.asan
+// CHECK-UBSAN-LINUX-NOT: libclang_rt.ubsan_cxx
+// CHECK-UBSAN-LINUX: "-whole-archive" "{{.*}}libclang_rt.san-i386.a" "-no-whole-archive"
+// CHECK-UBSAN-LINUX-NOT: libclang_rt.asan
+// CHECK-UBSAN-LINUX-NOT: libclang_rt.ubsan_cxx
 // CHECK-UBSAN-LINUX-NOT: "-lstdc++"
 
 // RUN: %clang -fsanitize=undefined -fsanitize-link-c++-runtime %s -### -o %t.o 2>&1 \
@@ -210,13 +215,15 @@
 // RUN:   | FileCheck --check-prefix=CHECK-UBSAN-LINUX-CXX %s
 // CHECK-UBSAN-LINUX-CXX: "{{.*}}ld{{(.exe)?}}"
 // CHECK-UBSAN-LINUX-CXX-NOT: libclang_rt.asan
-// CHECK-UBSAN-LINUX-CXX: "-whole-archive" "{{.*}}libclang_rt.san-i386.a" "-no-whole-archive"
+// CHECK-UBSAN-LINUX-CXX: "-whole-archive" "{{.*}}libclang_rt.ubsan_cxx-i386.a" "-no-whole-archive"
+// CHECK-UBSAN-LINUX-CXX: "--dynamic-list={{.*}}libclang_rt.ubsan_cxx-i386.a.syms"
 // CHECK-UBSAN-LINUX-CXX-NOT: libclang_rt.asan
 // CHECK-UBSAN-LINUX-CXX: "-whole-archive" "{{.*}}libclang_rt.ubsan-i386.a" "-no-whole-archive"
-// CHECK-UBSAN-LINUX-CXX: "--dynamic-list={{.*}}libclang_rt.ubsan-i386.a.syms"
-// CHECK-UBSAN-LINUX-CXX: "-whole-archive" "{{.*}}libclang_rt.ubsan_cxx-i386.a" "-no-whole-archive"
 // CHECK-UBSAN-LINUX-CXX: "-lpthread"
-// CHECK-UBSAN-LINUX-CXX: "--dynamic-list={{.*}}libclang_rt.ubsan_cxx-i386.a.syms"
+// CHECK-UBSAN-LINUX-CXX: "--dynamic-list={{.*}}libclang_rt.ubsan-i386.a.syms"
+// CHECK-UBSAN-LINUX-CXX-NOT: libclang_rt.asan
+// CHECK-UBSAN-LINUX-CXX: "-whole-archive" "{{.*}}libclang_rt.san-i386.a" "-no-whole-archive"
+// CHECK-UBSAN-LINUX-CXX-NOT: libclang_rt.asan
 // CHECK-UBSAN-LINUX-CXX: "-lstdc++"
 
 // RUN: %clang -fsanitize=address,undefined %s -### -o %t.o 2>&1 \
@@ -240,8 +247,8 @@
 // CHECK-ASAN-UBSAN-LINUX-CXX-NOT: libclang_rt.san
 // CHECK-ASAN-UBSAN-LINUX-CXX: "-whole-archive" "{{.*}}libclang_rt.asan-i386.a" "-no-whole-archive"
 // CHECK-ASAN-UBSAN-LINUX-CXX-NOT: libclang_rt.san
-// CHECK-ASAN-UBSAN-LINUX-CXX: "-whole-archive" "{{.*}}libclang_rt.ubsan-i386.a" "-no-whole-archive"
 // CHECK-ASAN-UBSAN-LINUX-CXX: "-whole-archive" "{{.*}}libclang_rt.ubsan_cxx-i386.a" "-no-whole-archive"
+// CHECK-ASAN-UBSAN-LINUX-CXX: "-whole-archive" "{{.*}}libclang_rt.ubsan-i386.a" "-no-whole-archive"
 // CHECK-ASAN-UBSAN-LINUX-CXX: "-lpthread"
 // CHECK-ASAN-UBSAN-LINUX-CXX: "-lstdc++"
 





More information about the cfe-commits mailing list