diff --git a/cmake/modules/sanitaizers.cmake b/cmake/modules/sanitaizers.cmake new file mode 100644 index 000000000..f87a58a24 --- /dev/null +++ b/cmake/modules/sanitaizers.cmake @@ -0,0 +1,93 @@ +# +# Copyright (C) 2018 by George Cave - gcave@stablecoder.ca +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. + +set( + USE_SANITIZER + "" + CACHE + STRING + "Compile with a sanitizer. Options are: Address, Memory, MemoryWithOrigins, Undefined, Thread, Leak" + ) + +function(append value) + foreach(variable ${ARGN}) + set(${variable} "${${variable}} ${value}" PARENT_SCOPE) + endforeach(variable) +endfunction() + +if(USE_SANITIZER) + append("-fno-omit-frame-pointer" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + + if(UNIX) + + if(uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG") + append("-O1" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + endif() + + if(USE_SANITIZER MATCHES "([Aa]ddress)") + + message(STATUS "Building with Address sanitizer") + set(ENV{ASAN_OPTIONS} "halt_on_error=1:strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-g -O1") + append("-fsanitize=address -fsanitize-address-use-after-scope -fsanitize-recover=address" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + + elseif(USE_SANITIZER MATCHES "([Mm]emory([Ww]ith[Oo]rigins)?)") + + # Optional: -fno-optimize-sibling-calls -fsanitize-memory-track-origins=2 + append("-fsanitize=memory" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + if(USE_SANITIZER MATCHES "([Mm]emory[Ww]ith[Oo]rigins)") + message(STATUS "Building with MemoryWithOrigins sanitizer") + append("-fsanitize-memory-track-origins" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + else() + message(STATUS "Building with Memory sanitizer") + endif() + + elseif(USE_SANITIZER MATCHES "([Uu]ndefined)") + + message(STATUS "Building with Undefined sanitizer") + set(ENV{UBSAN_OPTIONS} "print_stacktrace=1") + append("-fsanitize=undefined" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + if(EXISTS "${BLACKLIST_FILE}") + append("-fsanitize-blacklist=${BLACKLIST_FILE}" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + endif() + + elseif(USE_SANITIZER MATCHES "([Tt]hread)") + + message(STATUS "Building with Thread sanitizer") + set(ENV{TSAN_OPTIONS} "second_deadlock_stack=1") + append("-fsanitize=thread" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + + elseif(USE_SANITIZER MATCHES "([Ll]eak)") + + message(STATUS "Building with Leak sanitizer") + append("-fsanitize=leak" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + + else() + + message(FATAL_ERROR "Unsupported value of USE_SANITIZER: ${USE_SANITIZER}") + + endif() + elseif(MSVC) + if(USE_SANITIZER MATCHES "([Aa]ddress)") + message(STATUS "Building with Address sanitizer") + append("-fsanitize=address" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + else() + message(FATAL_ERROR "This sanitizer not yet supported in the MSVC environment: ${USE_SANITIZER}") + endif() + else() + message(FATAL_ERROR "USE_SANITIZER is not supported on this platform.") + endif() + +endif() diff --git a/scripts/build.sh b/scripts/build.sh index 667bfad87..01d5f5d73 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -9,33 +9,25 @@ build_clang() { case "$TARGET" in debug) CMAKE_BUILD_TYPE=Debug - build ;; release) CMAKE_BUILD_TYPE=RelWithDebInfo - build ;; asan) - export ASAN_OPTIONS='halt_on_error=1:strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1' - ASAN_CXX_FLAGS='-fno-omit-frame-pointer -fsanitize=address -fsanitize-address-use-after-scope -fsanitize-recover=address' - CMAKE_CXX_FLAGS_RELWITHDEBINFO="-g -O1 ${ASAN_CXX_FLAGS}" + USE_SANITIZER="Address" CMAKE_BUILD_TYPE=RelWithDebInfo - build ;; ubsan) - export UBSAN_OPTIONS='print_stacktrace=1' + USE_SANITIZER="Undefined" CMAKE_BUILD_TYPE=Debug - CMAKE_CXX_FLAGS='-fno-omit-frame-pointer -fsanitize=undefined' - build ;; tsan) - export TSAN_OPTIONS='second_deadlock_stack=1' + USE_SANITIZER="Thread" CMAKE_BUILD_TYPE=RelWithDebInfo - CMAKE_CXX_FLAGS_RELWITHDEBINFO='-g -O2 -fno-omit-frame-pointer -fsanitize=thread' - build ;; *) usage "bad clang target '$TARGET'";; esac + build } build_gcc() { @@ -116,6 +108,7 @@ build() { -DCMAKE_CXX_COMPILER="${CXX_COMPILER}" \ -DCMAKE_CXX_FLAGS="$CMAKE_CXX_FLAGS"\ -DCMAKE_CXX_FLAGS_RELWITHDEBINFO="$CMAKE_CXX_FLAGS_RELWITHDEBINFO" \ + -DUSE_SANITIZER="$USE_SANITIZER" \ -DCMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE \ -DOZO_BUILD_TESTS=ON \ -DOZO_BUILD_EXAMPLES=ON \ diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d853d871d..d668bdc58 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -16,6 +16,8 @@ include_directories(SYSTEM "${source_dir}/include") include_directories(SYSTEM "${CMAKE_CURRENT_BINARY_DIR}/include") link_directories("${CMAKE_CURRENT_BINARY_DIR}/lib") +include(sanitaizers) + include_directories("${CMAKE_CURRENT_SOURCE_DIR}") set(SOURCES