From c08855de881d728cb72611d8695335fb7f571a58 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 29 Mar 2018 22:57:09 +0200 Subject: [PATCH] Merge #12692: Add configure options for various -fsanitize flags 6feb46c Add --with-sanitizers option to configure (Evan Klitzke) Pull request description: This adds configure options for `-fsanitize=address`, `-fsanitize=thread`, and `-fsanitize=undefined` which are all disabled by default. These flags are useful for developers who wish to do additional safety checking. Note that some of these are mutually incompatible, and these may have a large performance overhead. There's some kind of strange logic required to properly check for the availability of these flags in a way that works on both GCC and Clang, hopefully the comments make it clear what's going on. Tree-SHA512: 2d6fe402799110e59ee452dddf37f7ca2d26a7fecec50be25c8a134e4a20beb31f1e8f438dffd443641562418075896d1eeb450623425b272d80e05e3027a587 --- configure.ac | 28 +++++++++++++++++++++++ doc/developer-notes.md | 51 ++++++++++++++++++++++++++++++++++++++++++ src/Makefile.am | 4 ++-- 3 files changed, 81 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index faa05eb4e3..fb75e6c622 100644 --- a/configure.ac +++ b/configure.ac @@ -238,6 +238,12 @@ if test "x$enable_miner" = xyes; then AC_DEFINE(ENABLE_MINER, 1, [Define this symbol if in-wallet miner should be enabled]) fi +# Enable different -fsanitize options +AC_ARG_WITH([sanitizers], + [AS_HELP_STRING([--with-sanitizers], + [comma separated list of extra sanitizers to build with (default is none enabled)])], + [use_sanitizers=$withval]) + # Enable gprof profiling AC_ARG_ENABLE([gprof], [AS_HELP_STRING([--enable-gprof], @@ -291,6 +297,26 @@ fi # Needed for MinGW targets when debug symbols are enabled as compiled objects get very large AX_CHECK_COMPILE_FLAG([-Wa,-mbig-obj], [CXXFLAGS="$CXXFLAGS -Wa,-mbig-obj"],,,) +if test x$use_sanitizers != x; then + # First check if the compiler accepts flags. If an incompatible pair like + # -fsanitize=address,thread is used here, this check will fail. This will also + # fail if a bad argument is passed, e.g. -fsanitize=undfeined + AX_CHECK_COMPILE_FLAG( + [[-fsanitize=$use_sanitizers]], + [[SANITIZER_CXXFLAGS=-fsanitize=$use_sanitizers]], + [AC_MSG_ERROR([compiler did not accept requested flags])]) + + # Some compilers (e.g. GCC) require additional libraries like libasan, + # libtsan, libubsan, etc. Make sure linking still works with the sanitize + # flag. This is a separate check so we can give a better error message when + # the sanitize flags are supported by the compiler but the actual sanitizer + # libs are missing. + AX_CHECK_LINK_FLAG( + [[-fsanitize=$use_sanitizers]], + [[SANITIZER_LDFLAGS=-fsanitize=$use_sanitizers]], + [AC_MSG_ERROR([linker did not accept requested flags, you are missing required libraries])]) +fi + ERROR_CXXFLAGS= if test "x$enable_werror" = "xyes"; then if test "x$CXXFLAG_WERROR" = "x"; then @@ -1415,6 +1441,8 @@ AC_SUBST(HARDENED_CPPFLAGS) AC_SUBST(HARDENED_LDFLAGS) AC_SUBST(PIC_FLAGS) AC_SUBST(PIE_FLAGS) +AC_SUBST(SANITIZER_CXXFLAGS) +AC_SUBST(SANITIZER_LDFLAGS) AC_SUBST(SSE42_CXXFLAGS) AC_SUBST(SSE41_CXXFLAGS) AC_SUBST(AVX2_CXXFLAGS) diff --git a/doc/developer-notes.md b/doc/developer-notes.md index af41526e15..89cab1f2f3 100644 --- a/doc/developer-notes.md +++ b/doc/developer-notes.md @@ -246,6 +246,57 @@ make cov # A coverage report will now be accessible at `./test_dash.coverage/index.html`. ``` +**Sanitizers** + +Bitcoin can be compiled with various "sanitizers" enabled, which add +instrumentation for issues regarding things like memory safety, thread race +conditions, or undefined behavior. This is controlled with the +`--with-sanitizers` configure flag, which should be a comma separated list of +sanitizers to enable. The sanitizer list should correspond to supported +`-fsanitize=` options in your compiler. These sanitizers have runtime overhead, +so they are most useful when testing changes or producing debugging builds. + +Some examples: + +```bash +# Enable both the address sanitizer and the undefined behavior sanitizer +./configure --with-sanitizers=address,undefined + +# Enable the thread sanitizer +./configure --with-sanitizers=thread +``` + +If you are compiling with GCC you will typically need to install corresponding +"san" libraries to actually compile with these flags, e.g. libasan for the +address sanitizer, libtsan for the thread sanitizer, and libubsan for the +undefined sanitizer. If you are missing required libraries, the configure script +will fail with a linker error when testing the sanitizer flags. + +The test suite should pass cleanly with the `thread` and `undefined` sanitizers, +but there are a number of known problems when using the `address` sanitizer. The +address sanitizer is known to fail in +[sha256_sse4::Transform](/src/crypto/sha256_sse4.cpp) which makes it unusable +unless you also use `--disable-asm` when running configure. We would like to fix +sanitizer issues, so please send pull requests if you can fix any errors found +by the address sanitizer (or any other sanitizer). + +Not all sanitizer options can be enabled at the same time, e.g. trying to build +with `--with-sanitizers=address,thread` will fail in the configure script as +these sanitizers are mutually incompatible. Refer to your compiler manual to +learn more about these options and which sanitizers are supported by your +compiler. + +Additional resources: + + * [AddressSanitizer](https://clang.llvm.org/docs/AddressSanitizer.html) + * [LeakSanitizer](https://clang.llvm.org/docs/LeakSanitizer.html) + * [MemorySanitizer](https://clang.llvm.org/docs/MemorySanitizer.html) + * [ThreadSanitizer](https://clang.llvm.org/docs/ThreadSanitizer.html) + * [UndefinedBehaviorSanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html) + * [GCC Instrumentation Options](https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html) + * [Google Sanitizers Wiki](https://github.com/google/sanitizers/wiki) + * [Issue #12691: Enable -fsanitize flags in Travis](https://github.com/bitcoin/bitcoin/issues/12691) + Locking/mutex usage notes ------------------------- diff --git a/src/Makefile.am b/src/Makefile.am index 3c04c3aead..813a97cf83 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -5,8 +5,8 @@ DIST_SUBDIRS = secp256k1 univalue -AM_LDFLAGS = $(PTHREAD_CFLAGS) $(LIBTOOL_LDFLAGS) $(HARDENED_LDFLAGS) $(GPROF_LDFLAGS) -AM_CXXFLAGS = $(HARDENED_CXXFLAGS) $(ERROR_CXXFLAGS) $(GPROF_CXXFLAGS) +AM_LDFLAGS = $(PTHREAD_CFLAGS) $(LIBTOOL_LDFLAGS) $(HARDENED_LDFLAGS) $(GPROF_LDFLAGS) $(SANITIZER_LDFLAGS) +AM_CXXFLAGS = $(HARDENED_CXXFLAGS) $(ERROR_CXXFLAGS) $(GPROF_CXXFLAGS) $(SANITIZER_CXXFLAGS) AM_CPPFLAGS = $(HARDENED_CPPFLAGS) AM_LIBTOOLFLAGS = --preserve-dup-deps EXTRA_LIBRARIES =