From: Alexey Samsonov Date: Wed, 27 Feb 2013 11:14:55 +0000 (+0000) Subject: [Sanitizer] Change driver behavior when linking with -fsanitize=thread and -fsanitize... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8614304c0d728d43ef16691708281273101b00af;p=clang [Sanitizer] Change driver behavior when linking with -fsanitize=thread and -fsanitize=memory. TSan/MSan also provide their versions of new/delete and should use the same strategy as ASan. Share the code that sets linker flags for all sanitizers. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@176178 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index ce005d05af..c24878d70f 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -1568,6 +1568,35 @@ SanitizerArgs::SanitizerArgs(const Driver &D, const ArgList &Args) /* Default */false); } +static void addSanitizerRTLinkFlagsLinux( + const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs, + const StringRef Sanitizer, bool BeforeLibStdCXX) { + // Sanitizer runtime is located in the Linux library directory and + // has name "libclang_rt.-.a". + SmallString<128> LibSanitizer(TC.getDriver().ResourceDir); + 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 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)); + } + CmdArgs.push_back("-lpthread"); + CmdArgs.push_back("-ldl"); + CmdArgs.push_back("-export-dynamic"); +} + /// 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 addAsanRTLinux(const ToolChain &TC, const ArgList &Args, @@ -1592,26 +1621,7 @@ static void addAsanRTLinux(const ToolChain &TC, const ArgList &Args, TC.getDriver().Diag(diag::err_drv_argument_only_allowed_with) << "-fsanitize-address-zero-base-shadow" << "-pie"; } - // LibAsan is "libclang_rt.asan-.a" in the Linux library - // resource directory. - SmallString<128> LibAsan(TC.getDriver().ResourceDir); - llvm::sys::path::append(LibAsan, "lib", "linux", - (Twine("libclang_rt.asan-") + - TC.getArchName() + ".a")); - // The ASan runtime needs to come before -lstdc++ (or -lc++, libstdc++.a, - // etc.) so that the linker picks ASan's 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 PrefixArgs; - PrefixArgs.push_back("-whole-archive"); - PrefixArgs.push_back(Args.MakeArgString(LibAsan)); - PrefixArgs.push_back("-no-whole-archive"); - CmdArgs.insert(CmdArgs.begin(), PrefixArgs.begin(), PrefixArgs.end()); - CmdArgs.push_back("-lpthread"); - CmdArgs.push_back("-ldl"); - CmdArgs.push_back("-export-dynamic"); + addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "asan", true); } } } @@ -1624,16 +1634,7 @@ static void addTsanRTLinux(const ToolChain &TC, const ArgList &Args, if (!Args.hasArg(options::OPT_pie)) TC.getDriver().Diag(diag::err_drv_argument_only_allowed_with) << "-fsanitize=thread" << "-pie"; - // LibTsan is "libclang_rt.tsan-.a" in the Linux library - // resource directory. - SmallString<128> LibTsan(TC.getDriver().ResourceDir); - llvm::sys::path::append(LibTsan, "lib", "linux", - (Twine("libclang_rt.tsan-") + - TC.getArchName() + ".a")); - CmdArgs.push_back(Args.MakeArgString(LibTsan)); - CmdArgs.push_back("-lpthread"); - CmdArgs.push_back("-ldl"); - CmdArgs.push_back("-export-dynamic"); + addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "tsan", true); } } @@ -1645,16 +1646,7 @@ static void addMsanRTLinux(const ToolChain &TC, const ArgList &Args, if (!Args.hasArg(options::OPT_pie)) TC.getDriver().Diag(diag::err_drv_argument_only_allowed_with) << "-fsanitize=memory" << "-pie"; - // LibMsan is "libclang_rt.msan-.a" in the Linux library - // resource directory. - SmallString<128> LibMsan(TC.getDriver().ResourceDir); - llvm::sys::path::append(LibMsan, "lib", "linux", - (Twine("libclang_rt.msan-") + - TC.getArchName() + ".a")); - CmdArgs.push_back(Args.MakeArgString(LibMsan)); - CmdArgs.push_back("-lpthread"); - CmdArgs.push_back("-ldl"); - CmdArgs.push_back("-export-dynamic"); + addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "msan", true); } } @@ -1662,15 +1654,7 @@ static void addMsanRTLinux(const ToolChain &TC, const ArgList &Args, /// (Linux). static void addUbsanRTLinux(const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs) { - // LibUbsan is "libclang_rt.ubsan-.a" in the Linux library - // resource directory. - SmallString<128> LibUbsan(TC.getDriver().ResourceDir); - llvm::sys::path::append(LibUbsan, "lib", "linux", - (Twine("libclang_rt.ubsan-") + - TC.getArchName() + ".a")); - CmdArgs.push_back(Args.MakeArgString(LibUbsan)); - CmdArgs.push_back("-lpthread"); - CmdArgs.push_back("-export-dynamic"); + addSanitizerRTLinkFlagsLinux(TC, Args, CmdArgs, "ubsan", false); } static bool shouldUseFramePointer(const ArgList &Args, diff --git a/test/Driver/asan-ld.c b/test/Driver/asan-ld.c deleted file mode 100644 index 01b62a62a0..0000000000 --- a/test/Driver/asan-ld.c +++ /dev/null @@ -1,57 +0,0 @@ -// Test AddressSanitizer ld flags. - -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -// RUN: -target i386-unknown-linux -fsanitize=address \ -// RUN: --sysroot=%S/Inputs/basic_linux_tree \ -// RUN: | FileCheck --check-prefix=CHECK-LINUX %s -// -// CHECK-LINUX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}" -// CHECK-LINUX-NOT: "-lc" -// CHECK-LINUX: libclang_rt.asan-i386.a" -// CHECK-LINUX: "-lpthread" -// CHECK-LINUX: "-ldl" -// CHECK-LINUX: "-export-dynamic" - -// RUN: %clangxx -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -// RUN: -target i386-unknown-linux -fsanitize=address \ -// RUN: --sysroot=%S/Inputs/basic_linux_tree \ -// RUN: | FileCheck --check-prefix=CHECK-LINUX-CXX %s -// -// CHECK-LINUX-CXX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}" -// CHECK-LINUX-CXX-NOT: "-lc" -// CHECK-LINUX-CXX: "-whole-archive" "{{.*}}libclang_rt.asan-i386.a" "-no-whole-archive" -// CHECK-LINUX-CXX: "-lpthread" -// CHECK-LINUX-CXX: "-ldl" -// CHECK-LINUX-CXX: "-export-dynamic" -// CHECK-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 \ -// RUN: -lstdc++ -static 2>&1 \ -// RUN: | FileCheck --check-prefix=CHECK-LINUX-CXX-STATIC %s -// -// CHECK-LINUX-CXX-STATIC: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}" -// CHECK-LINUX-CXX-STATIC-NOT: stdc++ -// CHECK-LINUX-CXX-STATIC: "-whole-archive" "{{.*}}libclang_rt.asan-i386.a" "-no-whole-archive" -// CHECK-LINUX-CXX-STATIC: stdc++ - -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -// RUN: -target arm-linux-androideabi -fsanitize=address \ -// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ -// RUN: | FileCheck --check-prefix=CHECK-ANDROID %s -// -// CHECK-ANDROID: "{{(.*[^.0-9A-Z_a-z])?}}ld{{(.exe)?}}" -// CHECK-ANDROID-NOT: "-lc" -// CHECK-ANDROID: libclang_rt.asan-arm-android.so" -// CHECK-ANDROID-NOT: "-lpthread" -// -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -// RUN: -target arm-linux-androideabi -fsanitize=address \ -// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ -// RUN: -shared \ -// RUN: | FileCheck --check-prefix=CHECK-ANDROID-SHARED %s -// -// CHECK-ANDROID-SHARED: "{{(.*[^.0-9A-Z_a-z])?}}ld{{(.exe)?}}" -// CHECK-ANDROID-SHARED-NOT: "-lc" -// CHECK-ANDROID-SHARED: libclang_rt.asan-arm-android.so" -// CHECK-ANDROID-SHARED-NOT: "-lpthread" diff --git a/test/Driver/sanitizer-ld.c b/test/Driver/sanitizer-ld.c new file mode 100644 index 0000000000..9bb2eab29a --- /dev/null +++ b/test/Driver/sanitizer-ld.c @@ -0,0 +1,102 @@ +// Test sanitizers ld flags. + +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target i386-unknown-linux -fsanitize=address \ +// RUN: --sysroot=%S/Inputs/basic_linux_tree \ +// RUN: | FileCheck --check-prefix=CHECK-ASAN-LINUX %s +// +// 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: "-lpthread" +// CHECK-ASAN-LINUX: "-ldl" +// CHECK-ASAN-LINUX: "-export-dynamic" + +// RUN: %clangxx -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target i386-unknown-linux -fsanitize=address \ +// RUN: --sysroot=%S/Inputs/basic_linux_tree \ +// RUN: | FileCheck --check-prefix=CHECK-ASAN-LINUX-CXX %s +// +// 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-i386.a" "-no-whole-archive" +// CHECK-ASAN-LINUX-CXX: "-lpthread" +// CHECK-ASAN-LINUX-CXX: "-ldl" +// CHECK-ASAN-LINUX-CXX: "-export-dynamic" +// 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 \ +// RUN: -lstdc++ -static 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-ASAN-LINUX-CXX-STATIC %s +// +// CHECK-ASAN-LINUX-CXX-STATIC: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}" +// CHECK-ASAN-LINUX-CXX-STATIC-NOT: stdc++ +// CHECK-ASAN-LINUX-CXX-STATIC: "-whole-archive" "{{.*}}libclang_rt.asan-i386.a" "-no-whole-archive" +// CHECK-ASAN-LINUX-CXX-STATIC: stdc++ + +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target arm-linux-androideabi -fsanitize=address \ +// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ +// RUN: | FileCheck --check-prefix=CHECK-ASAN-ANDROID %s +// +// 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" +// +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target arm-linux-androideabi -fsanitize=address \ +// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ +// RUN: -shared \ +// RUN: | FileCheck --check-prefix=CHECK-ASAN-ANDROID-SHARED %s +// +// CHECK-ASAN-ANDROID-SHARED: "{{(.*[^.0-9A-Z_a-z])?}}ld{{(.exe)?}}" +// CHECK-ASAN-ANDROID-SHARED-NOT: "-lc" +// CHECK-ASAN-ANDROID-SHARED: libclang_rt.asan-arm-android.so" +// CHECK-ASAN-ANDROID-SHARED-NOT: "-lpthread" + +// RUN: %clangxx -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target x86_64-unknown-linux -lstdc++ -fsanitize=thread \ +// RUN: --sysroot=%S/Inputs/basic_linux_tree \ +// RUN: | FileCheck --check-prefix=CHECK-TSAN-LINUX-CXX %s +// +// 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: "-ldl" +// CHECK-TSAN-LINUX-CXX: "-export-dynamic" +// CHECK-TSAN-LINUX-CXX: stdc++ + +// RUN: %clangxx -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target x86_64-unknown-linux -lstdc++ -fsanitize=memory \ +// RUN: --sysroot=%S/Inputs/basic_linux_tree \ +// RUN: | FileCheck --check-prefix=CHECK-MSAN-LINUX-CXX %s +// +// 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: "-ldl" +// CHECK-MSAN-LINUX-CXX: "-export-dynamic" +// CHECK-MSAN-LINUX-CXX: stdc++ + +// RUN: %clang -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 %s +// CHECK-UBSAN-LINUX: "{{.*}}ld{{(.exe)?}}" +// CHECK-UBSAN-LINUX-NOT: "-lc" +// CHECK-UBSAN-LINUX: libclang_rt.ubsan-i386.a" +// CHECK-UBSAN-LINUX: "-lpthread" + +// RUN: %clang -fsanitize=undefined %s -### -o %t.o 2>&1 \ +// RUN: -target i386-unknown-linux \ +// RUN: --sysroot=%S/Inputs/basic_linux_tree \ +// 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" diff --git a/test/Driver/ubsan-ld.c b/test/Driver/ubsan-ld.c deleted file mode 100644 index 7f601ab316..0000000000 --- a/test/Driver/ubsan-ld.c +++ /dev/null @@ -1,20 +0,0 @@ -// Test UndefinedBehaviorSanitizer ld flags. - -// RUN: %clang -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-LINUX %s -// CHECK-LINUX: "{{.*}}ld{{(.exe)?}}" -// CHECK-LINUX-NOT: "-lc" -// CHECK-LINUX: libclang_rt.ubsan-i386.a" -// CHECK-LINUX: "-lpthread" - -// RUN: %clang -fsanitize=undefined %s -### -o %t.o 2>&1 \ -// RUN: -target i386-unknown-linux \ -// RUN: --sysroot=%S/Inputs/basic_linux_tree \ -// RUN: -shared \ -// RUN: | FileCheck --check-prefix=CHECK-LINUX-SHARED %s -// CHECK-LINUX-SHARED: "{{.*}}ld{{(.exe)?}}" -// CHECK-LINUX-SHARED-NOT: "-lc" -// CHECK-LINUX-SHARED: libclang_rt.ubsan-i386.a" -// CHECK-LINUX-SHARED: "-lpthread"