emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] trunk r115756: Fix core dumps with gcc -fsanitize=address


From: Paul Eggert
Subject: [Emacs-diffs] trunk r115756: Fix core dumps with gcc -fsanitize=address and GNU/Linux.
Date: Thu, 26 Dec 2013 08:57:32 +0000
User-agent: Bazaar (2.6b2)

------------------------------------------------------------
revno: 115756
revision-id: address@hidden
parent: address@hidden
committer: Paul Eggert <address@hidden>
branch nick: trunk
timestamp: Thu 2013-12-26 00:57:28 -0800
message:
  Fix core dumps with gcc -fsanitize=address and GNU/Linux.
  
  On my Fedora 19 platform the core dumps were so big that
  my desktop became nearly catatonic.
  * configure.ac: Check whether addresses are sanitized.
  (CANNOT_DUMP): Warn if addresses are sanitized and not CANNOT_DUMP.
  (DOUG_LEA_MALLOC): Do not define if addresses are sanitized.
  (SYSTEM_MALLOC): Define if addresses are sanitized.
  * src/alloc.c (no_sanitize_memcpy) [MAX_SAVE_STACK > 0]: New function.
  (Fgarbage_collect) [MAX_SAVE_STACK > 0]: Use it.
  (USE_ALIGNED_MALLOC): Do not define if addresses are sanitized.
  (mark_memory): Use ATTRIBUTE_NO_SANITIZE_ADDRESS rather than
  a clang-only syntax.
  * src/conf_post.h (__has_feature): New macro, if not already defined.
  (ADDRESS_SANITIZER, ADDRESS_SANITIZER_WORKAROUND)
  (ATTRIBUTE_NO_SANITIZE_ADDRESS): New macros.
modified:
  ChangeLog                      changelog-20091113204419-o5vbwnq5f7feedwu-1538
  configure.ac                   
configure.in-20091113204419-o5vbwnq5f7feedwu-783
  src/ChangeLog                  changelog-20091113204419-o5vbwnq5f7feedwu-1438
  src/alloc.c                    alloc.c-20091113204419-o5vbwnq5f7feedwu-252
  src/conf_post.h                conf_post.h-20120730211826-q0qbxxwh2emw52hd-1
=== modified file 'ChangeLog'
--- a/ChangeLog 2013-12-24 18:27:53 +0000
+++ b/ChangeLog 2013-12-26 08:57:28 +0000
@@ -1,3 +1,11 @@
+2013-12-26  Paul Eggert  <address@hidden>
+
+       Fix core dumps with gcc -fsanitize=address and GNU/Linux.
+       * configure.ac: Check whether addresses are sanitized.
+       (CANNOT_DUMP): Warn if addresses are sanitized and not CANNOT_DUMP.
+       (DOUG_LEA_MALLOC): Do not define if addresses are sanitized.
+       (SYSTEM_MALLOC): Define if addresses are sanitized.
+
 2013-12-24  Paul Eggert  <address@hidden>
 
        Automate the procedure for updating copyright year.

=== modified file 'configure.ac'
--- a/configure.ac      2013-12-23 15:13:14 +0000
+++ b/configure.ac      2013-12-26 08:57:28 +0000
@@ -1048,6 +1048,21 @@
 
 LDFLAGS="$late_LDFLAGS"
 
+AC_CACHE_CHECK([whether addresses are sanitized],
+  [emacs_cv_sanitize_address],
+  [AC_COMPILE_IFELSE(
+     [AC_LANG_PROGRAM(
+       [[#ifndef __has_feature
+         #define __has_feature(f) 0
+         #endif
+         #if defined __SANITIZE_ADDRESS__ || __has_feature (address_sanitizer)
+         #else
+          #error "Addresses are not sanitized."
+         #endif
+       ]])],
+     [emacs_cv_sanitize_address=yes],
+     [emacs_cv_sanitize_address=no])])
+
 dnl The function dump-emacs will not be defined and temacs will do
 dnl (load "loadup") automatically unless told otherwise.
 test "x$CANNOT_DUMP" = "x" && CANNOT_DUMP=no
@@ -1055,8 +1070,11 @@
   your-opsys-here) CANNOT_DUMP=yes ;;
 esac
 
-test "$CANNOT_DUMP" = "yes" && \
+if test "$CANNOT_DUMP" = "yes"; then
   AC_DEFINE(CANNOT_DUMP, 1, [Define if Emacs cannot be dumped on your system.])
+elif test "$emacs_cv_sanitize_address" = yes; then
+  AC_MSG_WARN([[Addresses are sanitized; suggest CANNOT_DUMP=yes]])
+fi
 
 AC_SUBST(CANNOT_DUMP)
 
@@ -1888,20 +1906,21 @@
 AC_CACHE_CHECK(
   [whether malloc is Doug Lea style],
   [emacs_cv_var_doug_lea_malloc],
-  [AC_LINK_IFELSE(
-     [AC_LANG_PROGRAM(
-        [[#include <malloc.h>
-         static void hook (void) {}]],
-        [[malloc_set_state (malloc_get_state ());
-         __after_morecore_hook = hook;
-         __malloc_initialize_hook = hook;]])],
-     [emacs_cv_var_doug_lea_malloc=yes],
-     [emacs_cv_var_doug_lea_malloc=no])])
+  [emacs_cv_var_doug_lea_malloc=no
+   dnl Hooks do not work with address sanitization.
+   if test "$emacs_cv_sanitize_address" != yes; then
+     AC_LINK_IFELSE(
+       [AC_LANG_PROGRAM(
+         [[#include <malloc.h>
+           static void hook (void) {}]],
+         [[malloc_set_state (malloc_get_state ());
+           __after_morecore_hook = hook;
+           __malloc_initialize_hook = hook;]])],
+       [emacs_cv_var_doug_lea_malloc=yes])])
+   fi
 doug_lea_malloc=$emacs_cv_var_doug_lea_malloc
 
-
-dnl See comments in aix4-2.h about maybe using system malloc there.
-system_malloc=no
+system_malloc=$emacs_cv_sanitize_address
 case "$opsys" in
   ## darwin ld insists on the use of malloc routines in the System framework.
   darwin|sol2-10) system_malloc=yes ;;

=== modified file 'src/ChangeLog'
--- a/src/ChangeLog     2013-12-25 17:30:24 +0000
+++ b/src/ChangeLog     2013-12-26 08:57:28 +0000
@@ -1,3 +1,17 @@
+2013-12-26  Paul Eggert  <address@hidden>
+
+       Fix core dumps with gcc -fsanitize=address and GNU/Linux.
+       On my Fedora 19 platform the core dumps were so big that
+       my desktop became nearly catatonic.
+       * alloc.c (no_sanitize_memcpy) [MAX_SAVE_STACK > 0]: New function.
+       (Fgarbage_collect) [MAX_SAVE_STACK > 0]: Use it.
+       (USE_ALIGNED_MALLOC): Do not define if addresses are sanitized.
+       (mark_memory): Use ATTRIBUTE_NO_SANITIZE_ADDRESS rather than
+       a clang-only syntax.
+       * conf_post.h (__has_feature): New macro, if not already defined.
+       (ADDRESS_SANITIZER, ADDRESS_SANITIZER_WORKAROUND)
+       (ATTRIBUTE_NO_SANITIZE_ADDRESS): New macros.
+
 2013-12-25  Eli Zaretskii  <address@hidden>
 
        * w32fns.c (Fw32_shell_execute): Make DOCUMENT absolute only if it

=== modified file 'src/alloc.c'
--- a/src/alloc.c       2013-12-16 07:45:33 +0000
+++ b/src/alloc.c       2013-12-26 08:57:28 +0000
@@ -203,7 +203,27 @@
 #if MAX_SAVE_STACK > 0
 static char *stack_copy;
 static ptrdiff_t stack_copy_size;
-#endif
+
+/* Copy to DEST a block of memory from SRC of size SIZE bytes,
+   avoiding any address sanitization.  */
+
+static void * ATTRIBUTE_NO_SANITIZE_ADDRESS
+no_sanitize_memcpy (void *dest, void const *src, size_t size)
+{
+  if (! ADDRESS_SANITIZER)
+    return memcpy (dest, src, size);
+  else
+    {
+      size_t i;
+      char *d = dest;
+      char const *s = src;
+      for (i = 0; i < size; i++)
+       d[i] = s[i];
+      return dest;
+    }
+}
+
+#endif /* MAX_SAVE_STACK > 0 */
 
 static Lisp_Object Qconses;
 static Lisp_Object Qsymbols;
@@ -920,20 +940,26 @@
 /* The entry point is lisp_align_malloc which returns blocks of at most
    BLOCK_BYTES and guarantees they are aligned on a BLOCK_ALIGN boundary.  */
 
-#if !defined SYSTEM_MALLOC && !defined DOUG_LEA_MALLOC
-# define USE_ALIGNED_ALLOC 1
+/* Use aligned_alloc if it or a simple substitute is available.
+   Address sanitization breaks aligned allocation, as of gcc 4.8.2 and
+   clang 3.3 anyway.  */
+
+#if ! ADDRESS_SANITIZER
+# if !defined SYSTEM_MALLOC && !defined DOUG_LEA_MALLOC
+#  define USE_ALIGNED_ALLOC 1
 /* Defined in gmalloc.c.  */
 void *aligned_alloc (size_t, size_t);
-#elif defined HAVE_ALIGNED_ALLOC
-# define USE_ALIGNED_ALLOC 1
-#elif defined HAVE_POSIX_MEMALIGN
-# define USE_ALIGNED_ALLOC 1
+# elif defined HAVE_ALIGNED_ALLOC
+#  define USE_ALIGNED_ALLOC 1
+# elif defined HAVE_POSIX_MEMALIGN
+#  define USE_ALIGNED_ALLOC 1
 static void *
 aligned_alloc (size_t alignment, size_t size)
 {
   void *p;
   return posix_memalign (&p, alignment, size) == 0 ? p : 0;
 }
+# endif
 #endif
 
 /* BLOCK_ALIGN has to be a power of 2.  */
@@ -4553,16 +4579,8 @@
 /* Mark Lisp objects referenced from the address range START+OFFSET..END
    or END+OFFSET..START. */
 
-static void
+static void ATTRIBUTE_NO_SANITIZE_ADDRESS
 mark_memory (void *start, void *end)
-#if defined (__clang__) && defined (__has_feature)
-#if __has_feature(address_sanitizer)
-  /* Do not allow -faddress-sanitizer to check this function, since it
-     crosses the function stack boundary, and thus would yield many
-     false positives. */
-  __attribute__((no_address_safety_analysis))
-#endif
-#endif
 {
   void **pp;
   int i;
@@ -5477,7 +5495,7 @@
              stack_copy = xrealloc (stack_copy, stack_size);
              stack_copy_size = stack_size;
            }
-         memcpy (stack_copy, stack, stack_size);
+         no_sanitize_memcpy (stack_copy, stack, stack_size);
        }
     }
 #endif /* MAX_SAVE_STACK > 0 */

=== modified file 'src/conf_post.h'
--- a/src/conf_post.h   2013-12-23 12:07:46 +0000
+++ b/src/conf_post.h   2013-12-26 08:57:28 +0000
@@ -50,8 +50,19 @@
 #endif
 #endif
 
+/* When not using Clang, assume its attributes and features are absent.  */
 #ifndef __has_attribute
-# define __has_attribute(a) false /* non-clang */
+# define __has_attribute(a) false
+#endif
+#ifndef __has_feature
+# define __has_feature(a) false
+#endif
+
+/* True if addresses are being sanitized.  */
+#if defined __SANITIZE_ADDRESS__ || __has_feature (address_sanitizer)
+# define ADDRESS_SANITIZER true
+#else
+# define ADDRESS_SANITIZER false
 #endif
 
 #ifdef DARWIN_OS
@@ -204,6 +215,32 @@
 
 #define ATTRIBUTE_CONST _GL_ATTRIBUTE_CONST
 
+/* Work around GCC bug 59600: when a function is inlined, the inlined
+   code may have its addresses sanitized even if the function has the
+   no_sanitize_address attribute.  This bug is present in GCC 4.8.2
+   and clang 3.3, the latest releases as of December 2013, and the
+   only platforms known to support address sanitization.  When the bug
+   is fixed the #if can be updated accordingly.  */
+#if ADDRESS_SANITIZER
+# define ADDRESS_SANITIZER_WORKAROUND NO_INLINE
+#else
+# define ADDRESS_SANITIZER_WORKAROUND
+#endif
+
+/* Attribute of functions whose code should not have addresses
+   sanitized.  */
+
+#if (__has_attribute (no_sanitize_address) \
+     || 4 < __GNUC__ + (8 <= __GNUC_MINOR__))
+# define ATTRIBUTE_NO_SANITIZE_ADDRESS \
+    __attribute__ ((no_sanitize_address)) ADDRESS_SANITIZER_WORKAROUND
+#elif __has_attribute (no_address_safety_analysis)
+# define ATTRIBUTE_NO_SANITIZE_ADDRESS \
+    __attribute__ ((no_address_safety_analysis)) ADDRESS_SANITIZER_WORKAROUND
+#else
+# define ATTRIBUTE_NO_SANITIZE_ADDRESS
+#endif
+
 /* Some versions of GNU/Linux define noinline in their headers.  */
 #ifdef noinline
 #undef noinline


reply via email to

[Prev in Thread] Current Thread [Next in Thread]