r177605 - Split ubsan runtime into three pieces (clang part):

Richard Smith richard-llvm at metafoo.co.uk
Wed Mar 20 16:49:08 PDT 2013


Author: rsmith
Date: Wed Mar 20 18:49:07 2013
New Revision: 177605

URL: http://llvm.org/viewvc/llvm-project?rev=177605&view=rev
Log:
Split ubsan runtime into three pieces (clang part):
 * libclang_rt-san-* is sanitizer_common, and is linked in only if no other
   sanitizer runtime is present.
 * libclang_rt-ubsan-* is the piece of the runtime which doesn't depend on
   a C++ ABI library, and is always linked in.
 * libclang_rt-ubsan_cxx-* is the piece of the runtime which depends on a
   C++ ABI library, and is only linked in when linking a C++ binary.

This change also switches us to using -whole-archive for the ubsan runtime
(which is made possible by the above split), and switches us to only linking
the sanitizer runtime into the main binary and not into DSOs (which is made
possible by using -whole-archive).

The motivation for this is to only link a single copy of sanitizer_common
into any binary. This is becoming important now because we want to share
more state between multiple sanitizers in the same process (for instance,
we want a single shared output mutex).

The Darwin ubsan runtime is unchanged; because we use a DSO there, we don't
need this complexity.

Modified:
    cfe/trunk/lib/Driver/Tools.cpp
    cfe/trunk/runtime/compiler-rt/Makefile
    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=177605&r1=177604&r2=177605&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/Tools.cpp (original)
+++ cfe/trunk/lib/Driver/Tools.cpp Wed Mar 20 18:49:07 2013
@@ -1582,21 +1582,21 @@ static void addSanitizerRTLinkFlagsLinux
   llvm::sys::path::append(
       LibSanitizer, "lib", "linux",
       (Twine("libclang_rt.") + Sanitizer + "-" + TC.getArchName() + ".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.
-  if (BeforeLibStdCXX) {
-    SmallVector<const char *, 3> PrefixArgs;
-    PrefixArgs.push_back("-whole-archive");
-    PrefixArgs.push_back(Args.MakeArgString(LibSanitizer));
-    PrefixArgs.push_back("-no-whole-archive");
-    CmdArgs.insert(CmdArgs.begin(), PrefixArgs.begin(), PrefixArgs.end());
-  } else {
-    CmdArgs.push_back(Args.MakeArgString(LibSanitizer));
-  }
+  SmallVector<const char *, 3> 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());
+
   CmdArgs.push_back("-lpthread");
   CmdArgs.push_back("-ldl");
   CmdArgs.push_back("-export-dynamic");
@@ -1658,8 +1658,22 @@ static void addMsanRTLinux(const ToolCha
 /// If UndefinedBehaviorSanitizer is enabled, add appropriate linker flags
 /// (Linux).
 static void addUbsanRTLinux(const ToolChain &TC, const ArgList &Args,
-                            ArgStringList &CmdArgs) {
+                            ArgStringList &CmdArgs, bool IsCXX,
+                            bool HasOtherSanitizerRt) {
+  if (Args.hasArg(options::OPT_shared))
+    return;
+
+  // 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)
+    addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "san", true);
+
   addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "ubsan", false);
+
+  // Only include the bits of the runtime which need a C++ ABI library if
+  // we're linking in C++ mode.
+  if (IsCXX)
+    addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "ubsan_cxx", false);
 }
 
 static bool shouldUseFramePointer(const ArgList &Args,
@@ -5876,7 +5890,9 @@ void linuxtools::Link::ConstructJob(Comp
 
   // Call these before we add the C++ ABI library.
   if (Sanitize.needsUbsanRt())
-    addUbsanRTLinux(getToolChain(), Args, CmdArgs);
+    addUbsanRTLinux(getToolChain(), Args, CmdArgs, D.CCCIsCXX,
+                    Sanitize.needsAsanRt() || Sanitize.needsTsanRt() ||
+                    Sanitize.needsMsanRt());
   if (Sanitize.needsAsanRt())
     addAsanRTLinux(getToolChain(), Args, CmdArgs);
   if (Sanitize.needsTsanRt())

Modified: cfe/trunk/runtime/compiler-rt/Makefile
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/runtime/compiler-rt/Makefile?rev=177605&r1=177604&r2=177605&view=diff
==============================================================================
--- cfe/trunk/runtime/compiler-rt/Makefile (original)
+++ cfe/trunk/runtime/compiler-rt/Makefile Wed Mar 20 18:49:07 2013
@@ -99,13 +99,14 @@ TryCompile = \
 # We currently only try to generate runtime libraries on x86.
 ifeq ($(ARCH),x86)
 RuntimeLibrary.linux.Configs += \
-	full-i386.a profile-i386.a asan-i386.a ubsan-i386.a
+	full-i386.a profile-i386.a san-i386.a asan-i386.a ubsan-i386.a \
+	ubsan_cxx-i386.a
 endif
 
 ifeq ($(ARCH),x86_64)
 RuntimeLibrary.linux.Configs += \
-	full-x86_64.a profile-x86_64.a asan-x86_64.a tsan-x86_64.a msan-x86_64.a \
-	ubsan-x86_64.a
+	full-x86_64.a profile-x86_64.a san-x86_64.a asan-x86_64.a \
+	tsan-x86_64.a msan-x86_64.a ubsan-x86_64.a ubsan_cxx-x86_64.a
 # We need to build 32-bit ASan/UBsan libraries on 64-bit platform, and add them
 # to the list of runtime libraries to make
 # "clang -fsanitize=(address|undefined) -m32" work.
@@ -113,7 +114,8 @@ RuntimeLibrary.linux.Configs += \
 # executable.
 test_source = $(LLVM_SRC_ROOT)/tools/clang/runtime/compiler-rt/clang_linux_test_input.c
 ifeq ($(call TryCompile,$(ToolDir)/clang,$(test_source),-m32),0)
-RuntimeLibrary.linux.Configs += asan-i386.a ubsan-i386.a
+RuntimeLibrary.linux.Configs += san-i386.a asan-i386.a ubsan-i386.a \
+                                ubsan_cxx-i386.a
 endif
 ifneq ($(LLVM_ANDROID_TOOLCHAIN_DIR),)
 RuntimeLibrary.linux.Configs += asan-arm-android.so

Modified: cfe/trunk/test/Driver/sanitizer-ld.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/sanitizer-ld.c?rev=177605&r1=177604&r2=177605&view=diff
==============================================================================
--- cfe/trunk/test/Driver/sanitizer-ld.c (original)
+++ cfe/trunk/test/Driver/sanitizer-ld.c Wed Mar 20 18:49:07 2013
@@ -87,9 +87,52 @@
 // RUN:     --sysroot=%S/Inputs/basic_linux_tree \
 // RUN:   | FileCheck --check-prefix=CHECK-UBSAN-LINUX %s
 // CHECK-UBSAN-LINUX: "{{.*}}ld{{(.exe)?}}"
-// CHECK-UBSAN-LINUX-NOT: "-lc"
-// CHECK-UBSAN-LINUX: libclang_rt.ubsan-i386.a"
+// 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: "-whole-archive" "{{.*}}libclang_rt.ubsan-i386.a" "-no-whole-archive"
+// CHECK-UBSAN-LINUX-NOT: libclang_rt.ubsan_cxx
 // CHECK-UBSAN-LINUX: "-lpthread"
+// CHECK-UBSAN-LINUX-NOT: "-lstdc++"
+
+// RUN: %clangxx -fsanitize=undefined %s -### -o %t.o 2>&1 \
+// RUN:     -target i386-unknown-linux \
+// RUN:     --sysroot=%S/Inputs/basic_linux_tree \
+// 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-NOT: libclang_rt.asan
+// CHECK-UBSAN-LINUX-CXX: "-whole-archive" "{{.*}}libclang_rt.ubsan-i386.a" "-no-whole-archive"
+// CHECK-UBSAN-LINUX-CXX: "-whole-archive" "{{.*}}libclang_rt.ubsan_cxx-i386.a" "-no-whole-archive"
+// CHECK-UBSAN-LINUX-CXX: "-lpthread"
+// CHECK-UBSAN-LINUX-CXX: "-lstdc++"
+
+// RUN: %clang -fsanitize=address,undefined %s -### -o %t.o 2>&1 \
+// RUN:     -target i386-unknown-linux \
+// RUN:     --sysroot=%S/Inputs/basic_linux_tree \
+// RUN:   | FileCheck --check-prefix=CHECK-ASAN-UBSAN-LINUX %s
+// CHECK-ASAN-UBSAN-LINUX: "{{.*}}ld{{(.exe)?}}"
+// CHECK-ASAN-UBSAN-LINUX-NOT: libclang_rt.san
+// CHECK-ASAN-UBSAN-LINUX: "-whole-archive" "{{.*}}libclang_rt.asan-i386.a" "-no-whole-archive"
+// CHECK-ASAN-UBSAN-LINUX-NOT: libclang_rt.san
+// CHECK-ASAN-UBSAN-LINUX: "-whole-archive" "{{.*}}libclang_rt.ubsan-i386.a" "-no-whole-archive"
+// CHECK-ASAN-UBSAN-LINUX-NOT: libclang_rt.ubsan_cxx
+// CHECK-ASAN-UBSAN-LINUX: "-lpthread"
+// CHECK-ASAN-UBSAN-LINUX-NOT: "-lstdc++"
+
+// RUN: %clangxx -fsanitize=address,undefined %s -### -o %t.o 2>&1 \
+// RUN:     -target i386-unknown-linux \
+// RUN:     --sysroot=%S/Inputs/basic_linux_tree \
+// RUN:   | FileCheck --check-prefix=CHECK-ASAN-UBSAN-LINUX-CXX %s
+// CHECK-ASAN-UBSAN-LINUX-CXX: "{{.*}}ld{{(.exe)?}}"
+// 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: "-lpthread"
+// CHECK-ASAN-UBSAN-LINUX-CXX: "-lstdc++"
 
 // RUN: %clang -fsanitize=undefined %s -### -o %t.o 2>&1 \
 // RUN:     -target i386-unknown-linux \
@@ -97,6 +140,4 @@
 // RUN:     -shared \
 // RUN:   | FileCheck --check-prefix=CHECK-UBSAN-LINUX-SHARED %s
 // CHECK-UBSAN-LINUX-SHARED: "{{.*}}ld{{(.exe)?}}"
-// CHECK-UBSAN-LINUX-SHARED-NOT: "-lc"
-// CHECK-UBSAN-LINUX-SHARED: libclang_rt.ubsan-i386.a"
-// CHECK-UBSAN-LINUX-SHARED: "-lpthread"
+// CHECK-UBSAN-LINUX-SHARED-NOT: libclang_rt.ubsan-i386.a"





More information about the cfe-commits mailing list