From: Alexey Samsonov Date: Mon, 15 Sep 2014 19:58:40 +0000 (+0000) Subject: Major rewrite of linking strategy for sanitizer runtimes on Linux. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=fe43cf05ff6f62ace630d7710f0319f10c7a2a33;p=clang Major rewrite of linking strategy for sanitizer runtimes on Linux. Change 1: we used to add static sanitizer runtimes at the very beginning of the linker invocation, even before crtbegin.o, which is gross and not correct in general. Fix this: now addSanitizerRuntimes() adds all sanitizer-related link flags to the end of the linker invocation being constructed. It means, that we should call this function in the correct place, namely, before AddLinkerInputs() to make sure sanitizer versions of library functions will be preferred. Change 2: Put system libraries sanitizer libraries depend on at the end of the linker invocation, where all the rest system libraries are located. Respect --nodefaultlibs and --nostdlib flags. This is another way to fix PR15823. Original fix landed in r215940 put "-lpthread" and friends immediately after static ASan runtime, before the user linker inputs. This caused significant slowdown in dynamic linker for large binaries linked against thousands of shared objects. Instead, to mark system libraries as DT_NEEDED we prepend them with "--no-as-needed" flag, discarding the "-Wl,--as-needed" flag that could be provided by the user. Otherwise, this change is a code cleanup. Instead of having a special method for each sanitizer, we introduce a function collectSanitizerRuntimes() that analyzes -fsanitize= flags and returns the set of static and shared libraries that needs to be linked. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@217817 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index 408b2a895d..0262764591 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -2153,155 +2153,114 @@ static SmallString<128> getSanitizerRTLibName(const ToolChain &TC, 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 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 &SharedRuntimes, + SmallVectorImpl &StaticRuntimes, + SmallVectorImpl &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 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, @@ -6641,6 +6600,7 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, 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) && @@ -6652,6 +6612,8 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, 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)) @@ -6706,8 +6668,6 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o"))); } - addSanitizerRuntimes(getToolChain(), Args, CmdArgs); - addProfileRT(ToolChain, Args, CmdArgs); const char *Exec = @@ -7465,9 +7425,8 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA, 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); @@ -7489,6 +7448,9 @@ void gnutools::Link::ConstructJob(Compilation &C, const JobAction &JA, 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; diff --git a/test/Driver/sanitizer-ld.c b/test/Driver/sanitizer-ld.c index 247a925c6a..dc8e93e50f 100644 --- a/test/Driver/sanitizer-ld.c +++ b/test/Driver/sanitizer-ld.c @@ -9,11 +9,12 @@ // 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 \ @@ -24,8 +25,8 @@ // 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" @@ -60,10 +61,10 @@ // 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 \ @@ -82,14 +83,14 @@ // // 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 \ @@ -126,10 +127,10 @@ // // 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 \ @@ -159,12 +160,13 @@ // 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 \ @@ -175,12 +177,13 @@ // 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 \ @@ -189,16 +192,14 @@ // 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 \ @@ -215,16 +216,19 @@ // 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 \ @@ -236,8 +240,8 @@ // 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 \ @@ -247,10 +251,10 @@ // 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 \ @@ -286,8 +290,8 @@ // 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 \