diff --git a/CMakeLists.txt b/CMakeLists.txt index e67a3d0ec..5b15a747d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,14 +67,10 @@ else() CACHE BOOL "Build a core for libretro (experimental)") endif(LIBRETRO_INCLUDE_DIR) -# Run-time checks with GCC / LLVM (Clang) AddressSanitizer: -# - stack protection -# - checking of pointer accesses -# # Configure Hatari with AddressSanitizer: # cd build; make clean; cmake -D ENABLE_ASAN:BOOL=1 -D .. # If everything's fine, CMake output should include: -# Performing Test ASAN_AVAILABLE - Success" +# - ASAN : Compiler Address Sanitizer enabled # # After (re-)building Hatari, run it as following to see # available AddressSanitizer options (and that it works): @@ -82,11 +78,12 @@ endif(LIBRETRO_INCLUDE_DIR) # # For more info: # https://github.com/google/sanitizers/wiki/AddressSanitizer +# https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html # CHECK_C_COMPILER_FLAG("-fsanitize=address" ASAN_AVAILABLE) if(ASAN_AVAILABLE) set(ENABLE_ASAN 0 - CACHE BOOL "Enable GCC/LLVM run-time stack/pointer debugging (~2x slowdown)") + CACHE BOOL "Enable GCC/LLVM run-time address debugging (~2x slowdown)") endif(ASAN_AVAILABLE) CHECK_C_COMPILER_FLAG("-fsanitize=undefined" UBSAN_AVAILABLE) @@ -95,6 +92,18 @@ if(UBSAN_AVAILABLE) CACHE BOOL "Enable GCC/LLVM run-time undefined behavior debugging") endif(UBSAN_AVAILABLE) +CHECK_C_COMPILER_FLAG("-fstack-protector-all -fsanitize=bounds-strict" SSP_AVAILABLE) +if(SSP_AVAILABLE) + set(ENABLE_SSP 0 + CACHE BOOL "Enable GCC/LLVM run-time stack protection") +endif(SSP_AVAILABLE) + +CHECK_C_COMPILER_FLAG("-fhardened" HARDENED_AVAILABLE) +if(HARDENED_AVAILABLE) + set(ENABLE_HARDENED 0 + CACHE BOOL "Enable GCC/LLVM run-time hardening options (for production / distros not enabling them by default)") +endif(HARDENED_AVAILABLE) + find_program(GZIP gzip) if(UNIX AND GZIP) set(ENABLE_MAN_PAGES 1 CACHE BOOL "Built and install man pages") @@ -274,12 +283,8 @@ check_struct_has_member("struct dirent" d_type dirent.h HAVE_DIRENT_D_TYPE) # Other CFLAGS: # ############# -# GCC/Clang stack/pointer debugging (~2x slowdown) +# GCC/Clang address pointer access debugging (~2x slowdown) if(ENABLE_ASAN) - # better backtraces - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -fno-omit-frame-pointer") - # enable stack protection - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector-all") # enable AddressSanitizer with global variable tracking set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-common") endif(ENABLE_ASAN) @@ -290,6 +295,24 @@ if(ENABLE_UBSAN) add_definitions(-DENABLE_UBSAN=1) endif(ENABLE_UBSAN) +# GCC/Clang stack protection options (overlaps with HARDENED) +if(ENABLE_SSP) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector-all -fsanitize=bounds-strict") +endif(ENABLE_SSP) + +# GCC/Clang production hardening option (overlaps with SSP) +if(ENABLE_HARDENED) + if(ENABLE_SSP) + message(FATAL_ERROR "Enabled either HARDENED or SSP, not both!") + endif(ENABLE_SSP) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fhardened") +endif(ENABLE_HARDENED) + +# Debug & protection options require better backtraces +if(ENABLE_ASAN OR ENABLE_SSP OR ENABLE_UBSAN) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -fno-omit-frame-pointer") +endif(ENABLE_ASAN OR ENABLE_SSP OR ENABLE_UBSAN) + # GCC/Clang specific flags: if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang") # We want to allow ‘for’-loop initial declarations a la for(int i=0; ...) @@ -545,6 +568,14 @@ if(ENABLE_UBSAN) message(" - UBSAN :\tCompiler Undefined Behavior Sanitizer enabled") endif(ENABLE_UBSAN) +if(ENABLE_SSP) + message(" - SSP :\tCompiler stack protections enabled") +endif(ENABLE_SSP) + +if(ENABLE_HARDENED) + message(" - HARDENED :\tCompiler hardening options enabled") +endif(ENABLE_HARDENED) + if(ENABLE_WERROR) message(" - WERROR :\tCompiler warnings treated as errors") endif(ENABLE_WERROR) diff --git a/configure b/configure index a4e7110a7..5f8ab79f3 100755 --- a/configure +++ b/configure @@ -11,19 +11,24 @@ fi print_help() { - echo "This is a simple configure script wrapper around cmake build system." - echo "Parameters are:" + echo "This is a simple configure script wrapper around CMake build system." + echo + echo "Hatari / build options:" echo " --prefix= Set the install prefix to path" - echo " --enable-asan Enable address sanitizer debug build" - echo " --enable-debug Enable debug (non-optimized) build" - echo " --disable-dsp Disable DSP emulation for Falcon mode." + echo " --disable-dsp Disable DSP emulation for Falcon mode" echo " --disable-tracing Disable tracing messages for debugging" echo " --disable-osx-bundle Disable application bundling on macOS" - echo " --enable-ubsan Enable undefined behavior sanitizer debug build" - echo " --enable-werror Use -Werror flag to stop on compiler warnings" echo " --cross-compile-win64_32 Build the 32 bit Windows version using mingw-w64" echo " --cross-compile-win64_64 Build the 64 bit Windows version using mingw-w64" echo + echo "Debugging / hardening options:" + echo " --enable-asan Enable address sanitizer debug build" + echo " --enable-debug Enable debug (-O/-g) builds" + echo " --enable-hardened Enable compiler run-time hardening (if distro doesn't)" + echo " --enable-ssp Enable compiler stack protections" + echo " --enable-ubsan Enable undefined behavior sanitizer debug build" + echo " --enable-werror Use -Werror flag to stop on compiler warnings" + echo echo "Please run cmake directly for full control over the build." echo } @@ -40,24 +45,11 @@ do print_help exit 0 ;; + # main options --prefix) prefix=${1##*=} # get part after = cmake_args="$cmake_args -DCMAKE_INSTALL_PREFIX:PATH=$prefix" ;; - --enable-asan) - cmake_args="$cmake_args -DENABLE_ASAN:BOOL=1" - ;; - --disable-asan) - cmake_args="$cmake_args -DENABLE_ASAN:BOOL=0" - ;; - --enable-debug) - build_type="Debug" - cmake_args="$cmake_args -DCMAKE_BUILD_TYPE:STRING=Debug" - ;; - --disable-debug) - build_type="Release" - cmake_args="$cmake_args -DCMAKE_BUILD_TYPE:STRING=Release" - ;; --enable-dsp) cmake_args="$cmake_args -DENABLE_DSP_EMU:BOOL=1" ;; @@ -76,6 +68,39 @@ do --disable-osx-bundle) cmake_args="$cmake_args -DENABLE_OSX_BUNDLE:BOOL=0" ;; + --cross-compile-win64_32) + cmake_args="$cmake_args -DCMAKE_TOOLCHAIN_FILE=cmake/Toolchain-mingw32-win64_32.cmake" + ;; + --cross-compile-win64_64) + cmake_args="$cmake_args -DCMAKE_TOOLCHAIN_FILE=cmake/Toolchain-mingw32-win64_64.cmake" + ;; + # debugging options + --enable-asan) + cmake_args="$cmake_args -DENABLE_ASAN:BOOL=1" + ;; + --disable-asan) + cmake_args="$cmake_args -DENABLE_ASAN:BOOL=0" + ;; + --enable-debug) + build_type="Debug" + cmake_args="$cmake_args -DCMAKE_BUILD_TYPE:STRING=Debug" + ;; + --disable-debug) + build_type="Release" + cmake_args="$cmake_args -DCMAKE_BUILD_TYPE:STRING=Release" + ;; + --enable-hardened) + cmake_args="$cmake_args -DENABLE_HARDENED:BOOL=1" + ;; + --disable-hardened) + cmake_args="$cmake_args -DENABLE_HARDENED:BOOL=0" + ;; + --enable-ssp) + cmake_args="$cmake_args -DENABLE_SSP:BOOL=1" + ;; + --disable-ssp) + cmake_args="$cmake_args -DENABLE_SSP:BOOL=0" + ;; --enable-ubsan) cmake_args="$cmake_args -DENABLE_UBSAN:BOOL=1" ;; @@ -88,12 +113,7 @@ do --disable-werror) cmake_args="$cmake_args -DENABLE_WERROR:BOOL=0" ;; - --cross-compile-win64_32) - cmake_args="$cmake_args -DCMAKE_TOOLCHAIN_FILE=cmake/Toolchain-mingw32-win64_32.cmake" - ;; - --cross-compile-win64_64) - cmake_args="$cmake_args -DCMAKE_TOOLCHAIN_FILE=cmake/Toolchain-mingw32-win64_64.cmake" - ;; + *) echo "Invalid argument: $preq" echo "Run $0 --help for a list of valid parameters."