Index: cmake/Modules/AddCompilerRT.cmake =================================================================== --- cmake/Modules/AddCompilerRT.cmake +++ cmake/Modules/AddCompilerRT.cmake @@ -491,6 +491,8 @@ -DCMAKE_INSTALL_PREFIX:PATH= -DLLVM_PATH=${LLVM_MAIN_SRC_DIR} -DLIBCXX_STANDALONE_BUILD=On + -DLIBCXX_ENABLE_EXCEPTIONS=OFF + -DLIBCXX_CXX_ABI=none LOG_BUILD 1 LOG_CONFIGURE 1 LOG_INSTALL 1 Index: lib/fuzzer/CMakeLists.txt =================================================================== --- lib/fuzzer/CMakeLists.txt +++ lib/fuzzer/CMakeLists.txt @@ -33,6 +33,10 @@ set(LIBFUZZER_CFLAGS ${SANITIZER_COMMON_CFLAGS}) +if(COMPILER_RT_LIBCXX_PATH) + list(APPEND LIBFUZZER_CFLAGS -nostdinc++ -D_LIBCPP_ABI_VERSION=__Fuzzer) +endif() + append_list_if(COMPILER_RT_HAS_OMIT_FRAME_POINTER_FLAG -fno-omit-frame-pointer LIBFUZZER_CFLAGS) if (CMAKE_CXX_FLAGS MATCHES "fsanitize-coverage") @@ -75,6 +79,57 @@ CFLAGS ${LIBFUZZER_CFLAGS} PARENT_TARGET fuzzer) +macro(partially_link_lib name dir) + add_custom_command(TARGET ${name} POST_BUILD + COMMAND ${CMAKE_LINKER} --whole-archive "$" --no-whole-archive ${LIBCXX_${arch}_PREFIX}/lib/libc++.a -r -o Fuzzer_main.o + COMMAND ${CMAKE_COMMAND} -E remove "$" + COMMAND ${CMAKE_AR} qcs "$" Fuzzer_main.o + WORKING_DIRECTORY ${dir} + ) +endmacro() + +if(COMPILER_RT_LIBCXX_PATH) + foreach(arch ${FUZZER_SUPPORTED_ARCH}) + get_target_flags_for_arch(${arch} TARGET_CFLAGS) + set(LIBCXX_${arch}_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/libcxx_fuzzer_${arch}) + add_custom_libcxx(libcxx_fuzzer_${arch} ${LIBCXX_${arch}_PREFIX} + CFLAGS ${TARGET_CFLAGS} -D_LIBCPP_ABI_VERSION=__Fuzzer -D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS=1 -fvisibility=hidden) + target_compile_options(RTfuzzer.${arch} PRIVATE + -isystem ${CMAKE_CURRENT_BINARY_DIR}/libcxx_fuzzer_${arch}/include/c++/v1 + ) + add_dependencies(RTfuzzer.${arch} libcxx_fuzzer_${arch}) + target_compile_options(RTfuzzer_main.${arch} PRIVATE + -isystem ${CMAKE_CURRENT_BINARY_DIR}/libcxx_fuzzer_${arch}/include/c++/v1 + ) + add_dependencies(RTfuzzer_main.${arch} libcxx_fuzzer_${arch}) + set(cxx_${arch}_merge_dir "${CMAKE_CURRENT_BINARY_DIR}/cxx_${arch}_merge.dir") + file(MAKE_DIRECTORY ${cxx_${arch}_merge_dir}) + add_custom_command(TARGET clang_rt.fuzzer-${arch} POST_BUILD + COMMAND ${CMAKE_LINKER} --whole-archive "$" --no-whole-archive ${LIBCXX_${arch}_PREFIX}/lib/libc++.a -r -o Fuzzer_main.o + COMMAND ${CMAKE_COMMAND} -E remove "$" + COMMAND ${CMAKE_AR} qcs "$" Fuzzer_main.o + WORKING_DIRECTORY ${cxx_${arch}_merge_dir} + ) + add_custom_command(TARGET clang_rt.fuzzer_no_main-${arch} POST_BUILD + COMMAND ${CMAKE_LINKER} --whole-archive "$" --no-whole-archive ${LIBCXX_${arch}_PREFIX}/lib/libc++.a -r -o Fuzzer.o + COMMAND ${CMAKE_COMMAND} -E remove "$" + COMMAND ${CMAKE_AR} qcs "$" Fuzzer.o + WORKING_DIRECTORY ${cxx_${arch}_merge_dir} + ) + + # TODO: CMake 3.4 doesn't support the use of object libraries from custom + # commands. When LLVM moves to CMake 3.9, we could instead use the command + # below to create the object file directly without relinking the archive. + # + # add_custom_command( + # OUTPUT Fuzzer.o + # COMMAND ld -r $ ${LIBCXX_${arch}_PREFIX}/lib/libc++.a -o Fuzzer.o + # DEPENDS $ + # COMMAND_EXPAND_LISTS + # ) + endforeach() +endif() + if(COMPILER_RT_INCLUDE_TESTS) add_subdirectory(tests) endif() Index: lib/fuzzer/tests/CMakeLists.txt =================================================================== --- lib/fuzzer/tests/CMakeLists.txt +++ lib/fuzzer/tests/CMakeLists.txt @@ -18,6 +18,10 @@ list(APPEND LIBFUZZER_UNITTEST_LINK_FLAGS -lstdc++ -lpthread) endif() +if(COMPILER_RT_LIBCXX_PATH) + list(APPEND LIBFUZZER_UNITTEST_CFLAGS -nostdinc++ -D_LIBCPP_ABI_VERSION=__Fuzzer) +endif() + foreach(arch ${FUZZER_SUPPORTED_ARCH}) set(LIBFUZZER_TEST_RUNTIME RTFuzzerTest.${arch}) if(APPLE) @@ -33,14 +37,22 @@ ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} FOLDER "Compiler-RT Runtime tests") + if(COMPILER_RT_LIBCXX_PATH) + set(LIBFUZZER_TEST_RUNTIME_DEPS libcxx_fuzzer_${arch}) + set(LIBFUZZER_TEST_RUNTIME_CFLAGS + -isystem ${CMAKE_CURRENT_BINARY_DIR}/../libcxx_fuzzer_${arch}/include/c++/v1) + set(LIBFUZZER_TEST_RUNTIME_LINK_FLAGS + ${CMAKE_CURRENT_BINARY_DIR}/../libcxx_fuzzer_${arch}/lib/libc++.a) + endif() + set(FuzzerTestObjects) generate_compiler_rt_tests(FuzzerTestObjects FuzzerUnitTests "Fuzzer-${arch}-Test" ${arch} SOURCES FuzzerUnittest.cpp ${COMPILER_RT_GTEST_SOURCE} RUNTIME ${LIBFUZZER_TEST_RUNTIME} - DEPS gtest - CFLAGS ${LIBFUZZER_UNITTEST_CFLAGS} - LINK_FLAGS ${LIBFUZZER_UNITTEST_LINK_FLAGS}) + DEPS gtest ${LIBFUZZER_TEST_RUNTIME_DEPS} + CFLAGS ${LIBFUZZER_UNITTEST_CFLAGS} ${LIBFUZZER_TEST_RUNTIME_CFLAGS} + LINK_FLAGS ${LIBFUZZER_UNITTEST_LINK_FLAGS} ${LIBFUZZER_TEST_RUNTIME_LINK_FLAGS}) set_target_properties(FuzzerUnitTests PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) endforeach() Index: test/fuzzer/CMakeLists.txt =================================================================== --- test/fuzzer/CMakeLists.txt +++ test/fuzzer/CMakeLists.txt @@ -8,36 +8,44 @@ list(APPEND LIBFUZZER_TEST_DEPS FuzzerUnitTests) endif() -set(LIBFUZZER_TESTSUITES) - +add_custom_target(check-fuzzer) if(COMPILER_RT_INCLUDE_TESTS) # libFuzzer unit tests. configure_lit_site_cfg( ${CMAKE_CURRENT_SOURCE_DIR}/unit/lit.site.cfg.in ${CMAKE_CURRENT_BINARY_DIR}/unit/lit.site.cfg) - list(APPEND LIBFUZZER_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/unit) + add_lit_testsuite(check-fuzzer-unit "Running Fuzzer unit tests" + ${CMAKE_CURRENT_BINARY_DIR}/unit + DEPENDS ${LIBFUZZER_TEST_DEPS}) + set_target_properties(check-fuzzer-unit PROPERTIES FOLDER "Compiler-RT Tests") + add_dependencies(check-fuzzer check-fuzzer-unit) endif() -foreach(arch ${FUZZER_SUPPORTED_ARCH}) - set(LIBFUZZER_TEST_COMPILER ${COMPILER_RT_TEST_COMPILER}) - get_test_cc_for_arch(${arch} LIBFUZZER_TEST_COMPILER LIBFUZZER_TEST_FLAGS) - - string(TOUPPER ${arch} ARCH_UPPER_CASE) - set(CONFIG_NAME ${ARCH_UPPER_CASE}${OS_NAME}Config) - - # LIT-based libFuzzer tests. - configure_lit_site_cfg( - ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in - ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg - ) - list(APPEND LIBFUZZER_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}) - +foreach(stdlib IN ITEMS stdlibc++ libc++) + string(REPLACE "+" "x" stdlib_name ${stdlib}) + foreach(arch ${FUZZER_SUPPORTED_ARCH}) + set(LIBFUZZER_TEST_COMPILER ${COMPILER_RT_TEST_COMPILER}) + get_test_cc_for_arch(${arch} LIBFUZZER_TEST_COMPILER LIBFUZZER_TEST_FLAGS) + + set(LIBFUZZER_TEST_STDLIB ${stdlib}) + string(TOUPPER ${stdlib_name} STDLIB_UPPER_CASE) + + string(TOUPPER ${arch} ARCH_UPPER_CASE) + set(CONFIG_NAME ${ARCH_UPPER_CASE}${STDLIB_UPPER_CASE}${OS_NAME}Config) + + # LIT-based libFuzzer tests. + configure_lit_site_cfg( + ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in + ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg + ) + + add_lit_testsuite(check-fuzzer-${stdlib_name} "Running Fuzzer ${stdlib} tests" + ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME} + DEPENDS ${LIBFUZZER_TEST_DEPS}) + set_target_properties(check-fuzzer-${stdlib_name} PROPERTIES FOLDER "Compiler-RT Tests") + add_dependencies(check-fuzzer check-fuzzer-${stdlib_name}) + endforeach() endforeach() set(EXCLUDE_FROM_ALL ON) - -add_lit_testsuite(check-fuzzer "Running Fuzzer tests" - ${LIBFUZZER_TESTSUITES} - DEPENDS ${LIBFUZZER_TEST_DEPS}) -set_target_properties(check-fuzzer PROPERTIES FOLDER "Compiler-RT Tests") Index: test/fuzzer/lit.cfg =================================================================== --- test/fuzzer/lit.cfg +++ test/fuzzer/lit.cfg @@ -7,6 +7,8 @@ config.suffixes = ['.test'] config.test_source_root = os.path.dirname(__file__) +config.environment['LD_LIBRARY_PATH'] = config.llvm_library_dir + # Choose between lit's internal shell pipeline runner and a real shell. If # LIT_USE_INTERNAL_SHELL is in the environment, we use that as an override. use_lit_shell = os.environ.get("LIT_USE_INTERNAL_SHELL") @@ -51,7 +53,10 @@ def generate_compiler_cmd(is_cpp=True, fuzzer_enabled=True): compiler_cmd = config.c_compiler - link_cmd = '-lc++' if 'darwin' in config.target_triple else '-lstdc++' + if config.clang and config.stdlib == 'libc++': + link_cmd = '-stdlib=libc++ -lc++' + else: + link_cmd = '-lc++' if 'darwin' in config.target_triple else '-lstdc++' std_cmd = '-std=c++11' if is_cpp else '' sanitizers = ['address'] if fuzzer_enabled: Index: test/fuzzer/lit.site.cfg.in =================================================================== --- test/fuzzer/lit.site.cfg.in +++ test/fuzzer/lit.site.cfg.in @@ -5,9 +5,11 @@ config.cpp_compiler = "@LIBFUZZER_TEST_COMPILER@" config.target_flags = "@LIBFUZZER_TEST_FLAGS@" config.c_compiler = "@LIBFUZZER_TEST_COMPILER@" +config.stdlib = "@LIBFUZZER_TEST_STDLIB@" config.osx_sysroot_flag = "@OSX_SYSROOT_FLAG@" config.cmake_binary_dir = "@CMAKE_BINARY_DIR@" +config.llvm_library_dir = "@LLVM_LIBRARY_DIR@" config.target_triple = "@TARGET_TRIPLE@" # Load common config for all compiler-rt lit tests.