From 179e77d612cf30d7e88bd208b0fac4e8d1f02cc4 Mon Sep 17 00:00:00 2001 From: Alexander Haase Date: Thu, 12 May 2016 19:59:28 +0200 Subject: [PATCH] Added option for static linking gcc sanitizers. If you like to preload a sanitized library in front of an application, it will fail, because it is not the first in the library list anymore. This behaviour is gcc specific - clang will static link the sanitizers instead. To get the same for gcc, the new SANITIZE_LINK_STATIC flag will link the sanitizers static in gcc environments. Note: The preloaded executable must be sanitized, too! Otherwise ASan will print an error message! --- cmake/FindASan.cmake | 3 +- cmake/FindSanitizers.cmake | 7 ++++ cmake/sanitize-helpers.cmake | 68 ++++++++++++++++++++++-------------- 3 files changed, 51 insertions(+), 27 deletions(-) diff --git a/cmake/FindASan.cmake b/cmake/FindASan.cmake index c9c55e6..7605df1 100644 --- a/cmake/FindASan.cmake +++ b/cmake/FindASan.cmake @@ -25,7 +25,8 @@ option(SANITIZE_ADDRESS "Enable AddressSanitizer for sanitized targets." Off) set(FLAG_CANDIDATES - # Clang 3.2+ use this version + # Clang 3.2+ use this version. The no-omit-frame-pointer option is optional. + "-g -sanitize=address -fno-omit-frame-pointer" "-g -fsanitize=address" # Older deprecated flag for ASan diff --git a/cmake/FindSanitizers.cmake b/cmake/FindSanitizers.cmake index de3ea17..2be9d4a 100644 --- a/cmake/FindSanitizers.cmake +++ b/cmake/FindSanitizers.cmake @@ -22,6 +22,13 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +# If any of the used compiler is a GNU compiler, add a second option to static +# link against the sanitizers. +option(SANITIZE_LINK_STATIC "Try to link static against sanitizers." Off) + + + + set(FIND_QUIETLY_FLAG "") if (DEFINED Sanitizers_FIND_QUIETLY) set(FIND_QUIETLY_FLAG "QUIET") diff --git a/cmake/sanitize-helpers.cmake b/cmake/sanitize-helpers.cmake index 1afe1f2..7ea90cc 100644 --- a/cmake/sanitize-helpers.cmake +++ b/cmake/sanitize-helpers.cmake @@ -66,6 +66,33 @@ function (sanitizer_target_compilers TARGET RETURN_VAR) endfunction () +# Helper function to check compiler flags for language compiler. +function (sanitizer_check_compiler_flag FLAG LANG VARIABLE) + if (${LANG} STREQUAL "C") + include(CheckCCompilerFlag) + check_c_compiler_flag("${FLAG}" ${VARIABLE}) + + elseif (${LANG} STREQUAL "CXX") + include(CheckCXXCompilerFlag) + check_cxx_compiler_flag("${FLAG}" ${VARIABLE}) + + elseif (${LANG} STREQUAL "Fortran") + # CheckFortranCompilerFlag was introduced in CMake 3.x. To be compatible + # with older Cmake versions, we will check if this module is present + # before we use it. Otherwise we will define Fortran coverage support as + # not available. + include(CheckFortranCompilerFlag OPTIONAL RESULT_VARIABLE INCLUDED) + if (INCLUDED) + check_fortran_compiler_flag("${FLAG}" ${VARIABLE}) + elseif (NOT CMAKE_REQUIRED_QUIET) + message(STATUS "Performing Test ${VARIABLE}") + message(STATUS "Performing Test ${VARIABLE}" + " - Failed (Check not supported)") + endif () + endif() +endfunction () + + # Helper function to test compiler flags. function (sanitizer_check_compiler_flags FLAG_CANDIDATES NAME PREFIX) set(CMAKE_REQUIRED_QUIET ${${PREFIX}_FIND_QUIETLY}) @@ -84,34 +111,23 @@ function (sanitizer_check_compiler_flags FLAG_CANDIDATES NAME PREFIX) set(CMAKE_REQUIRED_FLAGS "${FLAG}") unset(${PREFIX}_FLAG_DETECTED CACHE) - - if (${LANG} STREQUAL "C") - include(CheckCCompilerFlag) - check_c_compiler_flag("${FLAG}" ${PREFIX}_FLAG_DETECTED) - - elseif (${LANG} STREQUAL "CXX") - include(CheckCXXCompilerFlag) - check_cxx_compiler_flag("${FLAG}" ${PREFIX}_FLAG_DETECTED) - - elseif (${LANG} STREQUAL "Fortran") - # CheckFortranCompilerFlag was introduced in CMake 3.x. To - # be compatible with older Cmake versions, we will check if - # this module is present before we use it. Otherwise we will - # define Fortran coverage support as not available. - include(CheckFortranCompilerFlag OPTIONAL - RESULT_VARIABLE INCLUDED) - if (INCLUDED) - check_fortran_compiler_flag("${FLAG}" - ${PREFIX}_FLAG_DETECTED) - elseif (NOT CMAKE_REQUIRED_QUIET) - message(STATUS - "Performing Test ${PREFIX}_FLAG_DETECTED") - message(STATUS "Performing Test ${PREFIX}_FLAG_DETECTED" - " - Failed (Check not supported)") - endif () - endif() + sanitizer_check_compiler_flag("${FLAG}" ${LANG} + ${PREFIX}_FLAG_DETECTED) if (${PREFIX}_FLAG_DETECTED) + # If compiler is a GNU compiler, search for static flag, if + # SANITIZE_LINK_STATIC is enabled. + if (SANITIZE_LINK_STATIC) + string(TOLOWER ${PREFIX} PREFIX_lower) + sanitizer_check_compiler_flag( + "-static-lib${PREFIX_lower}" ${LANG} + ${PREFIX}_STATIC_FLAG_DETECTED) + + if (${PREFIX}_STATIC_FLAG_DETECTED) + set(FLAG "-static-lib${PREFIX_lower} ${FLAG}") + endif () + endif () + set(${PREFIX}_${COMPILER}_FLAGS "${FLAG}" CACHE STRING "${NAME} flags for ${COMPILER} compiler.") mark_as_advanced(${PREFIX}_${COMPILER}_FLAGS)