diff --git a/cmake/FindMSan.cmake b/cmake/FindMSan.cmake index 2a7a2a8..ac9a290 100644 --- a/cmake/FindMSan.cmake +++ b/cmake/FindMSan.cmake @@ -1,7 +1,8 @@ -# # The MIT License (MIT) # -# Copyright (c) 2013 Matthew Arsenault +# Copyright (c) +# 2013 Matthew Arsenault +# 2015-2016 RWTH Aachen University, Federal Republic of Germany # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -10,66 +11,32 @@ # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. -# This module tests if memory sanitizer is supported by the compiler, -# and creates a MSan build type (i.e. set CMAKE_BUILD_TYPE=MSan to use -# it). This sets the following variables: -# -# CMAKE_C_FLAGS_MSAN - Flags to use for C with msan -# CMAKE_CXX_FLAGS_MSAN - Flags to use for C++ with msan -# HAVE_MEMORY_SANITIZER - True or false if the MSan build type is available +option(SANITIZE_MEMORY "Enable MemorySanitizer for sanitized targets." Off) -include(CheckCCompilerFlag) +set(FLAG_CANDIDATES + "-g -O1 -fsanitize=memory" +) -# Set -Werror to catch "argument unused during compilation" warnings -set(CMAKE_REQUIRED_FLAGS "-Werror -fmemory-sanitizer") # Also needs to be a link flag for test to pass -check_c_compiler_flag("-fmemory-sanitizer" HAVE_FLAG_MEMORY_SANITIZER) -set(CMAKE_REQUIRED_FLAGS "-Werror -fsanitize=memory") # Also needs to be a link flag for test to pass -check_c_compiler_flag("-fsanitize=memory" HAVE_FLAG_SANITIZE_MEMORY) +include(sanitize-helpers) -unset(CMAKE_REQUIRED_FLAGS) +sanitizer_check_compiler_flags("${FLAG_CANDIDATES}" "MemorySanitizer" "MSan") -if(HAVE_FLAG_SANITIZE_MEMORY) - # Clang 3.2+ use this version - set(MEMORY_SANITIZER_FLAG "-fsanitize=memory") -elseif(HAVE_FLAG_MEMORY_SANITIZER) - # Older deprecated flag for MSan - set(MEMORY_SANITIZER_FLAG "-fmemory-sanitizer") -endif() +function (add_sanitize_memory TARGET) + if (NOT SANITIZE_THREAD) + return() + endif () -if(NOT MEMORY_SANITIZER_FLAG) - return() -else(NOT MEMORY_SANITIZER_FLAG) - set(HAVE_MEMORY_SANITIZER TRUE) -endif() - -set(HAVE_MEMORY_SANITIZER TRUE) - -set(CMAKE_C_FLAGS_MSAN "-O1 -g ${MEMORY_SANITIZER_FLAG} -fno-omit-frame-pointer -fno-optimize-sibling-calls" - CACHE STRING "Flags used by the C compiler during MSan builds." - FORCE) -set(CMAKE_CXX_FLAGS_MSAN "-O1 -g ${MEMORY_SANITIZER_FLAG} -fno-omit-frame-pointer -fno-optimize-sibling-calls" - CACHE STRING "Flags used by the C++ compiler during MSan builds." - FORCE) -set(CMAKE_EXE_LINKER_FLAGS_MSAN "${MEMORY_SANITIZER_FLAG}" - CACHE STRING "Flags used for linking binaries during MSan builds." - FORCE) -set(CMAKE_SHARED_LINKER_FLAGS_MSAN "${MEMORY_SANITIZER_FLAG}" - CACHE STRING "Flags used by the shared libraries linker during MSan builds." - FORCE) -mark_as_advanced(CMAKE_C_FLAGS_MSAN - CMAKE_CXX_FLAGS_MSAN - CMAKE_EXE_LINKER_FLAGS_MSAN - CMAKE_SHARED_LINKER_FLAGS_MSAN) + saitizer_add_flags(${TARGET} "MemorySanitizer" "MSan") +endfunction () diff --git a/cmake/FindSanitizers.cmake b/cmake/FindSanitizers.cmake index 272bb2d..e92221c 100644 --- a/cmake/FindSanitizers.cmake +++ b/cmake/FindSanitizers.cmake @@ -30,6 +30,12 @@ option(SANITIZE "Enable all available sanitizers for sanitized targets." OFF) if (SANITIZE) set(SANITIZE_ADDRESS ON CACHE BOOL "Enable AddressSanitizer for sanitized targets." FORCE) + set(SANITIZE_THREAD ON CACHE BOOL + "Enable ThreadSanitizer for sanitized targets." FORCE) + set(SANITIZE_MEMORY ON CACHE BOOL + "Enable MemorySanitizer for sanitized targets." FORCE) + set(SANITIZE_UNDEFINED ON CACHE BOOL + "Enable UndefinedBehaviorSanitizer for sanitized targets." FORCE) endif (SANITIZE) @@ -41,10 +47,16 @@ if (DEFINED Sanitizers_FIND_QUIETLY) endif () find_package(ASan ${FIND_QUIETLY_FLAG}) +find_package(TSan ${FIND_QUIETLY_FLAG}) +find_package(MSan ${FIND_QUIETLY_FLAG}) +find_package(UBSan ${FIND_QUIETLY_FLAG}) function(add_sanitizers TARGET) add_sanitize_address(${TARGET}) + add_sanitize_thread(${TARGET}) + add_sanitize_memory(${TARGET}) + add_sanitize_undefined(${TARGET}) endfunction(add_sanitizers) diff --git a/cmake/FindTSan.cmake b/cmake/FindTSan.cmake index 283ae7f..b933642 100644 --- a/cmake/FindTSan.cmake +++ b/cmake/FindTSan.cmake @@ -1,7 +1,8 @@ -# # The MIT License (MIT) # -# Copyright (c) 2013 Matthew Arsenault +# Copyright (c) +# 2013 Matthew Arsenault +# 2015-2016 RWTH Aachen University, Federal Republic of Germany # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -10,68 +11,32 @@ # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. -# This module tests if thread sanitizer is supported by the compiler, -# and creates a TSan build type (i.e. set CMAKE_BUILD_TYPE=TSan to use -# it). This sets the following variables: -# -# CMAKE_C_FLAGS_TSAN - Flags to use for C with tsan -# CMAKE_CXX_FLAGS_TSAN - Flags to use for C++ with tsan -# HAVE_THREAD_SANITIZER - True or false if the TSan build type is available +option(SANITIZE_THREAD "Enable ThreadSanitizer for sanitized targets." Off) -include(CheckCCompilerFlag) +set(FLAG_CANDIDATES + "-g -O1 -fsanitize=thread" +) -# Set -Werror to catch "argument unused during compilation" warnings -set(CMAKE_REQUIRED_FLAGS "-Werror -fthread-sanitizer") # Also needs to be a link flag for test to pass -check_c_compiler_flag("-fthread-sanitizer" HAVE_FLAG_THREAD_SANITIZER) +include(sanitize-helpers) -set(CMAKE_REQUIRED_FLAGS "-Werror -fsanitize=thread") # Also needs to be a link flag for test to pass -check_c_compiler_flag("-fsanitize=thread" HAVE_FLAG_SANITIZE_THREAD) -unset(CMAKE_REQUIRED_FLAGS) +sanitizer_check_compiler_flags("${FLAG_CANDIDATES}" "ThreadSanitizer" "TSan") -# A special test that uses threads seems to not be necessary. tsan -# symbols are used even in just int main() { return 0; } +function (add_sanitize_thread TARGET) + if (NOT SANITIZE_THREAD) + return() + endif () - -if(HAVE_FLAG_SANITIZE_THREAD) - # Clang 3.2+ use this version - set(THREAD_SANITIZER_FLAG "-fsanitize=thread") -elseif(HAVE_FLAG_THREAD_SANITIZER) - # Older deprecated flag for TSan - set(THREAD_SANITIZER_FLAG_FLAG "-fthread-sanitizer") -else() - set(HAVE_THREAD_SANITIZER FALSE) - return() -endif() - -set(HAVE_THREAD_SANITIZER TRUE) - -set(CMAKE_C_FLAGS_TSAN "-O1 -g ${THREAD_SANITIZER_FLAG} -fno-omit-frame-pointer" - CACHE STRING "Flags used by the C compiler during TSan builds." - FORCE - ) -set(CMAKE_CXX_FLAGS_TSAN "-O1 -g ${THREAD_SANITIZER_FLAG} -fno-omit-frame-pointer" - CACHE STRING "Flags used by the C++ compiler during TSan builds." - FORCE) -set(CMAKE_EXE_LINKER_FLAGS_TSAN "${THREAD_SANITIZER_FLAG}" - CACHE STRING "Flags used for linking binaries during TSan builds." - FORCE) -set(CMAKE_SHARED_LINKER_FLAGS_TSAN "${THREAD_SANITIZER_FLAG}" - CACHE STRING "Flags used by the shared libraries linker during TSan builds." - FORCE) -mark_as_advanced(CMAKE_C_FLAGS_TSAN - CMAKE_CXX_FLAGS_TSAN - CMAKE_EXE_LINKER_FLAGS_TSAN - CMAKE_SHARED_LINKER_FLAGS_TSAN) + saitizer_add_flags(${TARGET} "ThreadSanitizer" "TSan") +endfunction () diff --git a/cmake/FindUBSan.cmake b/cmake/FindUBSan.cmake index a31c68f..f520f36 100644 --- a/cmake/FindUBSan.cmake +++ b/cmake/FindUBSan.cmake @@ -1,7 +1,8 @@ -# # The MIT License (MIT) # -# Copyright (c) 2013 Matthew Arsenault +# Copyright (c) +# 2013 Matthew Arsenault +# 2015-2016 RWTH Aachen University, Federal Republic of Germany # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -10,115 +11,34 @@ # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. -# Check if the compiler supports a working ubsan. Provides a UBSan -# build type, which is essentially Debug + ubsan. The flag can be used -# independently to compose it with other build types or sanitizers. -# -# Sets these variables: -# -# HAVE_UNDEFINED_BEHAVIOR_SANITIZER - True or false if the UBSan is available -# UNDEFINED_BEHAVIOR_SANITIZER_FLAG - Flag to add to compiler to use ubsan if supported -# -# CMAKE_C_FLAGS_UBSAN - Flags to use for C with ubsan -# CMAKE_CXX_FLAGS_UBSAN - Flags to use for C++ with ubsan -## -# +option(SANITIZE_UNDEFINED + "Enable UndefinedBehaviorSanitizer for sanitized targets." Off) + +set(FLAG_CANDIDATES + "-g -O1 -fsanitize=undefined" +) -include(CheckCXXCompilerFlag) -include(CheckCXXSourceRuns) +include(sanitize-helpers) -# Set -Werror to catch "argument unused during compilation" warnings -set(CMAKE_REQUIRED_FLAGS "-Werror") -check_cxx_compiler_flag("-fsanitize=undefined" HAVE_FLAG_SANITIZE_UNDEFINED) -check_cxx_compiler_flag("-fcatch-undefined-behavior" HAVE_FLAG_CATCH_UNDEFINED_BEHAVIOR) -if(HAVE_FLAG_SANITIZE_UNDEFINED) - set(UNDEFINED_BEHAVIOR_SANITIZER_FLAG "-fsanitize=undefined") -elseif(HAVE_FLAG_CATCH_UNDEFINED_BEHAVIOR) - set(UNDEFINED_BEHAVIOR_SANITIZER_FLAG "-fcatch-undefined-behavior") -else() - set(HAVE_UNDEFINED_BEHAVIOR_SANITIZER FALSE) - return() -endif() -unset(CMAKE_REQUIRED_FLAGS) - - -# It isn't sufficient to check if the flag works since the -# check_c_compiler_flag test doesn't link the output. -# -# Most clang packages ship broken packages (the autotools build -# produces a broken package which doesn't include the ubsan -# compiler-rt, so check that it actually works with a linked program -# before trying to use it -set(CMAKE_REQUIRED_FLAGS "${UNDEFINED_BEHAVIOR_SANITIZER_FLAG} -Wno-error=delete-non-virtual-dtor") - -check_cxx_source_runs( -" -#include -#include -#include - -class BarB -{ - public: - float y; - /* Include something that uses a virtual function. The symbols - that are broken on current OS X libc++ involve this */ - virtual int arst(int o) - { - return 4 + o; - } - }; - -/* Just include something that ubsan will need to check */ -int main(int argc, const char* argv[]) -{ - BarB* b = new BarB(); - if (argc > 1) - { - fputs(argv[atoi(argv[1])], stdout); - std::cout << b->arst(atoi(argv[1])); - } - - delete b; - return 0; -} -" - HAVE_UNDEFINED_BEHAVIOR_SANITIZER) -unset(CMAKE_REQUIRED_FLAGS) - -if(NOT HAVE_UNDEFINED_BEHAVIOR_SANITIZER) - return() -endif() - - -set(CMAKE_C_FLAGS_UBSAN "-O0 -g ${UNDEFINED_BEHAVIOR_SANITIZER_FLAG} -fno-omit-frame-pointer" - CACHE STRING "Flags used by the C compiler during UBSan builds." - FORCE) -set(CMAKE_CXX_FLAGS_UBSAN "-O0 -g ${UNDEFINED_BEHAVIOR_SANITIZER_FLAG} -fno-omit-frame-pointer" - CACHE STRING "Flags used by the C++ compiler during UBSan builds." - FORCE) -set(CMAKE_EXE_LINKER_FLAGS_UBSAN "${UNDEFINED_BEHAVIOR_SANITIZER_FLAG}" - CACHE STRING "Flags used for linking binaries during UBSan builds." - FORCE) -set(CMAKE_SHARED_LINKER_FLAGS_UBSAN "${UNDEFINED_BEHAVIOR_SANITIZER_FLAG}" - CACHE STRING "Flags used by the shared libraries linker during UBSan builds." - FORCE) -mark_as_advanced(CMAKE_C_FLAGS_UBSAN - CMAKE_CXX_FLAGS_UBSAN - CMAKE_EXE_LINKER_FLAGS_UBSAN - CMAKE_SHARED_LINKER_FLAGS_UBSAN) +sanitizer_check_compiler_flags("${FLAG_CANDIDATES}" "UndefinedBehaviorSanitizer" + "UBSan") +function (add_sanitize_undefined TARGET) + if (NOT SANITIZE_UNDEFINED) + return() + endif () + saitizer_add_flags(${TARGET} "UndefinedBehaviorSanitizer" "UBSan") +endfunction ()