From dec27b39d8f998acbede27d93857aed56d59b243 Mon Sep 17 00:00:00 2001 From: Dmitry Chestnykh Date: Sun, 15 Dec 2024 18:03:01 +0300 Subject: [PATCH 1/4] [LLVM][compiler-rt] Fix build with LLVM_USE_SANITIZER=Undefined Fix #120003 The patch contains fixes to all the errors described in the issue attachement --- compiler-rt/cmake/config-ix.cmake | 3 +- .../lib/scudo/standalone/tests/CMakeLists.txt | 2 + compiler-rt/test/CMakeLists.txt | 126 +++++++++--------- llvm/CMakeLists.txt | 9 +- llvm/cmake/modules/HandleLLVMOptions.cmake | 3 +- 5 files changed, 80 insertions(+), 63 deletions(-) diff --git a/compiler-rt/cmake/config-ix.cmake b/compiler-rt/cmake/config-ix.cmake index 6d52eecc9a91f..25b0f6e2f3e2d 100644 --- a/compiler-rt/cmake/config-ix.cmake +++ b/compiler-rt/cmake/config-ix.cmake @@ -931,7 +931,8 @@ endif() # calling malloc on first use. # TODO(hctim): Enable this on Android again. Looks like it's causing a SIGSEGV # for Scudo and GWP-ASan, further testing needed. -if (GWP_ASAN_SUPPORTED_ARCH AND +if (COMPILER_RT_HAS_SANITIZER_COMMON AND + GWP_ASAN_SUPPORTED_ARCH AND COMPILER_RT_BUILD_GWP_ASAN AND COMPILER_RT_BUILD_SANITIZERS AND "gwp_asan" IN_LIST COMPILER_RT_SANITIZERS_TO_BUILD AND diff --git a/compiler-rt/lib/scudo/standalone/tests/CMakeLists.txt b/compiler-rt/lib/scudo/standalone/tests/CMakeLists.txt index a85eb737dba0a..d33fb05114375 100644 --- a/compiler-rt/lib/scudo/standalone/tests/CMakeLists.txt +++ b/compiler-rt/lib/scudo/standalone/tests/CMakeLists.txt @@ -1,5 +1,7 @@ include_directories(..) +include(CompilerRTCompile) + add_custom_target(ScudoUnitTests) set_target_properties(ScudoUnitTests PROPERTIES FOLDER "Compiler-RT Tests") diff --git a/compiler-rt/test/CMakeLists.txt b/compiler-rt/test/CMakeLists.txt index f9e23710d3e4f..3f87e69964f91 100644 --- a/compiler-rt/test/CMakeLists.txt +++ b/compiler-rt/test/CMakeLists.txt @@ -46,75 +46,81 @@ if(NOT ANDROID) endif() endif() -umbrella_lit_testsuite_begin(check-compiler-rt) - -function(compiler_rt_test_runtime runtime) - string(TOUPPER ${runtime} runtime_uppercase) - if(COMPILER_RT_HAS_${runtime_uppercase} AND COMPILER_RT_INCLUDE_TESTS) - if (${runtime} STREQUAL cfi AND NOT COMPILER_RT_HAS_UBSAN) - # CFI tests require diagnostic mode, which is implemented in UBSan. - elseif (${runtime} STREQUAL scudo_standalone) - add_subdirectory(scudo/standalone) - else() - add_subdirectory(${runtime}) +# XXX: Maybe more precise conditions to enable/disable tests +# But now the below code is broken at least with LLVM_USE_SANITIZER=Undefined +if(NOT LLVM_USE_SANITIZER) + + umbrella_lit_testsuite_begin(check-compiler-rt) + + function(compiler_rt_test_runtime runtime) + string(TOUPPER ${runtime} runtime_uppercase) + if(COMPILER_RT_HAS_${runtime_uppercase} AND COMPILER_RT_INCLUDE_TESTS) + if (${runtime} STREQUAL cfi AND NOT COMPILER_RT_HAS_UBSAN) + # CFI tests require diagnostic mode, which is implemented in UBSan. + elseif (${runtime} STREQUAL scudo_standalone) + add_subdirectory(scudo/standalone) + else() + add_subdirectory(${runtime}) + endif() endif() - endif() -endfunction() + endfunction() -# Run sanitizer tests only if we're sure that clang would produce -# working binaries. -if(COMPILER_RT_CAN_EXECUTE_TESTS) - if(COMPILER_RT_BUILD_BUILTINS) - add_subdirectory(builtins) - endif() - if(COMPILER_RT_BUILD_SANITIZERS) - compiler_rt_test_runtime(interception) + # Run sanitizer tests only if we're sure that clang would produce + # working binaries. + if(COMPILER_RT_CAN_EXECUTE_TESTS) + if(COMPILER_RT_BUILD_BUILTINS) + add_subdirectory(builtins) + endif() + if(COMPILER_RT_BUILD_SANITIZERS) + compiler_rt_test_runtime(interception) - compiler_rt_test_runtime(lsan) - compiler_rt_test_runtime(ubsan) - compiler_rt_test_runtime(sanitizer_common) + compiler_rt_test_runtime(lsan) + compiler_rt_test_runtime(ubsan) + compiler_rt_test_runtime(sanitizer_common) - # OpenBSD not supporting asan, cannot run the tests - if(COMPILER_RT_BUILD_LIBFUZZER AND NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "OpenBSD" AND NOT ANDROID) - compiler_rt_test_runtime(fuzzer) + # OpenBSD not supporting asan, cannot run the tests + if(COMPILER_RT_BUILD_LIBFUZZER AND NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "OpenBSD" AND NOT ANDROID) + compiler_rt_test_runtime(fuzzer) - # These tests don't need an additional runtime but use asan runtime. - add_subdirectory(metadata) - endif() + # These tests don't need an additional runtime but use asan runtime. + add_subdirectory(metadata) + endif() - foreach(sanitizer ${COMPILER_RT_SANITIZERS_TO_BUILD}) - compiler_rt_test_runtime(${sanitizer}) - endforeach() - endif() - if(COMPILER_RT_BUILD_PROFILE AND COMPILER_RT_HAS_PROFILE) - compiler_rt_test_runtime(profile) - endif() - if(COMPILER_RT_BUILD_CTX_PROFILE) - compiler_rt_test_runtime(ctx_profile) - endif() - if(COMPILER_RT_BUILD_MEMPROF) - compiler_rt_test_runtime(memprof) - endif() - if(COMPILER_RT_BUILD_XRAY) - compiler_rt_test_runtime(xray) + foreach(sanitizer ${COMPILER_RT_SANITIZERS_TO_BUILD}) + compiler_rt_test_runtime(${sanitizer}) + endforeach() + endif() + if(COMPILER_RT_BUILD_PROFILE AND COMPILER_RT_HAS_PROFILE) + compiler_rt_test_runtime(profile) + endif() + if(COMPILER_RT_BUILD_CTX_PROFILE) + compiler_rt_test_runtime(ctx_profile) + endif() + if(COMPILER_RT_BUILD_MEMPROF) + compiler_rt_test_runtime(memprof) + endif() + if(COMPILER_RT_BUILD_XRAY) + compiler_rt_test_runtime(xray) + endif() + if(COMPILER_RT_BUILD_ORC) + compiler_rt_Test_runtime(orc) + endif() + # ShadowCallStack does not yet provide a runtime with compiler-rt, the tests + # include their own minimal runtime + add_subdirectory(shadowcallstack) endif() - if(COMPILER_RT_BUILD_ORC) - compiler_rt_Test_runtime(orc) + + # Now that we've traversed all the directories and know all the lit testsuites, + # introduce a rule to run to run all of them. + get_property(LLVM_COMPILER_RT_LIT_DEPENDS GLOBAL PROPERTY LLVM_COMPILER_RT_LIT_DEPENDS) + add_custom_target(compiler-rt-test-depends) + set_target_properties(compiler-rt-test-depends PROPERTIES FOLDER "Compiler-RT/Tests") + if(LLVM_COMPILER_RT_LIT_DEPENDS) + add_dependencies(compiler-rt-test-depends ${LLVM_COMPILER_RT_LIT_DEPENDS}) endif() - # ShadowCallStack does not yet provide a runtime with compiler-rt, the tests - # include their own minimal runtime - add_subdirectory(shadowcallstack) -endif() + umbrella_lit_testsuite_end(check-compiler-rt) -# Now that we've traversed all the directories and know all the lit testsuites, -# introduce a rule to run to run all of them. -get_property(LLVM_COMPILER_RT_LIT_DEPENDS GLOBAL PROPERTY LLVM_COMPILER_RT_LIT_DEPENDS) -add_custom_target(compiler-rt-test-depends) -set_target_properties(compiler-rt-test-depends PROPERTIES FOLDER "Compiler-RT/Tests") -if(LLVM_COMPILER_RT_LIT_DEPENDS) - add_dependencies(compiler-rt-test-depends ${LLVM_COMPILER_RT_LIT_DEPENDS}) -endif() -umbrella_lit_testsuite_end(check-compiler-rt) +endif(LLVM_USE_SANITIZER) if(COMPILER_RT_STANDALONE_BUILD) if(NOT TARGET check-all) diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt index f14065ab03799..f4bd6ceaa681d 100644 --- a/llvm/CMakeLists.txt +++ b/llvm/CMakeLists.txt @@ -707,8 +707,15 @@ endif( LLVM_USE_PERF ) set(LLVM_USE_SANITIZER "" CACHE STRING "Define the sanitizer used to build binaries and tests.") option(LLVM_OPTIMIZE_SANITIZED_BUILDS "Pass -O1 on debug sanitizer builds" ON) + +if( CMAKE_C_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) + set(LLVM_UBSAN_FLAGS_CLANG "-fno-sanitize=function") +else() + # gcc doesn't know about -fsanitize=function + set(LLVM_UBSAN_FLAGS_CLANG) +endif() set(LLVM_UBSAN_FLAGS - "-fsanitize=undefined -fno-sanitize=vptr,function -fno-sanitize-recover=all" + "-fsanitize=undefined -fno-sanitize=vptr ${LLVM_UBSAN_FLAGS_CLANG} -fno-sanitize-recover=all" CACHE STRING "Compile flags set to enable UBSan. Only used if LLVM_USE_SANITIZER contains 'Undefined'.") set(LLVM_LIB_FUZZING_ENGINE "" CACHE PATH diff --git a/llvm/cmake/modules/HandleLLVMOptions.cmake b/llvm/cmake/modules/HandleLLVMOptions.cmake index f19125eb6bf27..76ace6a1a951e 100644 --- a/llvm/cmake/modules/HandleLLVMOptions.cmake +++ b/llvm/cmake/modules/HandleLLVMOptions.cmake @@ -1064,7 +1064,8 @@ if(LLVM_USE_SANITIZER) if (LLVM_USE_SANITIZE_COVERAGE) append("-fsanitize=fuzzer-no-link" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() - if (LLVM_USE_SANITIZER MATCHES ".*Undefined.*") + if (LLVM_USE_SANITIZER MATCHES ".*Undefined.*" AND CMAKE_C_COMPILER_ID MATCHES "Clang" AND + CMAKE_CXX_COMPILER_ID MATCHES "Clang") set(IGNORELIST_FILE "${PROJECT_SOURCE_DIR}/utils/sanitizers/ubsan_ignorelist.txt") if (EXISTS "${IGNORELIST_FILE}") # Use this option name version since -fsanitize-ignorelist is only From aa5865edb5fe9df00fcea247262880489573ac7b Mon Sep 17 00:00:00 2001 From: Dmitry Chestnykh Date: Mon, 16 Dec 2024 19:47:03 +0300 Subject: [PATCH 2/4] [LLVM] Check host compiler supports flags --- llvm/CMakeLists.txt | 6 +++++- llvm/cmake/modules/HandleLLVMOptions.cmake | 10 +++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt index f4bd6ceaa681d..9ff0b8c4dd5ba 100644 --- a/llvm/CMakeLists.txt +++ b/llvm/CMakeLists.txt @@ -3,6 +3,8 @@ cmake_minimum_required(VERSION 3.20.0) include(CMakeDependentOption) +include(CheckCCompilerFlag) +include(CheckCXXCompilerFlag) set(LLVM_COMMON_CMAKE_UTILS ${CMAKE_CURRENT_SOURCE_DIR}/../cmake) include(${LLVM_COMMON_CMAKE_UTILS}/Modules/CMakePolicy.cmake @@ -708,7 +710,9 @@ set(LLVM_USE_SANITIZER "" CACHE STRING "Define the sanitizer used to build binaries and tests.") option(LLVM_OPTIMIZE_SANITIZED_BUILDS "Pass -O1 on debug sanitizer builds" ON) -if( CMAKE_C_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) +check_c_compiler_flag(-fno-sanitize=function C_SUPPORTS_FNO_SANITIZE_FUNCTION_FLAG) +check_cxx_compiler_flag(-fno-sanitize=function CXX_SUPPORTS_FNO_SANITIZE_FUNCTION_FLAG) +if( CMAKE_C_COMPILER_ID MATCHES "Clang" AND C_SUPPORTS_FNO_SANITIZE_FUNCTION_FLAG AND CXX_SUPPORTS_FNO_SANITIZE_FUNCTION_FLAG) set(LLVM_UBSAN_FLAGS_CLANG "-fno-sanitize=function") else() # gcc doesn't know about -fsanitize=function diff --git a/llvm/cmake/modules/HandleLLVMOptions.cmake b/llvm/cmake/modules/HandleLLVMOptions.cmake index 76ace6a1a951e..fd493dd36389f 100644 --- a/llvm/cmake/modules/HandleLLVMOptions.cmake +++ b/llvm/cmake/modules/HandleLLVMOptions.cmake @@ -1064,14 +1064,14 @@ if(LLVM_USE_SANITIZER) if (LLVM_USE_SANITIZE_COVERAGE) append("-fsanitize=fuzzer-no-link" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() - if (LLVM_USE_SANITIZER MATCHES ".*Undefined.*" AND CMAKE_C_COMPILER_ID MATCHES "Clang" AND - CMAKE_CXX_COMPILER_ID MATCHES "Clang") + if (LLVM_USE_SANITIZER MATCHES ".*Undefined.*") set(IGNORELIST_FILE "${PROJECT_SOURCE_DIR}/utils/sanitizers/ubsan_ignorelist.txt") - if (EXISTS "${IGNORELIST_FILE}") + check_c_compiler_flag(-fsanitize-blacklist=${IGNORELIST_FILE} C_SUPPORTS_FSANITIZE_BLACKLIST_FLAG) + check_cxx_compiler_flag(-fsanitize-blacklist=${IGNORELIST_FILE} CXX_SUPPORTS_FSANITIZE_BLACKLIST_FLAG) + if (EXISTS "${IGNORELIST_FILE}" AND C_SUPPORTS_FSANITIZE_BLACKLIST_FLAG AND CXX_SUPPORTS_FSANITIZE_BLACKLIST_FLAG) # Use this option name version since -fsanitize-ignorelist is only # accepted with clang 13.0 or newer. - append("-fsanitize-blacklist=${IGNORELIST_FILE}" - CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + append("-fsanitize-blacklist=${IGNORELIST_FILE}" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() endif() endif() From 574e7f715a8ced5eb314140ecfde97561e210089 Mon Sep 17 00:00:00 2001 From: Dmitry Chestnykh Date: Mon, 16 Dec 2024 19:49:10 +0300 Subject: [PATCH 3/4] [LLVM] Update cond & comment --- llvm/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt index 9ff0b8c4dd5ba..3515792c07e64 100644 --- a/llvm/CMakeLists.txt +++ b/llvm/CMakeLists.txt @@ -712,10 +712,10 @@ option(LLVM_OPTIMIZE_SANITIZED_BUILDS "Pass -O1 on debug sanitizer builds" ON) check_c_compiler_flag(-fno-sanitize=function C_SUPPORTS_FNO_SANITIZE_FUNCTION_FLAG) check_cxx_compiler_flag(-fno-sanitize=function CXX_SUPPORTS_FNO_SANITIZE_FUNCTION_FLAG) -if( CMAKE_C_COMPILER_ID MATCHES "Clang" AND C_SUPPORTS_FNO_SANITIZE_FUNCTION_FLAG AND CXX_SUPPORTS_FNO_SANITIZE_FUNCTION_FLAG) +if( C_SUPPORTS_FNO_SANITIZE_FUNCTION_FLAG AND CXX_SUPPORTS_FNO_SANITIZE_FUNCTION_FLAG ) set(LLVM_UBSAN_FLAGS_CLANG "-fno-sanitize=function") else() - # gcc doesn't know about -fsanitize=function + # some compiler (for example gcc) doesn't know about -fsanitize=function set(LLVM_UBSAN_FLAGS_CLANG) endif() set(LLVM_UBSAN_FLAGS From 0fc05eff1eb1f6400a891cd56dc8b66d8137537e Mon Sep 17 00:00:00 2001 From: Dmitry Chestnykh Date: Mon, 16 Dec 2024 19:51:25 +0300 Subject: [PATCH 4/4] [LLVM] Rename variable --- llvm/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt index 3515792c07e64..93cee3b3ff482 100644 --- a/llvm/CMakeLists.txt +++ b/llvm/CMakeLists.txt @@ -713,13 +713,13 @@ option(LLVM_OPTIMIZE_SANITIZED_BUILDS "Pass -O1 on debug sanitizer builds" ON) check_c_compiler_flag(-fno-sanitize=function C_SUPPORTS_FNO_SANITIZE_FUNCTION_FLAG) check_cxx_compiler_flag(-fno-sanitize=function CXX_SUPPORTS_FNO_SANITIZE_FUNCTION_FLAG) if( C_SUPPORTS_FNO_SANITIZE_FUNCTION_FLAG AND CXX_SUPPORTS_FNO_SANITIZE_FUNCTION_FLAG ) - set(LLVM_UBSAN_FLAGS_CLANG "-fno-sanitize=function") + set(FNO_SANITIZE_FUNCTION_FLAG "-fno-sanitize=function") else() # some compiler (for example gcc) doesn't know about -fsanitize=function - set(LLVM_UBSAN_FLAGS_CLANG) + set(FNO_SANITIZE_FUNCTION_FLAG) endif() set(LLVM_UBSAN_FLAGS - "-fsanitize=undefined -fno-sanitize=vptr ${LLVM_UBSAN_FLAGS_CLANG} -fno-sanitize-recover=all" + "-fsanitize=undefined -fno-sanitize=vptr ${FNO_SANITIZE_FUNCTION_FLAG} -fno-sanitize-recover=all" CACHE STRING "Compile flags set to enable UBSan. Only used if LLVM_USE_SANITIZER contains 'Undefined'.") set(LLVM_LIB_FUZZING_ENGINE "" CACHE PATH