From 9f5847984a6b837659968320e6d624a2ff94f609 Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Fri, 1 Dec 2017 08:38:25 +0000 Subject: [ubsan] lit changes for lld testing, future lto testing. Summary: As discussed in https://github.com/google/oss-fuzz/issues/933, it would be really awesome to be able to use ThinLTO for fuzzing. However, as @kcc has pointed out, it is currently undefined (untested) whether the sanitizers actually function properly with LLD and/or LTO. This patch is inspired by the cfi test, which already do test with LTO (and/or LLD), since LTO is required for CFI to function. I started with UBSan, because it's cmakelists / lit.* files appeared to be the cleanest. This patch adds the infrastructure to easily add LLD and/or LTO sub-variants of the existing lit test configurations. Also, this patch adds the LLD flavor, that explicitly does use LLD to link. The check-ubsan does pass on my machine. And to minimize the [initial] potential buildbot breakage i have put some restrictions on this flavour. Please review carefully, i have not worked with lit/sanitizer tests before. Reviewers: eugenis, vitalybuka Reviewed By: eugenis Subscribers: #sanitizers, pcc, kubamracek, mgorny, llvm-commits, mehdi_amini, inglorion, kcc Differential Revision: https://reviews.llvm.org/D39508 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@319525 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/asan/lit.cfg | 2 +- test/cfi/lit.cfg | 9 ++++++--- test/cfi/lit.site.cfg.in | 1 + test/lit.common.cfg | 19 +++++++++++++++++++ test/lit.common.configured.in | 1 + test/sanitizer_common/lit.common.cfg | 2 +- test/scudo/lit.cfg | 2 +- test/tsan/lit.cfg | 2 +- test/ubsan/CMakeLists.txt | 33 ++++++++++++++++++++++++++------- test/ubsan/lit.common.cfg | 10 ++++------ test/ubsan/lit.site.cfg.in | 3 +++ test/ubsan_minimal/lit.common.cfg | 2 +- 12 files changed, 65 insertions(+), 21 deletions(-) (limited to 'test') diff --git a/test/asan/lit.cfg b/test/asan/lit.cfg index 6a4044a44..4a08a7b47 100644 --- a/test/asan/lit.cfg +++ b/test/asan/lit.cfg @@ -96,7 +96,7 @@ if platform.system() == 'Windows': config.available_features.add(win_runtime_feature) def build_invocation(compile_flags): - return " " + " ".join([config.compile_wrapper, config.clang] + compile_flags) + " " + return " " + " ".join([config.clang] + compile_flags) + " " config.substitutions.append( ("%clang ", build_invocation(target_cflags)) ) config.substitutions.append( ("%clangxx ", build_invocation(target_cxxflags)) ) diff --git a/test/cfi/lit.cfg b/test/cfi/lit.cfg index 7dae9a0d5..cbffe6ea8 100644 --- a/test/cfi/lit.cfg +++ b/test/cfi/lit.cfg @@ -5,13 +5,16 @@ config.name = 'cfi' + config.name_suffix config.suffixes = ['.c', '.cpp', '.test'] config.test_source_root = os.path.dirname(__file__) -clang = ' '.join([config.compile_wrapper, config.clang, config.target_cflags]) -clangxx = ' '.join([config.compile_wrapper, config.clang, config.target_cflags] + config.cxx_mode_flags) +def build_invocation(compile_flags): + return " " + " ".join([config.clang] + compile_flags) + " " + +clang = build_invocation([config.target_cflags]) +clangxx = build_invocation([config.target_cflags] + config.cxx_mode_flags) config.substitutions.append((r"%clang ", clang + ' ')) config.substitutions.append((r"%clangxx ", clangxx + ' ')) if config.lto_supported: - clang_cfi = ' '.join(config.lto_launch + [clang] + config.lto_flags + ['-fsanitize=cfi ']) + clang_cfi = clang + '-fsanitize=cfi ' if config.cfi_lit_test_mode == "Devirt": config.available_features.add('devirt') diff --git a/test/cfi/lit.site.cfg.in b/test/cfi/lit.site.cfg.in index 066c915ef..eb9b44137 100644 --- a/test/cfi/lit.site.cfg.in +++ b/test/cfi/lit.site.cfg.in @@ -5,6 +5,7 @@ config.cfi_lit_test_mode = "@CFI_LIT_TEST_MODE@" config.target_arch = "@CFI_TEST_TARGET_ARCH@" config.target_cflags = "@CFI_TEST_TARGET_CFLAGS@" config.use_lld = @CFI_TEST_USE_LLD@ +config.use_lto = True # CFI *requires* LTO. config.use_thinlto = @CFI_TEST_USE_THINLTO@ lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured") diff --git a/test/lit.common.cfg b/test/lit.common.cfg index 56d4fef4e..0840f65a7 100644 --- a/test/lit.common.cfg +++ b/test/lit.common.cfg @@ -324,3 +324,22 @@ if config.asan_shadow_scale: config.available_features.add("shadow-scale-%s" % config.asan_shadow_scale) else: config.available_features.add("shadow-scale-3") + +# Propagate the LLD/LTO into the clang config option, so nothing else is needed. +run_wrapper = [] +target_cflags = [getattr(config, 'target_cflags', None)] +extra_cflags = [] + +if config.use_lto and config.lto_supported: + run_wrapper += config.lto_launch + extra_cflags += config.lto_flags +elif config.use_lto and (not config.lto_supported): + config.unsupported = True + +if config.use_lld and config.has_lld and not config.use_lto: + extra_cflags += ["-fuse-ld=lld"] +elif config.use_lld and (not config.has_lld): + config.unsupported = True + +config.clang = " " + " ".join(run_wrapper + [config.compile_wrapper, config.clang]) + " " +config.target_cflags = " " + " ".join(target_cflags + extra_cflags) + " " diff --git a/test/lit.common.configured.in b/test/lit.common.configured.in index e2da4cc9b..32a88200b 100644 --- a/test/lit.common.configured.in +++ b/test/lit.common.configured.in @@ -33,6 +33,7 @@ set_default("has_lld", @COMPILER_RT_HAS_LLD_PYBOOL@) set_default("can_symbolize", @CAN_SYMBOLIZE@) set_default("use_lld", False) set_default("use_thinlto", False) +set_default("use_lto", config.use_thinlto) set_default("android", @ANDROID_PYBOOL@) config.available_features.add('target-is-%s' % config.target_arch) diff --git a/test/sanitizer_common/lit.common.cfg b/test/sanitizer_common/lit.common.cfg index a4a5d4e85..c7a1682f7 100644 --- a/test/sanitizer_common/lit.common.cfg +++ b/test/sanitizer_common/lit.common.cfg @@ -48,7 +48,7 @@ clang_cflags = config.debug_info_flags + tool_cflags + [config.target_cflags] clang_cxxflags = config.cxx_mode_flags + clang_cflags def build_invocation(compile_flags): - return " " + " ".join([config.compile_wrapper, config.clang] + compile_flags) + " " + return " " + " ".join([config.clang] + compile_flags) + " " config.substitutions.append( ("%clang ", build_invocation(clang_cflags)) ) config.substitutions.append( ("%clangxx ", build_invocation(clang_cxxflags)) ) diff --git a/test/scudo/lit.cfg b/test/scudo/lit.cfg index 2f6469d25..028bf721b 100644 --- a/test/scudo/lit.cfg +++ b/test/scudo/lit.cfg @@ -36,7 +36,7 @@ if not config.android: cxx_flags = (c_flags + config.cxx_mode_flags + ["-std=c++11"]) def build_invocation(compile_flags): - return " " + " ".join([config.compile_wrapper, config.clang] + compile_flags) + " " + return " " + " ".join([config.clang] + compile_flags) + " " # Add clang substitutions. config.substitutions.append(("%clang ", build_invocation(c_flags))) diff --git a/test/tsan/lit.cfg b/test/tsan/lit.cfg index f0dc7b67e..fdbafefbc 100644 --- a/test/tsan/lit.cfg +++ b/test/tsan/lit.cfg @@ -66,7 +66,7 @@ if config.has_libcxx and config.host_os != 'Darwin': "-Wl,-rpath=%s" % libcxx_libdir] def build_invocation(compile_flags): - return " " + " ".join([config.compile_wrapper, config.clang] + compile_flags) + " " + return " " + " ".join([config.clang] + compile_flags) + " " config.substitutions.append( ("%clang_tsan ", build_invocation(clang_tsan_cflags)) ) config.substitutions.append( ("%clangxx_tsan ", build_invocation(clang_tsan_cxxflags)) ) diff --git a/test/ubsan/CMakeLists.txt b/test/ubsan/CMakeLists.txt index 5843e0cb8..779168147 100644 --- a/test/ubsan/CMakeLists.txt +++ b/test/ubsan/CMakeLists.txt @@ -3,9 +3,20 @@ set(UBSAN_LIT_TESTS_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(UBSAN_TESTSUITES) set(UBSAN_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS}) -macro(add_ubsan_testsuite test_mode sanitizer arch) +macro(add_ubsan_testsuite test_mode sanitizer arch lld thinlto) set(UBSAN_LIT_TEST_MODE "${test_mode}") - set(CONFIG_NAME ${UBSAN_LIT_TEST_MODE}-${arch}) + set(CONFIG_NAME ${UBSAN_LIT_TEST_MODE}) + if (${lld}) + set(CONFIG_NAME ${CONFIG_NAME}-lld) + list(APPEND UBSAN_TEST_DEPS lld) + endif() + if (${thinlto}) + set(CONFIG_NAME ${CONFIG_NAME}-thinlto) + list(APPEND UBSAN_TEST_DEPS LTO) + endif() + set(UBSAN_TEST_USE_LLD ${lld}) + set(UBSAN_TEST_USE_THINLTO ${thinlto}) + set(CONFIG_NAME ${CONFIG_NAME}-${arch}) configure_lit_site_cfg( ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg) @@ -15,6 +26,14 @@ macro(add_ubsan_testsuite test_mode sanitizer arch) endif() endmacro() +macro(add_ubsan_testsuites test_mode sanitizer arch) + add_ubsan_testsuite(${test_mode} ${sanitizer} ${arch} False False) + + if(COMPILER_RT_HAS_LLD AND arch STREQUAL "x86_64" AND NOT (APPLE OR WIN32)) + add_ubsan_testsuite(${test_mode} ${sanitizer} ${arch} True False) + endif() +endmacro() + set(UBSAN_TEST_ARCH ${UBSAN_SUPPORTED_ARCH}) if(APPLE) darwin_filter_host_archs(UBSAN_SUPPORTED_ARCH UBSAN_TEST_ARCH) @@ -23,20 +42,20 @@ endif() foreach(arch ${UBSAN_TEST_ARCH}) set(UBSAN_TEST_TARGET_ARCH ${arch}) get_test_cc_for_arch(${arch} UBSAN_TEST_TARGET_CC UBSAN_TEST_TARGET_CFLAGS) - add_ubsan_testsuite("Standalone" ubsan ${arch}) + add_ubsan_testsuites("Standalone" ubsan ${arch}) if(COMPILER_RT_HAS_ASAN AND ";${ASAN_SUPPORTED_ARCH};" MATCHES ";${arch};") # TODO(wwchrome): Re-enable ubsan for asan win 64-bit when ready. # Disable ubsan with AddressSanitizer tests for Windows 64-bit. if(NOT OS_NAME MATCHES "Windows" OR CMAKE_SIZEOF_VOID_P EQUAL 4) - add_ubsan_testsuite("AddressSanitizer" asan ${arch}) + add_ubsan_testsuites("AddressSanitizer" asan ${arch}) endif() endif() if(COMPILER_RT_HAS_MSAN AND ";${MSAN_SUPPORTED_ARCH};" MATCHES ";${arch};") - add_ubsan_testsuite("MemorySanitizer" msan ${arch}) + add_ubsan_testsuites("MemorySanitizer" msan ${arch}) endif() if(COMPILER_RT_HAS_TSAN AND ";${TSAN_SUPPORTED_ARCH};" MATCHES ";${arch};" AND NOT ANDROID) - add_ubsan_testsuite("ThreadSanitizer" tsan ${arch}) + add_ubsan_testsuites("ThreadSanitizer" tsan ${arch}) endif() endforeach() @@ -45,7 +64,7 @@ if(APPLE) set(UBSAN_TEST_TARGET_ARCH ${arch}) get_test_cc_for_arch(${arch} UBSAN_TEST_TARGET_CC UBSAN_TEST_TARGET_CFLAGS) set(UBSAN_TEST_TARGET_CFLAGS "${UBSAN_TEST_TARGET_CFLAGS} -lc++abi") - add_ubsan_testsuite("StandaloneStatic" ubsan ${arch}) + add_ubsan_testsuites("StandaloneStatic" ubsan ${arch}) endforeach() endif() diff --git a/test/ubsan/lit.common.cfg b/test/ubsan/lit.common.cfg index e1bd349af..83475a2dc 100644 --- a/test/ubsan/lit.common.cfg +++ b/test/ubsan/lit.common.cfg @@ -11,6 +11,9 @@ def get_required_attr(config, attr_name): "to lit.site.cfg " % attr_name) return attr_value +# Setup config name. +config.name = 'UBSan-' + config.name_suffix + # Setup source root. config.test_source_root = os.path.dirname(__file__) @@ -18,24 +21,19 @@ default_ubsan_opts = list(config.default_sanitizer_opts) # Choose between standalone and UBSan+ASan modes. ubsan_lit_test_mode = get_required_attr(config, 'ubsan_lit_test_mode') if ubsan_lit_test_mode == "Standalone": - config.name = 'UBSan-Standalone-' + config.target_arch config.available_features.add("ubsan-standalone") clang_ubsan_cflags = [] elif ubsan_lit_test_mode == "StandaloneStatic": - config.name = 'UBSan-StandaloneStatic-' + config.target_arch config.available_features.add("ubsan-standalone-static") clang_ubsan_cflags = ['-static-libsan'] elif ubsan_lit_test_mode == "AddressSanitizer": - config.name = 'UBSan-ASan-' + config.target_arch config.available_features.add("ubsan-asan") clang_ubsan_cflags = ["-fsanitize=address"] default_ubsan_opts += ['detect_leaks=0'] elif ubsan_lit_test_mode == "MemorySanitizer": - config.name = 'UBSan-MSan-' + config.target_arch config.available_features.add("ubsan-msan") clang_ubsan_cflags = ["-fsanitize=memory"] elif ubsan_lit_test_mode == "ThreadSanitizer": - config.name = 'UBSan-TSan-' + config.target_arch config.available_features.add("ubsan-tsan") clang_ubsan_cflags = ["-fsanitize=thread"] else: @@ -55,7 +53,7 @@ config.substitutions.append(('%env_ubsan_opts=', 'env UBSAN_OPTIONS=' + default_ubsan_opts_str)) def build_invocation(compile_flags): - return " " + " ".join([config.compile_wrapper, config.clang] + compile_flags) + " " + return " " + " ".join([config.clang] + compile_flags) + " " target_cflags = [get_required_attr(config, "target_cflags")] clang_ubsan_cflags += target_cflags diff --git a/test/ubsan/lit.site.cfg.in b/test/ubsan/lit.site.cfg.in index d8242163a..a4d7b50ed 100644 --- a/test/ubsan/lit.site.cfg.in +++ b/test/ubsan/lit.site.cfg.in @@ -1,9 +1,12 @@ @LIT_SITE_CFG_IN_HEADER@ # Tool-specific config options. +config.name_suffix = "@CONFIG_NAME@" config.ubsan_lit_test_mode = "@UBSAN_LIT_TEST_MODE@" config.target_cflags = "@UBSAN_TEST_TARGET_CFLAGS@" config.target_arch = "@UBSAN_TEST_TARGET_ARCH@" +config.use_lld = @UBSAN_TEST_USE_LLD@ +config.use_thinlto = @UBSAN_TEST_USE_THINLTO@ # Load common config for all compiler-rt lit tests. lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured") diff --git a/test/ubsan_minimal/lit.common.cfg b/test/ubsan_minimal/lit.common.cfg index 32a1d0b3e..e8b42bb82 100644 --- a/test/ubsan_minimal/lit.common.cfg +++ b/test/ubsan_minimal/lit.common.cfg @@ -16,7 +16,7 @@ config.test_source_root = os.path.dirname(__file__) config.name = 'UBSan-Minimal-' + config.target_arch def build_invocation(compile_flags): - return " " + " ".join([config.compile_wrapper, config.clang] + compile_flags) + " " + return " " + " ".join([config.clang] + compile_flags) + " " target_cflags = [get_required_attr(config, "target_cflags")] clang_ubsan_cflags = ["-fsanitize-minimal-runtime"] + target_cflags -- cgit v1.2.3