Add --enable-asan configure option
authorSimon Marchi <simon.marchi@efficios.com>
Fri, 14 May 2021 14:23:19 +0000 (10:23 -0400)
committerMichael Jeanson <mjeanson@efficios.com>
Fri, 12 Nov 2021 18:40:01 +0000 (13:40 -0500)
It's possible to build babeltrace with AddressSanitizer by adding
-fsanitize=address to CFLAGS/LDFLAGS, but it causes some issues.  These
issues are related to the fact that if libasan.so is to be loaded, it
must be the first library to be loaded.  When a Python interpreter loads
the bt2 module, that pulls in libbabeltrace2.so, which pulls libasan.so.
libasan.so then complains about not being the first loaded libraries.
The only way I know to fix this is to LD_PRELOAD libasan.so in the
Python interpreter.

The first case where this happens is when building the Python bindings.
This is because the Sphinx tool (so, the Python interpreter) loads the
bt2 Python module in order to obtain the documentation.

The other case is when running the Python bindings tests, the test
runner is in Python, and the .py tests imports the bt2 module.

In both cases, libasan unfortunately finds some leaks in the Python
interpreter.  We must therefore disable leak reporting with
ASAN_OPTIONS=detect_leaks=0.  This is particularly unfortunate for the
Python bindings tests, because it would be nice to know about leaks that
are libbabeltrace2's or the tests' fault.  But I don't see any way
around it.  For running Sphinx, we don't care about leaks.

Since we need to set some special environment variables when building
and checking if AddressSanitizer is used, it's much easier if the build
system knows that we want to use AddressSanitizer.  This patch therefore
adds a new `--enable-asan` option that developers should use in order to
use AddressSanitizer, instead of manually adding -fsanitize=address in
CFLAGS/LDFLAGS.

If `--enable-asan` is used, the following command will be invoked :

  $(CC) -print-file-name=libasan.so

... to find the path of the libasan.so library associated to the
compiler being used (it's important that we pre-load the right version
of libasan.so).

For the Python bindings documentation generation, the command is used in
the Makefile where Sphinx is invoked.

For tests, a boolean is written in a generated tests/utils/env.sh file,
which is sourced by tests/utils/utils.sh and the command is then used
when running the tests.

Change-Id: I5e0ca10532605cfdfda08b3ee4fcc39922480797
Signed-off-by: Simon Marchi <simon.marchi@efficios.com>
Reviewed-on: https://review.lttng.org/c/babeltrace/+/5860
Tested-by: jenkins <jenkins@lttng.org>
Reviewed-by: Michael Jeanson <mjeanson@efficios.com>
15 files changed:
configure.ac
doc/bindings/python/Makefile.am
src/bindings/python/bt2/Makefile.am
src/cli/Makefile.am
src/compat/Makefile.am
src/ctf-writer/Makefile.am
src/lib/Makefile.am
src/plugins/ctf/Makefile.am
src/plugins/lttng-utils/Makefile.am
src/plugins/text/Makefile.am
src/plugins/utils/Makefile.am
src/python-plugin-provider/Makefile.am
tests/lib/test-plugin-plugins/Makefile.am
tests/utils/env.sh.in
tests/utils/utils.sh

index 673fd7209523d66785ce18eddc917d3d1307f4f3..85f422a11af946a6dc443ab737e16e1654fda187 100644 (file)
@@ -409,6 +409,9 @@ AE_FEATURE([man-pages],[Do not build and install man pages (already built in a d
 AE_FEATURE_DEFAULT_DISABLE
 AE_FEATURE([Werror],[Treat compiler warnings as errors.])
 
+# When given, build with AddressSanitizer.
+AE_FEATURE_DEFAULT_DISABLE
+AE_FEATURE([asan],[Build with AddressSanitizer.])
 
 ##                                          ##
 ## Check for conflicting features selection ##
@@ -459,6 +462,7 @@ AM_CONDITIONAL([ENABLE_BUILT_IN_PLUGINS], AE_IS_FEATURE_ENABLED([built-in-plugin
 AM_CONDITIONAL([ENABLE_BUILT_IN_PYTHON_PLUGIN_SUPPORT], AE_IS_FEATURE_ENABLED([built-in-python-plugin-support]))
 AM_CONDITIONAL([ENABLE_MAN_PAGES], AE_IS_FEATURE_ENABLED([man-pages]))
 AM_CONDITIONAL([ENABLE_PYTHON_COMMON_DEPS], AE_IS_FEATURE_ENABLED([python-bindings]) || AE_IS_FEATURE_ENABLED([python-plugins]))
+AM_CONDITIONAL([ENABLE_ASAN], AE_IS_FEATURE_ENABLED([asan]))
 
 
 ##                                                                     ##
@@ -476,6 +480,8 @@ AE_IF_FEATURE_ENABLED([built-in-python-plugin-support],
 AE_IF_FEATURE_ENABLED([debug-info], [ENABLE_DEBUG_INFO_VAL=1], [ENABLE_DEBUG_INFO_VAL=0])
 AC_SUBST([ENABLE_DEBUG_INFO_VAL])
 
+AE_IF_FEATURE_ENABLED([asan], [ENABLE_ASAN=1], [ENABLE_ASAN=0])
+AC_SUBST([ENABLE_ASAN])
 
 ##                                           ##
 ## Check for optionnal features dependencies ##
@@ -634,13 +640,21 @@ AS_IF([test "x$exec_prefix" = xNONE], [
 
 AC_SUBST(LIBDIR)
 
+# If --enable-asan is used...
+AE_IF_FEATURE_ENABLED([asan], [
+  # ... add -fsanitize=address to the *FLAGS variables.
+  ASAN_CFLAGS="-fsanitize=address"
+  ASAN_CXXFLAGS="-fsanitize=address"
+  ASAN_LDFLAGS="-fsanitize=address"
+])
 
 
 
 # CFLAGS from libraries (the glib ones are needed for the following sizeof
 # test).
-AM_CFLAGS="${PTHREAD_CFLAGS} ${GLIB_CFLAGS}"
-AM_CXXFLAGS="${PTHREAD_CFLAGS} ${GLIB_CFLAGS}"
+AM_CFLAGS="${PTHREAD_CFLAGS} ${GLIB_CFLAGS} ${ASAN_CFLAGS}"
+AM_CXXFLAGS="${PTHREAD_CFLAGS} ${GLIB_CFLAGS} ${ASAN_CXXFLAGS}"
+AM_LDFLAGS="${ASAN_LDFLAGS}"
 
 # Check that the current size_t matches the size that glib thinks it should
 # be. This catches problems on multi-arch where people try to do a 32-bit
@@ -742,9 +756,10 @@ WARN_CFLAGS="${WARN_CFLAGS} -Wold-style-definition -Wstrict-prototypes"
 AM_CXXFLAGS="${AM_CXXFLAGS} ${WARN_CXXFLAGS}"
 AM_CFLAGS="${AM_CFLAGS} ${WARN_CFLAGS}"
 
-# Done for AM_CXXFLAGS and AM_CFLAGS.
+# Done for AM_CXXFLAGS, AM_CFLAGS and AM_LDFLAGS.
 AC_SUBST(AM_CXXFLAGS)
 AC_SUBST(AM_CFLAGS)
+AC_SUBST(AM_LDFLAGS)
 
 # Set global CPPFLAGS in AM_CPPFLAGS
 AM_CPPFLAGS="-I\$(top_srcdir)/include -I\$(top_builddir)/src -I\$(top_srcdir)/src -include common/config.h"
index f5d8490a8610ca5069bd9ff522d7735b0c728fde..a552196782808ee1bb9b6909dc58b6e32e007c54 100644 (file)
@@ -14,12 +14,30 @@ PYTHON_BT2_BUILD_LIB_DIR = $(abs_top_builddir)/src/bindings/python/bt2/build/bui
 PP = $(PYTHON_BT2_BUILD_LIB_DIR)
 LLP = $(abs_top_builddir)/src/lib/.libs
 
+# Sphinx loads the bt2 Python module and thus libbabeltrace2.so.  If
+# AddressSanitizer is used, we must preload libasan.so so that libasan doesn't
+# complain about not being the first loaded library.
+#
+# Python produces some leaks, so disable leak detection (we don't care about
+# leaks here anyway).
+if ENABLE_ASAN
+MAYBE_LD_PRELOAD = LD_PRELOAD="$$($(CC) -print-file-name=libasan.so):$(LD_PRELOAD)"
+MAYBE_ASAN_OPTIONS = ASAN_OPTIONS="$(ASAN_OPTIONS),detect_leaks=0"
+endif
+
 # `PATH` is used as a replacement for `LD_LIBRARY_PATH` on Windows
 # builds (Cygwin, MinGW).
 #
 # `DYLD_LIBRARY_PATH` is used a replacement for `LD_LIBRARY_PATH` on
 # macOS builds.
-SPHINXBUILD = PATH="$(LLP):$$PATH" PYTHONPATH="$(PP):$(SPHINX_EXT_DIR)" LD_LIBRARY_PATH="$(LLP)" DYLD_LIBRARY_PATH="$(LLP)" $(PYTHON) -m sphinx
+SPHINXBUILD = \
+       PATH="$(LLP):$$PATH" \
+       PYTHONPATH="$(PP):$(SPHINX_EXT_DIR)" \
+       LD_LIBRARY_PATH="$(LLP)" \
+       DYLD_LIBRARY_PATH="$(LLP)" \
+       $(MAYBE_LD_PRELOAD) \
+       $(MAYBE_ASAN_OPTIONS) \
+       $(PYTHON) -m sphinx
 SPHINX_SRC = \
        $(SPHINX_SOURCE_DIR)/common.rst \
        $(SPHINX_SOURCE_DIR)/index.rst \
index ec30c005c91468215470cc9306cfdad23809099f..c8e3eb44ae99e391fba19fccd46b1d7048a00a9a 100644 (file)
@@ -3,7 +3,7 @@
 # Since the shared object used by the python bindings is not built with
 # libtool, we need to add the directory containing libbabeltrace2 to the
 # linker path.
-AM_LDFLAGS=-L$(top_builddir)/src/lib/.libs
+AM_LDFLAGS += -L$(top_builddir)/src/lib/.libs
 
 INSTALLED_FILES=$(builddir)/installed_files.txt
 
index bfe868a18d23b3d953f428cae9fc3376e578bd5c..2428b489e62d6a9e320c05ec91ebd759ed5a2175 100644 (file)
@@ -44,7 +44,7 @@ babeltrace2_bin_SOURCES = \
 # -Wl,--no-as-needed is needed for recent gold linker who seems to think
 # it knows better and considers libraries with constructors having
 # side-effects as dead code.
-babeltrace2_bin_LDFLAGS = $(LD_NO_AS_NEEDED)
+babeltrace2_bin_LDFLAGS = $(AM_LDFLAGS) $(LD_NO_AS_NEEDED)
 
 # Add all the convenience libraries used by Babeltrace plugins and the
 # library. They will be used when embedding plugins (--enable-built-in-plugins),
index 8a3908d030af49eb8275e5627e5e02786f45c698..c857372a017801b5d270dffd04bbd019cdde74d9 100644 (file)
@@ -7,6 +7,7 @@ libcompat_la_SOURCES = \
        mman.h
 
 libcompat_la_LDFLAGS = \
+       $(AM_LDFLAGS) \
        $(LD_NO_AS_NEEDED)
 
 noinst_HEADERS = \
index 6e05b8d5a9ed99f35d88a58b5527f0d132fbacaf..2e979b012351b3b1a597d125d3fd3104208f628a 100644 (file)
@@ -49,8 +49,10 @@ libbabeltrace2_ctf_writer_la_SOURCES = \
        writer.c \
        writer.h
 
-libbabeltrace2_ctf_writer_la_LDFLAGS = $(LT_NO_UNDEFINED) \
-                       -version-info $(BABELTRACE_LIBRARY_VERSION)
+libbabeltrace2_ctf_writer_la_LDFLAGS = \
+       $(AM_LDFLAGS) \
+       $(LT_NO_UNDEFINED) \
+       -version-info $(BABELTRACE_LIBRARY_VERSION)
 
 libbabeltrace2_ctf_writer_la_LIBADD = \
        $(top_builddir)/src/logging/libbabeltrace2-logging.la \
index c636762612bd34f0eec09a8724eb40cef4b2b18e..a91138103b43c3d40592e38255ab67c1e3fb7314 100644 (file)
@@ -26,8 +26,10 @@ libbabeltrace2_la_SOURCES = \
        value.c \
        value.h
 
-libbabeltrace2_la_LDFLAGS = $(LT_NO_UNDEFINED) \
-                       -version-info $(BABELTRACE_LIBRARY_VERSION)
+libbabeltrace2_la_LDFLAGS = \
+       $(AM_LDFLAGS) \
+       $(LT_NO_UNDEFINED) \
+       -version-info $(BABELTRACE_LIBRARY_VERSION)
 
 libbabeltrace2_la_LIBADD = \
        prio-heap/libprio-heap.la \
index 104229d2de37844186007656791ce5959b9ced83..24a434011501ac47dfbf4ba5b053be65e46a9b22 100644 (file)
@@ -12,6 +12,7 @@ plugin_LTLIBRARIES = babeltrace-plugin-ctf.la
 babeltrace_plugin_ctf_la_SOURCES = plugin.c
 
 babeltrace_plugin_ctf_la_LDFLAGS = \
+       $(AM_LDFLAGS) \
        $(LT_NO_UNDEFINED) \
        -avoid-version -module $(LD_NOTEXT)
 
index d01e36fac376982e90aaa8fb8337b33c74b90d71..0beeadf2d38e38a4d5e6922117990f3763106efa 100644 (file)
@@ -17,6 +17,7 @@ babeltrace_plugin_lttng_utils_la_SOURCES = \
        plugin.c
 
 babeltrace_plugin_lttng_utils_la_LDFLAGS = \
+       $(AM_LDFLAGS) \
        $(LT_NO_UNDEFINED) \
        -avoid-version -module $(LD_NOTEXT) \
        $(ELFUTILS_LIBS)
index 9d8ed88dd84ab00391df49789c847ff04f636702..9e69ad8016aed8bc38eee57dab8f88459a7b4dc8 100644 (file)
@@ -7,6 +7,7 @@ plugin_LTLIBRARIES = babeltrace-plugin-text.la
 
 babeltrace_plugin_text_la_SOURCES = plugin.c
 babeltrace_plugin_text_la_LDFLAGS = \
+       $(AM_LDFLAGS) \
        $(LT_NO_UNDEFINED) \
        -avoid-version -module $(LD_NOTEXT)
 
index 5cacc96191bb0f4714ce7402cfc49dd7de5a331a..71881317277c92c8e9a217740caf1ffe83ad931e 100644 (file)
@@ -7,6 +7,7 @@ plugin_LTLIBRARIES = babeltrace-plugin-utils.la
 
 babeltrace_plugin_utils_la_SOURCES = plugin.c
 babeltrace_plugin_utils_la_LDFLAGS = \
+       $(AM_LDFLAGS) \
        $(LT_NO_UNDEFINED) \
        -avoid-version -module $(LD_NOTEXT)
 babeltrace_plugin_utils_la_LIBADD = \
index 822e5534296672ddc293a44b9a43ce10ef480130..3d3a11fea09663a1c537c4b28cce55cc23098e80 100644 (file)
@@ -11,6 +11,7 @@ babeltrace2_python_plugin_provider_la_SOURCES = \
        python-plugin-provider.h
 
 babeltrace2_python_plugin_provider_la_LDFLAGS = \
+       $(AM_LDFLAGS) \
        $(LT_NO_UNDEFINED) \
        -avoid-version -module \
        $(PYTHON_LDFLAGS)
index 62e48f7e17f241d4a221b365c2e221f740638871..4725a564969f458c1444f91fbb3d060e0791710e 100644 (file)
@@ -5,6 +5,7 @@ noinst_LTLIBRARIES = plugin-minimal.la plugin-sfs.la
 # the minimal plugin
 plugin_minimal_la_SOURCES = minimal.c
 plugin_minimal_la_LDFLAGS = \
+       $(AM_LDFLAGS) \
        $(LT_NO_UNDEFINED) \
        -rpath / -avoid-version -module $(LD_NOTEXT)
 plugin_minimal_la_LIBADD = \
@@ -15,6 +16,7 @@ plugin_minimal_la_LIBADD = \
 # source/filter/sink plugin
 plugin_sfs_la_SOURCES = sfs.c
 plugin_sfs_la_LDFLAGS = \
+       $(AM_LDFLAGS) \
        $(LT_NO_UNDEFINED) \
        -rpath / -avoid-version -module $(LD_NOTEXT)
 plugin_sfs_la_LIBADD = \
index af34046b822ca250d0564e8e27109bcea5b725c9..96f4fc0995b3e5526457e03e7d9ecedcc20c0fd3 100644 (file)
@@ -40,3 +40,16 @@ if [ "x${BT_TESTS_SED_BIN:-}" = "x" ]; then
        BT_TESTS_SED_BIN="@SED@"
 fi
 export BT_TESTS_SED_BIN
+
+if [ "x${BT_TESTS_CC_BIN:-}" = "x" ]; then
+       BT_TESTS_CC_BIN="@CC@"
+fi
+export BT_TESTS_CC_BIN
+
+
+### Optional features ###
+
+if [ "x${BT_TESTS_ENABLE_ASAN:-}" = "x" ]; then
+       BT_TESTS_ENABLE_ASAN="@ENABLE_ASAN@"
+fi
+export BT_TESTS_ENABLE_ASAN
index 9d9b639b4278965a9779c42372066c7a2982d4a8..3cbea1609d07666d0c046e65fe726422b35a7f37 100644 (file)
@@ -121,6 +121,19 @@ if [ "x${BT_TESTS_SED_BIN:-}" = "x" ]; then
 fi
 export BT_TESTS_SED_BIN
 
+if [ "x${BT_TESTS_CC_BIN:-}" = "x" ]; then
+       BT_TESTS_CC_BIN="cc"
+fi
+export BT_TESTS_CC_BIN
+
+
+### Optional features ###
+
+if [ "x${BT_TESTS_ENABLE_ASAN:-}" = "x" ]; then
+       BT_TESTS_ENABLE_ASAN="0"
+fi
+export BT_TESTS_ENABLE_ASAN
+
 
 # Data files path
 BT_TESTS_DATADIR="${BT_TESTS_SRCDIR}/data"
@@ -293,6 +306,7 @@ check_coverage() {
 # bt2 Python bindings.
 run_python_bt2() {
        local env_args
+       local lib_asan
 
        env_args=(
                "BABELTRACE_PYTHON_BT2_NO_TRACEBACK=1" \
@@ -322,6 +336,20 @@ run_python_bt2() {
                env_args+=("PYTHONHOME=$($BT_TESTS_PYTHON_CONFIG_BIN --prefix)")
        fi
 
+       # If AddressSanitizer is used, we must preload libasan.so so that
+       # libasan doesn't complain about not being the first loaded library.
+       #
+       # Python and sed (executed as part of the libtool wrapper) produce some
+       # leaks, so we must unfortunately disable leak detection.  Append it to
+       # existing ASAN_OPTIONS, such that we override the user's value if it
+       # contains detect_leaks=1.
+       if [ "x${BT_TESTS_ENABLE_ASAN:-}" = "x1" ]; then
+               lib_asan=$(${BT_TESTS_CC_BIN} -print-file-name=libasan.so)
+
+               env_args+=("LD_PRELOAD=${lib_asan}:${LD_PRELOAD:-}")
+               env_args+=("ASAN_OPTIONS=${ASAN_OPTIONS:-},detect_leaks=0")
+       fi
+
        env "${env_args[@]}" "$@"
 }
 
This page took 0.045228 seconds and 4 git commands to generate.