Add support for building with -fsanitize=undefined.
- add configure option --enable-ubsan 
- add __ubsan helpers (by Julian)

This requires gcc 4.9.2 or later. Not all platforms are supported, though.
With this change and VEX r3099 regression tests pass on amd64
with a valgrind compiled with -fsanitize=undefined.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@14995 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/Makefile.all.am b/Makefile.all.am
index 3b2772a..860ef90 100644
--- a/Makefile.all.am
+++ b/Makefile.all.am
@@ -111,6 +111,7 @@
 	@FLAG_W_FORMAT@ \
 	@FLAG_W_FORMAT_SECURITY@ \
 	@FLAG_FNO_STACK_PROTECTOR@ \
+	@FLAG_FSANITIZE@ \
 	-fno-strict-aliasing \
 	-fno-builtin
 
diff --git a/auxprogs/Makefile.am b/auxprogs/Makefile.am
index c3c67a4..89ca89b 100644
--- a/auxprogs/Makefile.am
+++ b/auxprogs/Makefile.am
@@ -72,7 +72,7 @@
 getoff_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CPPFLAGS  = $(AM_CPPFLAGS_@VGCONF_PLATFORM_PRI_CAPS@)
 getoff_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CFLAGS    = $(AM_CFLAGS_@VGCONF_PLATFORM_PRI_CAPS@)
 getoff_@VGCONF_ARCH_PRI@_@VGCONF_OS@_CCASFLAGS = $(AM_CCASFLAGS_PRI)
-getoff_@VGCONF_ARCH_PRI@_@VGCONF_OS@_LDFLAGS   = $(AM_CFLAGS_PRI)
+getoff_@VGCONF_ARCH_PRI@_@VGCONF_OS@_LDFLAGS   = $(AM_CFLAGS_PRI) @LIB_UBSAN@
 if HAVE_DLINFO_RTLD_DI_TLS_MODID
 getoff_@VGCONF_ARCH_PRI@_@VGCONF_OS@_LDADD = $(LDADD) -ldl
 endif
diff --git a/configure.ac b/configure.ac
index ebb0798..e731af9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -827,6 +827,16 @@
     VALT_LOAD_ADDRESS_SEC=$valt_load_address_sec_norml
 fi
 
+#----------------------------------------------------------------------------
+# Undefined behaviour sanitiser
+#----------------------------------------------------------------------------
+# Check whether we should build with the undefined beahviour sanitiser.
+
+AC_CACHE_CHECK([for using the undefined behaviour sanitiser], vg_cv_ubsan,
+   [AC_ARG_ENABLE(ubsan, 
+      [  --enable-ubsan          enables the undefined behaviour sanitiser],
+      [vg_cv_ubsan=$enableval],
+      [vg_cv_ubsan=no])])
 
 #----------------------------------------------------------------------------
 # Define MIPS_PAGE_SHIFT (--with-pagesize)
@@ -1777,6 +1787,28 @@
 
 AC_SUBST(FLAG_FNO_STACK_PROTECTOR)
 
+
+# Does this compiler support -fsanitize=undefined?
+# Only checked for if --enable-ubsan was given.
+if test "x${vg_cv_ubsan}" = "xyes"; then
+AC_MSG_CHECKING([if gcc accepts -fsanitize=undefined])
+safe_CFLAGS=$CFLAGS
+CFLAGS="-fsanitize=undefined"
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[
+  return 0;
+]])], [
+FLAG_FSANITIZE="-fsanitize=undefined"
+LIB_UBSAN="-static-libubsan"
+AC_MSG_RESULT([yes])
+], [
+FLAG_FSANITIZE=""
+LIB_UBSAN=""
+AC_MSG_RESULT([no])
+])
+CFLAGS=$safe_CFLAGS
+AC_SUBST(FLAG_FSANITIZE)
+AC_SUBST(LIB_UBSAN)
+fi
 # does this compiler support --param inline-unit-growth=... ?
 
 AC_MSG_CHECKING([if gcc accepts --param inline-unit-growth])
diff --git a/coregrind/Makefile.am b/coregrind/Makefile.am
index 64e1459..d07be73 100644
--- a/coregrind/Makefile.am
+++ b/coregrind/Makefile.am
@@ -48,7 +48,7 @@
 valgrind_CPPFLAGS  = $(AM_CPPFLAGS_PRI)
 valgrind_CFLAGS    = $(AM_CFLAGS_PRI)
 valgrind_CCASFLAGS = $(AM_CCASFLAGS_PRI)
-valgrind_LDFLAGS   = $(AM_CFLAGS_PRI)
+valgrind_LDFLAGS   = $(AM_CFLAGS_PRI) @LIB_UBSAN@
 if VGCONF_PLATFORMS_INCLUDE_X86_DARWIN
 valgrind_LDFLAGS   += -Wl,-read_only_relocs -Wl,suppress
 endif
@@ -77,7 +77,7 @@
 vgdb_CPPFLAGS  = $(AM_CPPFLAGS_PRI)
 vgdb_CFLAGS    = $(AM_CFLAGS_PRI)
 vgdb_CCASFLAGS = $(AM_CCASFLAGS_PRI)
-vgdb_LDFLAGS   = $(AM_CFLAGS_PRI)
+vgdb_LDFLAGS   = $(AM_CFLAGS_PRI) @LIB_UBSAN@
 if VGCONF_PLATVARIANT_IS_ANDROID
 vgdb_CFLAGS    += -static
 endif
diff --git a/coregrind/m_compiler.c b/coregrind/m_compiler.c
index 21c7c7a..f39a90f 100644
--- a/coregrind/m_compiler.c
+++ b/coregrind/m_compiler.c
@@ -39,6 +39,8 @@
 #include "config.h"
 #include "pub_core_basics.h"
 #include "pub_core_libcbase.h"
+#include "pub_core_libcassert.h"
+#include "pub_core_debuglog.h"
 
 #ifndef HAVE_BUILTIN_POPCOUT
 
@@ -218,6 +220,81 @@
 
 #endif
 
+
+/*====================================================================*/
+/*=== gcc -fsanitize=undefined helper function support             ===*/
+/*====================================================================*/
+
+void __ubsan_handle_type_mismatch ( void );
+void __ubsan_handle_type_mismatch ( void )
+{
+   VG_(debugLog)(0, "main:ubsan", "In %s", __func__);
+   vg_assert(0);
+}
+
+void __ubsan_handle_mul_overflow ( void );
+void __ubsan_handle_mul_overflow ( void )
+{
+   VG_(debugLog)(0, "main:ubsan", "In %s", __func__);
+   vg_assert(0);
+}
+
+void __ubsan_handle_add_overflow ( void );
+void __ubsan_handle_add_overflow ( void )
+{
+   VG_(debugLog)(0, "main:ubsan", "In %s", __func__);
+   vg_assert(0);
+}
+
+void __ubsan_handle_sub_overflow ( void );
+void __ubsan_handle_sub_overflow ( void )
+{
+   VG_(debugLog)(0, "main:ubsan", "In %s", __func__);
+   vg_assert(0);
+}
+
+void __ubsan_handle_divrem_overflow ( void );
+void __ubsan_handle_divrem_overflow ( void )
+{
+   VG_(debugLog)(0, "main:ubsan", "In %s", __func__);
+   vg_assert(0);
+}
+
+void __ubsan_handle_negate_overflow ( void );
+void __ubsan_handle_negate_overflow ( void )
+{
+   VG_(debugLog)(0, "main:ubsan", "In %s", __func__);
+   vg_assert(0);
+}
+
+void __ubsan_handle_out_of_bounds ( void );
+void __ubsan_handle_out_of_bounds ( void )
+{
+   VG_(debugLog)(0, "main:ubsan", "In %s", __func__);
+   vg_assert(0);
+}
+
+void __ubsan_handle_shift_out_of_bounds ( void );
+void __ubsan_handle_shift_out_of_bounds ( void )
+{
+   VG_(debugLog)(0, "main:ubsan", "In %s", __func__);
+   vg_assert(0);
+}
+
+void __ubsan_handle_vla_bound_not_positive ( void );
+void __ubsan_handle_vla_bound_not_positive ( void )
+{
+   VG_(debugLog)(0, "main:ubsan", "In %s", __func__);
+   vg_assert(0);
+}
+
+void __ubsan_handle_nonnull_arg ( void );
+void __ubsan_handle_nonnull_arg ( void )
+{
+   VG_(debugLog)(0, "main:ubsan", "In %s", __func__);
+   vg_assert(0);
+}
+
 /*--------------------------------------------------------------------*/
 /*--- end                                                          ---*/
 /*--------------------------------------------------------------------*/
diff --git a/coregrind/m_libcbase.c b/coregrind/m_libcbase.c
index b9a7574..60cad36 100644
--- a/coregrind/m_libcbase.c
+++ b/coregrind/m_libcbase.c
@@ -694,28 +694,30 @@
 
 void* VG_(memset) ( void *destV, Int c, SizeT sz )
 {
-   Int   c4;
-   HChar* d = (HChar*)destV;
+   UInt   c4;
+   UChar* d = destV;
+   UChar uc = c;
+
    while ((!VG_IS_4_ALIGNED(d)) && sz >= 1) {
-      d[0] = c;
+      d[0] = uc;
       d++;
       sz--;
    }
    if (sz == 0)
       return destV;
-   c4 = c & 0xFF;
+   c4 = uc;
    c4 |= (c4 << 8);
    c4 |= (c4 << 16);
    while (sz >= 16) {
-      ((Int*)d)[0] = c4;
-      ((Int*)d)[1] = c4;
-      ((Int*)d)[2] = c4;
-      ((Int*)d)[3] = c4;
+      ((UInt*)d)[0] = c4;
+      ((UInt*)d)[1] = c4;
+      ((UInt*)d)[2] = c4;
+      ((UInt*)d)[3] = c4;
       d += 16;
       sz -= 16;
    }
    while (sz >= 4) {
-      ((Int*)d)[0] = c4;
+      ((UInt*)d)[0] = c4;
       d += 4;
       sz -= 4;
    }
diff --git a/memcheck/tests/vbit-test/Makefile.am b/memcheck/tests/vbit-test/Makefile.am
index db6f6f5..9888fad 100644
--- a/memcheck/tests/vbit-test/Makefile.am
+++ b/memcheck/tests/vbit-test/Makefile.am
@@ -40,4 +40,4 @@
 vbit_test_CFLAGS       = $(AM_CFLAGS_PRI) -std=c99
 vbit_test_DEPENDENCIES = 
 vbit_test_LDADD        = 
-vbit_test_LDFLAGS      = $(AM_CFLAGS_PRI) -std=c99
+vbit_test_LDFLAGS      = $(AM_CFLAGS_PRI) -std=c99 @LIB_UBSAN@