Bug 1233568: Add support for building with Address Sanitizer. r=wtc.
authorJed Davis <jld@mozilla.com>
Sat, 27 Feb 2016 14:05:04 -0800
changeset 11950 47879a76b71a4cd7f3cd443480db7d2f26f38b18
parent 11949 aee88368c8c13ac700be24fb54b07e039c9d0796
child 11951 a61e85d5a3676dbb05f194c735352243c2f89dc5
push id1027
push userwtc@google.com
push dateSat, 27 Feb 2016 22:05:11 +0000
reviewerswtc
bugs1233568
Bug 1233568: Add support for building with Address Sanitizer. r=wtc. This is controlled by setting USE_ASAN=1 when building. Like the other build flags, it must also be set while testing.
Makefile
coreconf/Darwin.mk
coreconf/Linux.mk
coreconf/sanitizers.mk
tests/all.sh
tests/common/init.sh
--- a/Makefile
+++ b/Makefile
@@ -78,17 +78,26 @@ NSPR_CONFIGURE_OPTS += --enable-win32-ta
 endif
 ifdef USE_DEBUG_RTL
 NSPR_CONFIGURE_OPTS += --enable-debug-rtl
 endif
 ifdef USE_STATIC_RTL
 NSPR_CONFIGURE_OPTS += --enable-static-rtl
 endif
 ifdef NS_USE_GCC
-NSPR_COMPILERS = CC=gcc CXX=g++
+NSPR_CONFIGURE_ENV = CC=gcc CXX=g++
+endif
+
+ifdef SANITIZER_CFLAGS
+ifdef BUILD_OPT
+NSPR_CONFIGURE_OPTS += --enable-debug-symbols
+endif
+NSPR_CONFIGURE_ENV += CFLAGS='$(SANITIZER_CFLAGS)' \
+                      CXXFLAGS='$(SANITIZER_CFLAGS)' \
+                      LDFLAGS='$(SANITIZER_LFLAGS)'
 endif
 
 #
 # Some pwd commands on Windows (for example, the pwd
 # command in Cygwin) return a pathname that begins
 # with a (forward) slash.  When such a pathname is
 # passed to Windows build tools (for example, cl), it
 # is mistaken as a command-line option.  If that is the case,
@@ -105,17 +114,17 @@ ifeq ($(USEABSPATH),"YES")
 NSPR_PREFIX = $(shell pwd)/../dist/$(OBJDIR_NAME)
 else
 NSPR_PREFIX = $$(topsrcdir)/../dist/$(OBJDIR_NAME)
 endif
 
 $(NSPR_CONFIG_STATUS): $(NSPR_CONFIGURE)
 	mkdir -p $(CORE_DEPTH)/../nspr/$(OBJDIR_NAME)
 	cd $(CORE_DEPTH)/../nspr/$(OBJDIR_NAME) ; \
-	$(NSPR_COMPILERS) sh ../configure \
+	$(NSPR_CONFIGURE_ENV) sh ../configure \
 	$(NSPR_CONFIGURE_OPTS) \
 	--with-dist-prefix='$(NSPR_PREFIX)' \
 	--with-dist-includedir='$(NSPR_PREFIX)/include'
 
 build_nspr: $(NSPR_CONFIG_STATUS)
 	$(MAKE) -C $(CORE_DEPTH)/../nspr/$(OBJDIR_NAME)
 
 clobber_nspr: $(NSPR_CONFIG_STATUS)
--- a/coreconf/Darwin.mk
+++ b/coreconf/Darwin.mk
@@ -131,8 +131,11 @@ SYS_SQLITE3_VERSION_MINOR := $(shell ech
 
 ifeq (3,$(SYS_SQLITE3_VERSION_MAJOR))
     ifeq (,$(filter-out 0 1 2 3 4,$(SYS_SQLITE3_VERSION_MINOR)))
         # sqlite <= 3.4.x is too old, it doesn't provide sqlite3_file_control
     else
         NSS_USE_SYSTEM_SQLITE = 1
     endif
 endif
+
+include $(CORE_DEPTH)/coreconf/sanitizers.mk
+DARWIN_SDK_SHLIBFLAGS += $(SANITIZER_FLAGS)
--- a/coreconf/Linux.mk
+++ b/coreconf/Linux.mk
@@ -148,18 +148,22 @@ endif
 
 ARCH			= linux
 
 DSO_CFLAGS		= -fPIC
 DSO_LDOPTS		= -shared $(ARCHFLAG) -Wl,--gc-sections
 # The linker on Red Hat Linux 7.2 and RHEL 2.1 (GNU ld version 2.11.90.0.8)
 # incorrectly reports undefined references in the libraries we link with, so
 # we don't use -z defs there.
+# Also, -z defs conflicts with Address Sanitizer, which emits relocations
+# against the libsanitizer runtime built into the main executable.
 ZDEFS_FLAG		= -Wl,-z,defs
+ifneq ($(USE_ASAN),1)
 DSO_LDOPTS		+= $(if $(findstring 2.11.90.0.8,$(shell ld -v)),,$(ZDEFS_FLAG))
+endif
 LDFLAGS			+= $(ARCHFLAG)
 
 # On Maemo, we need to use the -rpath-link flag for even the standard system
 # library directories.
 ifdef _SBOX_DIR
 LDFLAGS			+= -Wl,-rpath-link,/usr/lib:/lib
 endif
 
@@ -205,8 +209,10 @@ ifdef MAPFILE
 	MKSHLIB += -Wl,--version-script,$(MAPFILE)
 endif
 PROCESS_MAP_FILE = grep -v ';-' $< | \
         sed -e 's,;+,,' -e 's; DATA ;;' -e 's,;;,,' -e 's,;.*,;,' > $@
 
 ifeq ($(OS_RELEASE),2.4)
 DEFINES += -DNO_FORK_CHECK
 endif
+
+include $(CORE_DEPTH)/coreconf/sanitizers.mk
new file mode 100644
--- /dev/null
+++ b/coreconf/sanitizers.mk
@@ -0,0 +1,19 @@
+# Address Sanitizer support; include this in OS-specific .mk files
+# *after* defining the variables that are appended to here.
+
+ifeq ($(USE_ASAN), 1)
+SANITIZER_FLAGS_COMMON = -fsanitize=address $(EXTRA_SANITIZER_FLAGS)
+SANITIZER_CFLAGS = $(SANITIZER_FLAGS_COMMON)
+SANITIZER_LFLAGS = $(SANITIZER_FLAGS_COMMON)
+OS_CFLAGS += $(SANITIZER_CFLAGS)
+LDFLAGS += $(SANITIZER_LFLAGS)
+
+# ASan needs frame pointers to save stack traces for allocation/free sites.
+# (Warning: some platforms, like ARM Linux in Thumb mode, don't have useful
+# frame pointers even with this option.)
+SANITIZER_CFLAGS += -fno-omit-frame-pointer
+
+# You probably want to be able to get debug info for failures, even with an
+# optimized build.
+OPTIMIZER += -g
+endif
--- a/tests/all.sh
+++ b/tests/all.sh
@@ -54,16 +54,17 @@
 # -----------------------------------------------------------
 #   HOST         - test machine host name
 #   DOMSUF       - test machine domain name
 #
 # Optional environment variables to specify build to use:
 # -------------------------------------------------------
 #   BUILT_OPT    - use optimized/debug build
 #   USE_64       - use 64bit/32bit build
+#   USE_ASAN     - use Address Sanitizer build
 #
 # Optional environment variables to enable specific NSS features:
 # ---------------------------------------------------------------
 #   NSS_DISABLE_ECC             - disable ECC
 #   NSS_ECC_MORE_THAN_SUITE_B   - enable extended ECC
 #
 # Optional environment variables to select which cycles/suites to test:
 # ---------------------------------------------------------------------
--- a/tests/common/init.sh
+++ b/tests/common/init.sh
@@ -39,16 +39,20 @@
 #    network. Also, this way all scripts have all shell function  available
 #    and a completely common environment
 #
 ########################################################################
 
 NSS_STRICT_SHUTDOWN=1
 export NSS_STRICT_SHUTDOWN
 
+# If using ASan, disable LSan; see bug 1246801.
+ASAN_OPTIONS="detect_leaks=0${ASAN_OPTIONS:+,$ASAN_OPTIONS}"
+export ASAN_OPTIONS
+
 # Init directories based on HOSTDIR variable
 if [ -z "${INIT_SOURCED}" -o "${INIT_SOURCED}" != "TRUE" ]; then
     init_directories()
     {
         TMP=${HOSTDIR}      #TMP=${TMP-/tmp}
         TEMP=${TMP}
         TMPDIR=${TMP}