[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.

llvm-svn: 176178
This commit is contained in:
Alexey Samsonov 2013-02-27 11:14:55 +00:00
parent 2cf17bfcc1
commit bfb0cd355f
4 changed files with 135 additions and 126 deletions

View File

@ -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.<Sanitizer>-<ArchName>.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<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));
}
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-<ArchName>.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<const char*, 3> 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-<ArchName>.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-<ArchName>.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-<ArchName>.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,

View File

@ -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"

View File

@ -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"

View File

@ -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"