return LibSanitizer;
}
-static void addSanitizerRTLinkFlags(const ToolChain &TC, const ArgList &Args,
- ArgStringList &CmdArgs,
- StringRef Sanitizer,
- bool ExportSymbols, bool LinkDeps) {
- SmallString<128> LibSanitizer =
- getSanitizerRTLibName(TC, Sanitizer, /*Shared*/ false);
-
- // 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
+static void addSanitizerRuntime(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs, StringRef Sanitizer,
+ bool IsShared) {
+ SmallString<128> LibSanitizer = getSanitizerRTLibName(TC, Sanitizer, IsShared);
+ // Static runtimes must be forced into executable, so we wrap them in
// whole-archive.
- SmallVector<const char *, 8> LibSanitizerArgs;
- LibSanitizerArgs.push_back("-whole-archive");
- LibSanitizerArgs.push_back(Args.MakeArgString(LibSanitizer));
- LibSanitizerArgs.push_back("-no-whole-archive");
- if (LinkDeps) {
- // 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)
- 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"))
- LibSanitizerArgs.push_back(
- Args.MakeArgString("--dynamic-list=" + LibSanitizer + ".syms"));
- else
- LibSanitizerArgs.push_back("-export-dynamic");
+ if (!IsShared)
+ CmdArgs.push_back("-whole-archive");
+ CmdArgs.push_back(Args.MakeArgString(LibSanitizer));
+ if (!IsShared)
+ CmdArgs.push_back("-no-whole-archive");
+}
+
+// Tries to use a file with the list of dynamic symbols that need to be exported
+// from the runtime library. Returns true if the file was found.
+static bool addSanitizerDynamicList(const ToolChain &TC, const ArgList &Args,
+ ArgStringList &CmdArgs,
+ StringRef Sanitizer) {
+ SmallString<128> LibSanitizer = getSanitizerRTLibName(TC, Sanitizer, false);
+ if (llvm::sys::fs::exists(LibSanitizer + ".syms")) {
+ CmdArgs.push_back(
+ Args.MakeArgString("--dynamic-list=" + LibSanitizer + ".syms"));
+ return true;
}
+ return false;
+}
- CmdArgs.insert(CmdArgs.begin(), LibSanitizerArgs.begin(),
- LibSanitizerArgs.end());
+static void linkSanitizerRuntimeDeps(const ToolChain &TC,
+ ArgStringList &CmdArgs) {
+ // Force linking against the system libraries sanitizers depends on
+ // (see PR15823 why this is necessary).
+ CmdArgs.push_back("--no-as-needed");
+ CmdArgs.push_back("-lpthread");
+ CmdArgs.push_back("-lrt");
+ CmdArgs.push_back("-lm");
+ // There's no libdl on FreeBSD.
+ if (TC.getTriple().getOS() != llvm::Triple::FreeBSD)
+ CmdArgs.push_back("-ldl");
}
-/// 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, bool Shared, bool IsCXX) {
- if (Shared) {
- // Link dynamic runtime if necessary.
- SmallString<128> LibSanitizer = getSanitizerRTLibName(TC, "asan", Shared);
- CmdArgs.insert(CmdArgs.begin(), Args.MakeArgString(LibSanitizer));
+static void
+collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
+ SmallVectorImpl<StringRef> &SharedRuntimes,
+ SmallVectorImpl<StringRef> &StaticRuntimes,
+ SmallVectorImpl<StringRef> &HelperStaticRuntimes) {
+ const SanitizerArgs &SanArgs = TC.getSanitizerArgs();
+ // Collect shared runtimes.
+ if (SanArgs.needsAsanRt() && SanArgs.needsSharedAsanRt()) {
+ SharedRuntimes.push_back("asan");
}
- // Do not link static runtime to DSOs or if compiling for Android.
+ // Collect static runtimes.
if (Args.hasArg(options::OPT_shared) ||
- (TC.getTriple().getEnvironment() == llvm::Triple::Android))
- return;
-
- if (Shared) {
- addSanitizerRTLinkFlags(TC, Args, CmdArgs, "asan-preinit",
- /*ExportSymbols*/ false,
- /*LinkDeps*/ false);
- } else {
- addSanitizerRTLinkFlags(TC, Args, CmdArgs, "asan", /*ExportSymbols*/ true,
- /*LinkDeps*/ true);
- if (IsCXX)
- addSanitizerRTLinkFlags(TC, Args, CmdArgs, "asan_cxx",
- /*ExportSymbols*/ true, /*LinkDeps*/ false);
- }
-}
-
-/// If ThreadSanitizer is enabled, add appropriate linker flags (Linux).
-/// This needs to be called before we add the C run-time (malloc, etc).
-static void addTsanRT(const ToolChain &TC, const ArgList &Args,
- ArgStringList &CmdArgs) {
- if (!Args.hasArg(options::OPT_shared))
- addSanitizerRTLinkFlags(TC, Args, CmdArgs, "tsan", /*ExportSymbols*/ true,
- /*LinkDeps*/ true);
-}
-
-/// If MemorySanitizer is enabled, add appropriate linker flags (Linux).
-/// This needs to be called before we add the C run-time (malloc, etc).
-static void addMsanRT(const ToolChain &TC, const ArgList &Args,
- ArgStringList &CmdArgs) {
- if (!Args.hasArg(options::OPT_shared))
- addSanitizerRTLinkFlags(TC, Args, CmdArgs, "msan", /*ExportSymbols*/ true,
- /*LinkDeps*/ true);
-}
-
-/// If LeakSanitizer is enabled, add appropriate linker flags (Linux).
-/// This needs to be called before we add the C run-time (malloc, etc).
-static void addLsanRT(const ToolChain &TC, const ArgList &Args,
- ArgStringList &CmdArgs) {
- if (!Args.hasArg(options::OPT_shared))
- addSanitizerRTLinkFlags(TC, Args, CmdArgs, "lsan", /*ExportSymbols */ true,
- /*LinkDeps*/ true);
-}
-
-/// If UndefinedBehaviorSanitizer is enabled, add appropriate linker flags
-/// (Linux).
-static void addUbsanRT(const ToolChain &TC, const ArgList &Args,
- ArgStringList &CmdArgs, bool IsCXX,
- bool HasOtherSanitizerRt) {
- // Do not link runtime into shared libraries.
- if (Args.hasArg(options::OPT_shared))
+ (TC.getTriple().getEnvironment() == llvm::Triple::Android)) {
+ // Don't link static runtimes into DSOs or if compiling for Android.
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)
- addSanitizerRTLinkFlags(TC, Args, CmdArgs, "san", /*ExportSymbols*/ false,
- /*LinkDeps*/ false);
-
- 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",
- /*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", /*ExportSymbols*/ true,
- /*LinkDeps*/ true);
-}
-
-// Should be called before we add C++ ABI library.
-static void addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
+ }
+ if (SanArgs.needsAsanRt()) {
+ if (SanArgs.needsSharedAsanRt()) {
+ HelperStaticRuntimes.push_back("asan-preinit");
+ } else {
+ StaticRuntimes.push_back("asan");
+ if (SanArgs.linkCXXRuntimes())
+ StaticRuntimes.push_back("asan_cxx");
+ }
+ }
+ if (SanArgs.needsDfsanRt())
+ StaticRuntimes.push_back("dfsan");
+ if (SanArgs.needsLsanRt())
+ StaticRuntimes.push_back("lsan");
+ if (SanArgs.needsMsanRt())
+ StaticRuntimes.push_back("msan");
+ if (SanArgs.needsTsanRt())
+ StaticRuntimes.push_back("tsan");
+ // WARNING: UBSan should always go last.
+ if (SanArgs.needsUbsanRt()) {
+ // If UBSan is not combined with another sanitizer, we need to pull in
+ // sanitizer_common explicitly.
+ if (StaticRuntimes.empty())
+ HelperStaticRuntimes.push_back("san");
+ StaticRuntimes.push_back("ubsan");
+ if (SanArgs.linkCXXRuntimes())
+ StaticRuntimes.push_back("ubsan_cxx");
+ }
+}
+
+// Should be called before we add system libraries (C++ ABI, libstdc++/libc++,
+// C runtime, etc). Returns true if sanitizer system deps need to be linked in.
+static bool addSanitizerRuntimes(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs) {
- const SanitizerArgs &Sanitize = TC.getSanitizerArgs();
- if (Sanitize.needsUbsanRt())
- addUbsanRT(TC, Args, CmdArgs, Sanitize.linkCXXRuntimes(),
- Sanitize.needsAsanRt() || Sanitize.needsTsanRt() ||
- Sanitize.needsMsanRt() || Sanitize.needsLsanRt());
- if (Sanitize.needsAsanRt())
- addAsanRT(TC, Args, CmdArgs, Sanitize.needsSharedAsanRt(),
- Sanitize.linkCXXRuntimes());
- if (Sanitize.needsTsanRt())
- addTsanRT(TC, Args, CmdArgs);
- if (Sanitize.needsMsanRt())
- addMsanRT(TC, Args, CmdArgs);
- if (Sanitize.needsLsanRt())
- addLsanRT(TC, Args, CmdArgs);
- if (Sanitize.needsDfsanRt())
- addDfsanRT(TC, Args, CmdArgs);
+ SmallVector<StringRef, 4> SharedRuntimes, StaticRuntimes,
+ HelperStaticRuntimes;
+ collectSanitizerRuntimes(TC, Args, SharedRuntimes, StaticRuntimes,
+ HelperStaticRuntimes);
+ for (auto RT : SharedRuntimes)
+ addSanitizerRuntime(TC, Args, CmdArgs, RT, true);
+ for (auto RT : HelperStaticRuntimes)
+ addSanitizerRuntime(TC, Args, CmdArgs, RT, false);
+ bool AddExportDynamic = false;
+ for (auto RT : StaticRuntimes) {
+ addSanitizerRuntime(TC, Args, CmdArgs, RT, false);
+ AddExportDynamic |= !addSanitizerDynamicList(TC, Args, CmdArgs, RT);
+ }
+ // If there is a static runtime with no dynamic list, force all the symbols
+ // to be dynamic to be sure we export sanitizer interface functions.
+ if (AddExportDynamic)
+ CmdArgs.push_back("-export-dynamic");
+ return !StaticRuntimes.empty();
}
static bool shouldUseFramePointerForTarget(const ArgList &Args,
if (D.IsUsingLTO(Args))
AddGoldPlugin(ToolChain, Args, CmdArgs);
+ bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
if (!Args.hasArg(options::OPT_nostdlib) &&
else
CmdArgs.push_back("-lm");
}
+ if (NeedsSanitizerDeps)
+ linkSanitizerRuntimeDeps(ToolChain, CmdArgs);
// FIXME: For some reason GCC passes -lgcc and -lgcc_s before adding
// the default system libraries. Just mimic this for now.
if (Args.hasArg(options::OPT_pg))
CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o")));
}
- addSanitizerRuntimes(getToolChain(), Args, CmdArgs);
-
addProfileRT(ToolChain, Args, CmdArgs);
const char *Exec =
if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
CmdArgs.push_back("--no-demangle");
+ bool NeedsSanitizerDeps = addSanitizerRuntimes(ToolChain, Args, CmdArgs);
AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs);
-
- addSanitizerRuntimes(getToolChain(), Args, CmdArgs);
// The profile runtime also needs access to system libraries.
addProfileRT(getToolChain(), Args, CmdArgs);
if (Args.hasArg(options::OPT_static))
CmdArgs.push_back("--start-group");
+ if (NeedsSanitizerDeps)
+ linkSanitizerRuntimeDeps(ToolChain, CmdArgs);
+
LibOpenMP UsedOpenMPLib = LibUnknown;
if (Args.hasArg(options::OPT_fopenmp)) {
UsedOpenMPLib = LibGOMP;
// CHECK-ASAN-LINUX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
// CHECK-ASAN-LINUX-NOT: "-lc"
// CHECK-ASAN-LINUX: libclang_rt.asan-i386.a"
+// CHECK-ASAN-LINUX-NOT: "-export-dynamic"
+// CHECK-ASAN-LINUX: "--dynamic-list={{.*}}libclang_rt.asan-i386.a.syms"
+// CHECK-ASAN-LINUX-NOT: "-export-dynamic"
// CHECK-ASAN-LINUX: "-lpthread"
// CHECK-ASAN-LINUX: "-lrt"
// CHECK-ASAN-LINUX: "-ldl"
-// CHECK-ASAN-LINUX-NOT: "-export-dynamic"
-// CHECK-ASAN-LINUX: "--dynamic-list={{.*}}libclang_rt.asan-i386.a.syms"
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
// RUN: -target i386-unknown-linux -fsanitize=address -shared-libasan \
// CHECK-SHARED-ASAN-LINUX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
// CHECK-SHARED-ASAN-LINUX-NOT: "-lc"
// CHECK-SHARED-ASAN-LINUX-NOT: libclang_rt.asan-i386.a"
-// CHECK-SHARED-ASAN-LINUX: "-whole-archive" "{{.*}}libclang_rt.asan-preinit-i386.a" "-no-whole-archive"
// CHECK-SHARED-ASAN-LINUX: libclang_rt.asan-i386.so"
+// CHECK-SHARED-ASAN-LINUX: "-whole-archive" "{{.*}}libclang_rt.asan-preinit-i386.a" "-no-whole-archive"
// CHECK-SHARED-ASAN-LINUX-NOT: "-lpthread"
// CHECK-SHARED-ASAN-LINUX-NOT: "-lrt"
// CHECK-SHARED-ASAN-LINUX-NOT: "-ldl"
// CHECK-ASAN-FREEBSD-NOT: libclang_rt.asan_cxx
// CHECK-ASAN-FREEBSD: freebsd{{/|\\+}}libclang_rt.asan-i386.a"
// CHECK-ASAN-FREEBSD-NOT: libclang_rt.asan_cxx
+// CHECK-ASAN-FREEBSD-NOT: "--dynamic-list"
+// CHECK-ASAN-FREEBSD: "-export-dynamic"
// CHECK-ASAN-FREEBSD: "-lpthread"
// CHECK-ASAN-FREEBSD: "-lrt"
-// CHECK-ASAN-FREEBSD: "-export-dynamic"
-// CHECK-ASAN-FREEBSD-NOT: "--dynamic-list"
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
// RUN: -target i386-unknown-freebsd -fsanitize=address \
//
// CHECK-ASAN-LINUX-CXX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
// CHECK-ASAN-LINUX-CXX-NOT: "-lc"
-// CHECK-ASAN-LINUX-CXX: "-whole-archive" "{{.*}}libclang_rt.asan_cxx-i386.a" "-no-whole-archive"
// CHECK-ASAN-LINUX-CXX: "-whole-archive" "{{.*}}libclang_rt.asan-i386.a" "-no-whole-archive"
+// CHECK-ASAN-LINUX-CXX: "-whole-archive" "{{.*}}libclang_rt.asan_cxx-i386.a" "-no-whole-archive"
+// CHECK-ASAN-LINUX-CXX-NOT: "--dynamic-list"
+// CHECK-ASAN-LINUX-CXX: "-export-dynamic"
+// CHECK-ASAN-LINUX-CXX: stdc++
// CHECK-ASAN-LINUX-CXX: "-lpthread"
// CHECK-ASAN-LINUX-CXX: "-lrt"
// CHECK-ASAN-LINUX-CXX: "-ldl"
-// CHECK-ASAN-LINUX-CXX: "-export-dynamic"
-// CHECK-ASAN-LINUX-CXX-NOT: "--dynamic-list"
-// CHECK-ASAN-LINUX-CXX: stdc++
// RUN: %clang -no-canonical-prefixes %s -### -o /dev/null -fsanitize=address \
// RUN: -target i386-unknown-linux --sysroot=%S/Inputs/basic_linux_tree \
//
// CHECK-ASAN-ANDROID: "{{(.*[^.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
// CHECK-ASAN-ANDROID-NOT: "-lc"
-// CHECK-ASAN-ANDROID: libclang_rt.asan-arm-android.so"
-// CHECK-ASAN-ANDROID-NOT: "-lpthread"
// CHECK-ASAN-ANDROID: "-pie"
// CHECK-ASAN-ANDROID-NOT: "-lpthread"
+// CHECK-ASAN-ANDROID: libclang_rt.asan-arm-android.so"
+// CHECK-ASAN-ANDROID-NOT: "-lpthread"
//
// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
// RUN: -target arm-linux-androideabi -fsanitize=address \
// CHECK-TSAN-LINUX-CXX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
// CHECK-TSAN-LINUX-CXX-NOT: stdc++
// CHECK-TSAN-LINUX-CXX: "-whole-archive" "{{.*}}libclang_rt.tsan-x86_64.a" "-no-whole-archive"
-// CHECK-TSAN-LINUX-CXX: "-lpthread"
-// CHECK-TSAN-LINUX-CXX: "-lrt"
-// CHECK-TSAN-LINUX-CXX: "-ldl"
// CHECK-TSAN-LINUX-CXX-NOT: "-export-dynamic"
// CHECK-TSAN-LINUX-CXX: "--dynamic-list={{.*}}libclang_rt.tsan-x86_64.a.syms"
+// CHECK-TSAN-LINUX-CXX-NOT: "-export-dynamic"
// CHECK-TSAN-LINUX-CXX: stdc++
+// CHECK-TSAN-LINUX-CXX: "-lpthread"
+// CHECK-TSAN-LINUX-CXX: "-lrt"
+// CHECK-TSAN-LINUX-CXX: "-ldl"
// RUN: %clangxx -no-canonical-prefixes %s -### -o %t.o 2>&1 \
// RUN: -target x86_64-unknown-linux -lstdc++ -fsanitize=memory \
// CHECK-MSAN-LINUX-CXX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}"
// CHECK-MSAN-LINUX-CXX-NOT: stdc++
// CHECK-MSAN-LINUX-CXX: "-whole-archive" "{{.*}}libclang_rt.msan-x86_64.a" "-no-whole-archive"
-// CHECK-MSAN-LINUX-CXX: "-lpthread"
-// CHECK-MSAN-LINUX-CXX: "-lrt"
-// CHECK-MSAN-LINUX-CXX: "-ldl"
// CHECK-MSAN-LINUX-CXX-NOT: "-export-dynamic"
// CHECK-MSAN-LINUX-CXX: "--dynamic-list={{.*}}libclang_rt.msan-x86_64.a.syms"
+// CHECK-MSAN-LINUX-CXX-NOT: "-export-dynamic"
// CHECK-MSAN-LINUX-CXX: stdc++
+// CHECK-MSAN-LINUX-CXX: "-lpthread"
+// CHECK-MSAN-LINUX-CXX: "-lrt"
+// CHECK-MSAN-LINUX-CXX: "-ldl"
// RUN: %clang -fsanitize=undefined %s -### -o %t.o 2>&1 \
// RUN: -target i386-unknown-linux \
// CHECK-UBSAN-LINUX: "{{.*}}ld{{(.exe)?}}"
// 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: "-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.san-i386.a" "-no-whole-archive"
+// 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-NOT: "-lstdc++"
+// CHECK-UBSAN-LINUX: "-lpthread"
// RUN: %clang -fsanitize=undefined -fsanitize-link-c++-runtime %s -### -o %t.o 2>&1 \
// RUN: -target i386-unknown-linux \
// 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.ubsan_cxx-i386.a" "-no-whole-archive"
-// CHECK-UBSAN-LINUX-CXX: "--dynamic-list={{.*}}libclang_rt.ubsan_cxx-i386.a.syms"
+// 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: "-lpthread"
+// CHECK-UBSAN-LINUX-CXX-NOT: libclang_rt.asan
// 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: "-whole-archive" "{{.*}}libclang_rt.ubsan_cxx-i386.a" "-no-whole-archive"
+// CHECK-UBSAN-LINUX-CXX-NOT: libclang_rt.asan
+// 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: "-lstdc++"
+// CHECK-UBSAN-LINUX-CXX-NOT: libclang_rt.asan
+// CHECK-UBSAN-LINUX-CXX: "-lpthread"
// RUN: %clang -fsanitize=address,undefined %s -### -o %t.o 2>&1 \
// RUN: -target i386-unknown-linux \
// 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++"
+// CHECK-ASAN-UBSAN-LINUX: "-lpthread"
// RUN: %clangxx -fsanitize=address,undefined %s -### -o %t.o 2>&1 \
// RUN: -target i386-unknown-linux \
// 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_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: "-whole-archive" "{{.*}}libclang_rt.ubsan_cxx-i386.a" "-no-whole-archive"
// CHECK-ASAN-UBSAN-LINUX-CXX: "-lstdc++"
+// CHECK-ASAN-UBSAN-LINUX-CXX: "-lpthread"
// RUN: %clang -fsanitize=undefined %s -### -o %t.o 2>&1 \
// RUN: -target i386-unknown-linux \
// CHECK-LSAN-UBSAN-LINUX-NOT: libclang_rt.san
// CHECK-LSAN-UBSAN-LINUX: "-whole-archive" "{{.*}}libclang_rt.ubsan-x86_64.a" "-no-whole-archive"
// CHECK-LSAN-UBSAN-LINUX-NOT: libclang_rt.ubsan_cxx
-// CHECK-LSAN-UBSAN-LINUX: "-lpthread"
// CHECK-LSAN-UBSAN-LINUX-NOT: "-lstdc++"
+// CHECK-LSAN-UBSAN-LINUX: "-lpthread"
// RUN: %clang -fsanitize=leak,address %s -### -o %t.o 2>&1 \
// RUN: -target x86_64-unknown-linux \