[TSan] Build TSan-instrumented version of libcxx and use it in lit tests.

TSan can produce false positives in code that uses C++11 threading,
as it doesn't see synchronization inside standard library. See
http://lists.cs.uiuc.edu/pipermail/cfe-dev/2014-February/035408.html
for an example of such case.

We may build custom TSan-instrumented version libcxx to fight with that.
This change adds build rules for libcxx_tsan and integrates it into
testing infrastructure.

llvm-svn: 208737
This commit is contained in:
Alexey Samsonov 2014-05-13 22:30:16 +00:00
parent 060ca7596c
commit 5716928ae2
7 changed files with 69 additions and 4 deletions

View File

@ -75,6 +75,7 @@ set(TSAN_HEADERS
rtl/tsan_update_shadow_word_inl.h
rtl/tsan_vector.h)
set(TSAN_RUNTIME_LIBRARIES)
add_custom_target(tsan)
# TSan is currently supported on 64-bit Linux only.
if(CAN_TARGET_x86_64 AND UNIX AND NOT APPLE)
@ -90,6 +91,7 @@ if(CAN_TARGET_x86_64 AND UNIX AND NOT APPLE)
$<TARGET_OBJECTS:RTSanitizerCommonLibc.${arch}>
CFLAGS ${TSAN_RTL_CFLAGS}
DEFS ${TSAN_COMMON_DEFINITIONS})
list(APPEND TSAN_RUNTIME_LIBRARIES clang_rt.tsan-${arch})
add_sanitizer_rt_symbols(clang_rt.tsan-${arch} rtl/tsan.syms.extra)
add_dependencies(tsan clang_rt.tsan-${arch}
clang_rt.tsan-${arch}-symbols)
@ -97,6 +99,14 @@ endif()
add_dependencies(compiler-rt tsan)
# Build libcxx instrumented with TSan.
if(COMPILER_RT_HAS_LIBCXX_SOURCES)
set(LIBCXX_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/libcxx_tsan)
add_custom_libcxx(libcxx_tsan ${LIBCXX_PREFIX}
DEPS ${TSAN_RUNTIME_LIBRARIES}
CFLAGS -fsanitize=thread)
endif()
if(COMPILER_RT_INCLUDE_TESTS)
add_subdirectory(tests)
endif()

View File

@ -16,6 +16,7 @@ set_default("llvm_build_mode", "@LLVM_BUILD_MODE@")
set_default("llvm_src_root", "@LLVM_SOURCE_DIR@")
set_default("llvm_obj_root", "@LLVM_BINARY_DIR@")
set_default("compiler_rt_src_root", "@COMPILER_RT_SOURCE_DIR@")
set_default("compiler_rt_obj_root", "@COMPILER_RT_BINARY_DIR@")
set_default("llvm_tools_dir", "@LLVM_TOOLS_DIR@")
set_default("clang", "@COMPILER_RT_TEST_COMPILER@")
set_default("compiler_id", "@COMPILER_RT_TEST_COMPILER_ID@")

View File

@ -1,11 +1,17 @@
configure_lit_site_cfg(
${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg)
set(TSAN_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS})
if(NOT COMPILER_RT_STANDALONE_BUILD)
list(APPEND TSAN_TEST_DEPS tsan)
endif()
if(COMPILER_RT_HAS_LIBCXX_SOURCES)
list(APPEND TSAN_TEST_DEPS libcxx_tsan)
set(TSAN_HAS_LIBCXX True)
else()
set(TSAN_HAS_LIBCXX False)
endif()
configure_lit_site_cfg(
${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg)
if(COMPILER_RT_INCLUDE_TESTS)
configure_lit_site_cfg(

View File

@ -0,0 +1,10 @@
def getRoot(config):
if not config.parent:
return config
return getRoot(config.parent)
root = getRoot(config)
if not root.has_libcxx:
config.unsupported = True

View File

@ -0,0 +1,24 @@
// RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
#include <stdio.h>
#include <memory>
#include <thread>
int main() {
int v1 = 0;
int v2 = 0;
std::thread t1;
std::thread t2;
{
auto thingy = std::make_shared<int>(42);
t1 = std::thread([thingy, &v1] { v1 = *thingy; });
t2 = std::thread([thingy, &v2] { v2 = *thingy; });
}
t1.join();
t2.join();
printf("%d %d\n", v1, v2);
// CHECK-NOT: ThreadSanitizer: data race
// CHECK: 42 42
return 0;
}

View File

@ -31,6 +31,18 @@ clang_tsan_cflags = ["-fsanitize=thread",
"-ldl",
"-m64"]
clang_tsan_cxxflags = config.cxx_mode_flags + clang_tsan_cflags
# Add additional flags if we're using instrumented libc++.
if config.has_libcxx:
# FIXME: Dehardcode this path somehow.
libcxx_path = os.path.join(config.compiler_rt_obj_root, "lib",
"tsan", "libcxx_tsan")
libcxx_incdir = os.path.join(libcxx_path, "include", "c++", "v1")
libcxx_libdir = os.path.join(libcxx_path, "lib")
libcxx_so = os.path.join(libcxx_libdir, "libc++.so")
clang_tsan_cxxflags += ["-std=c++11",
"-I%s" % libcxx_incdir,
libcxx_so,
"-Wl,-rpath=%s" % libcxx_libdir]
def build_invocation(compile_flags):
return " " + " ".join([config.clang] + compile_flags) + " "

View File

@ -1,6 +1,8 @@
## Autogenerated by LLVM/Clang configuration.
# Do not edit!
config.has_libcxx = @TSAN_HAS_LIBCXX@
# Load common config for all compiler-rt lit tests.
lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured")