aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggert2013-12-26 00:57:28 -0800
committerPaul Eggert2013-12-26 00:57:28 -0800
commite76119d7542b19eb03f8d725480cbf98f7fa03d9 (patch)
treebdc730dbcd0f54ca25623960feb8df4dfce073b7
parent2200a8c91de23f9749d1b3c961c4f8bb3145ddfa (diff)
downloademacs-e76119d7542b19eb03f8d725480cbf98f7fa03d9.tar.gz
emacs-e76119d7542b19eb03f8d725480cbf98f7fa03d9.zip
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.
-rw-r--r--ChangeLog8
-rw-r--r--configure.ac45
-rw-r--r--src/ChangeLog14
-rw-r--r--src/alloc.c52
-rw-r--r--src/conf_post.h39
5 files changed, 127 insertions, 31 deletions
diff --git a/ChangeLog b/ChangeLog
index 3630d570b28..ddf7d92ac14 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
12013-12-26 Paul Eggert <eggert@cs.ucla.edu>
2
3 Fix core dumps with gcc -fsanitize=address and GNU/Linux.
4 * configure.ac: Check whether addresses are sanitized.
5 (CANNOT_DUMP): Warn if addresses are sanitized and not CANNOT_DUMP.
6 (DOUG_LEA_MALLOC): Do not define if addresses are sanitized.
7 (SYSTEM_MALLOC): Define if addresses are sanitized.
8
12013-12-24 Paul Eggert <eggert@cs.ucla.edu> 92013-12-24 Paul Eggert <eggert@cs.ucla.edu>
2 10
3 Automate the procedure for updating copyright year. 11 Automate the procedure for updating copyright year.
diff --git a/configure.ac b/configure.ac
index ea76baf8f8f..8aaf2c6a8ac 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1048,6 +1048,21 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM([], [])],
1048 1048
1049LDFLAGS="$late_LDFLAGS" 1049LDFLAGS="$late_LDFLAGS"
1050 1050
1051AC_CACHE_CHECK([whether addresses are sanitized],
1052 [emacs_cv_sanitize_address],
1053 [AC_COMPILE_IFELSE(
1054 [AC_LANG_PROGRAM(
1055 [[#ifndef __has_feature
1056 #define __has_feature(f) 0
1057 #endif
1058 #if defined __SANITIZE_ADDRESS__ || __has_feature (address_sanitizer)
1059 #else
1060 #error "Addresses are not sanitized."
1061 #endif
1062 ]])],
1063 [emacs_cv_sanitize_address=yes],
1064 [emacs_cv_sanitize_address=no])])
1065
1051dnl The function dump-emacs will not be defined and temacs will do 1066dnl The function dump-emacs will not be defined and temacs will do
1052dnl (load "loadup") automatically unless told otherwise. 1067dnl (load "loadup") automatically unless told otherwise.
1053test "x$CANNOT_DUMP" = "x" && CANNOT_DUMP=no 1068test "x$CANNOT_DUMP" = "x" && CANNOT_DUMP=no
@@ -1055,8 +1070,11 @@ case "$opsys" in
1055 your-opsys-here) CANNOT_DUMP=yes ;; 1070 your-opsys-here) CANNOT_DUMP=yes ;;
1056esac 1071esac
1057 1072
1058test "$CANNOT_DUMP" = "yes" && \ 1073if test "$CANNOT_DUMP" = "yes"; then
1059 AC_DEFINE(CANNOT_DUMP, 1, [Define if Emacs cannot be dumped on your system.]) 1074 AC_DEFINE(CANNOT_DUMP, 1, [Define if Emacs cannot be dumped on your system.])
1075elif test "$emacs_cv_sanitize_address" = yes; then
1076 AC_MSG_WARN([[Addresses are sanitized; suggest CANNOT_DUMP=yes]])
1077fi
1060 1078
1061AC_SUBST(CANNOT_DUMP) 1079AC_SUBST(CANNOT_DUMP)
1062 1080
@@ -1888,20 +1906,21 @@ GNU_MALLOC=yes
1888AC_CACHE_CHECK( 1906AC_CACHE_CHECK(
1889 [whether malloc is Doug Lea style], 1907 [whether malloc is Doug Lea style],
1890 [emacs_cv_var_doug_lea_malloc], 1908 [emacs_cv_var_doug_lea_malloc],
1891 [AC_LINK_IFELSE( 1909 [emacs_cv_var_doug_lea_malloc=no
1892 [AC_LANG_PROGRAM( 1910 dnl Hooks do not work with address sanitization.
1893 [[#include <malloc.h> 1911 if test "$emacs_cv_sanitize_address" != yes; then
1894 static void hook (void) {}]], 1912 AC_LINK_IFELSE(
1895 [[malloc_set_state (malloc_get_state ()); 1913 [AC_LANG_PROGRAM(
1896 __after_morecore_hook = hook; 1914 [[#include <malloc.h>
1897 __malloc_initialize_hook = hook;]])], 1915 static void hook (void) {}]],
1898 [emacs_cv_var_doug_lea_malloc=yes], 1916 [[malloc_set_state (malloc_get_state ());
1899 [emacs_cv_var_doug_lea_malloc=no])]) 1917 __after_morecore_hook = hook;
1918 __malloc_initialize_hook = hook;]])],
1919 [emacs_cv_var_doug_lea_malloc=yes])])
1920 fi
1900doug_lea_malloc=$emacs_cv_var_doug_lea_malloc 1921doug_lea_malloc=$emacs_cv_var_doug_lea_malloc
1901 1922
1902 1923system_malloc=$emacs_cv_sanitize_address
1903dnl See comments in aix4-2.h about maybe using system malloc there.
1904system_malloc=no
1905case "$opsys" in 1924case "$opsys" in
1906 ## darwin ld insists on the use of malloc routines in the System framework. 1925 ## darwin ld insists on the use of malloc routines in the System framework.
1907 darwin|sol2-10) system_malloc=yes ;; 1926 darwin|sol2-10) system_malloc=yes ;;
diff --git a/src/ChangeLog b/src/ChangeLog
index 1e8684c4ddb..70df9cd3641 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,17 @@
12013-12-26 Paul Eggert <eggert@cs.ucla.edu>
2
3 Fix core dumps with gcc -fsanitize=address and GNU/Linux.
4 On my Fedora 19 platform the core dumps were so big that
5 my desktop became nearly catatonic.
6 * alloc.c (no_sanitize_memcpy) [MAX_SAVE_STACK > 0]: New function.
7 (Fgarbage_collect) [MAX_SAVE_STACK > 0]: Use it.
8 (USE_ALIGNED_MALLOC): Do not define if addresses are sanitized.
9 (mark_memory): Use ATTRIBUTE_NO_SANITIZE_ADDRESS rather than
10 a clang-only syntax.
11 * conf_post.h (__has_feature): New macro, if not already defined.
12 (ADDRESS_SANITIZER, ADDRESS_SANITIZER_WORKAROUND)
13 (ATTRIBUTE_NO_SANITIZE_ADDRESS): New macros.
14
12013-12-25 Eli Zaretskii <eliz@gnu.org> 152013-12-25 Eli Zaretskii <eliz@gnu.org>
2 16
3 * w32fns.c (Fw32_shell_execute): Make DOCUMENT absolute only if it 17 * w32fns.c (Fw32_shell_execute): Make DOCUMENT absolute only if it
diff --git a/src/alloc.c b/src/alloc.c
index 447b465a076..14c322a3a64 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -203,7 +203,27 @@ const char *pending_malloc_warning;
203#if MAX_SAVE_STACK > 0 203#if MAX_SAVE_STACK > 0
204static char *stack_copy; 204static char *stack_copy;
205static ptrdiff_t stack_copy_size; 205static ptrdiff_t stack_copy_size;
206#endif 206
207/* Copy to DEST a block of memory from SRC of size SIZE bytes,
208 avoiding any address sanitization. */
209
210static void * ATTRIBUTE_NO_SANITIZE_ADDRESS
211no_sanitize_memcpy (void *dest, void const *src, size_t size)
212{
213 if (! ADDRESS_SANITIZER)
214 return memcpy (dest, src, size);
215 else
216 {
217 size_t i;
218 char *d = dest;
219 char const *s = src;
220 for (i = 0; i < size; i++)
221 d[i] = s[i];
222 return dest;
223 }
224}
225
226#endif /* MAX_SAVE_STACK > 0 */
207 227
208static Lisp_Object Qconses; 228static Lisp_Object Qconses;
209static Lisp_Object Qsymbols; 229static Lisp_Object Qsymbols;
@@ -920,20 +940,26 @@ lisp_free (void *block)
920/* The entry point is lisp_align_malloc which returns blocks of at most 940/* The entry point is lisp_align_malloc which returns blocks of at most
921 BLOCK_BYTES and guarantees they are aligned on a BLOCK_ALIGN boundary. */ 941 BLOCK_BYTES and guarantees they are aligned on a BLOCK_ALIGN boundary. */
922 942
923#if !defined SYSTEM_MALLOC && !defined DOUG_LEA_MALLOC 943/* Use aligned_alloc if it or a simple substitute is available.
924# define USE_ALIGNED_ALLOC 1 944 Address sanitization breaks aligned allocation, as of gcc 4.8.2 and
945 clang 3.3 anyway. */
946
947#if ! ADDRESS_SANITIZER
948# if !defined SYSTEM_MALLOC && !defined DOUG_LEA_MALLOC
949# define USE_ALIGNED_ALLOC 1
925/* Defined in gmalloc.c. */ 950/* Defined in gmalloc.c. */
926void *aligned_alloc (size_t, size_t); 951void *aligned_alloc (size_t, size_t);
927#elif defined HAVE_ALIGNED_ALLOC 952# elif defined HAVE_ALIGNED_ALLOC
928# define USE_ALIGNED_ALLOC 1 953# define USE_ALIGNED_ALLOC 1
929#elif defined HAVE_POSIX_MEMALIGN 954# elif defined HAVE_POSIX_MEMALIGN
930# define USE_ALIGNED_ALLOC 1 955# define USE_ALIGNED_ALLOC 1
931static void * 956static void *
932aligned_alloc (size_t alignment, size_t size) 957aligned_alloc (size_t alignment, size_t size)
933{ 958{
934 void *p; 959 void *p;
935 return posix_memalign (&p, alignment, size) == 0 ? p : 0; 960 return posix_memalign (&p, alignment, size) == 0 ? p : 0;
936} 961}
962# endif
937#endif 963#endif
938 964
939/* BLOCK_ALIGN has to be a power of 2. */ 965/* BLOCK_ALIGN has to be a power of 2. */
@@ -4553,16 +4579,8 @@ mark_maybe_pointer (void *p)
4553/* Mark Lisp objects referenced from the address range START+OFFSET..END 4579/* Mark Lisp objects referenced from the address range START+OFFSET..END
4554 or END+OFFSET..START. */ 4580 or END+OFFSET..START. */
4555 4581
4556static void 4582static void ATTRIBUTE_NO_SANITIZE_ADDRESS
4557mark_memory (void *start, void *end) 4583mark_memory (void *start, void *end)
4558#if defined (__clang__) && defined (__has_feature)
4559#if __has_feature(address_sanitizer)
4560 /* Do not allow -faddress-sanitizer to check this function, since it
4561 crosses the function stack boundary, and thus would yield many
4562 false positives. */
4563 __attribute__((no_address_safety_analysis))
4564#endif
4565#endif
4566{ 4584{
4567 void **pp; 4585 void **pp;
4568 int i; 4586 int i;
@@ -5477,7 +5495,7 @@ See Info node `(elisp)Garbage Collection'. */)
5477 stack_copy = xrealloc (stack_copy, stack_size); 5495 stack_copy = xrealloc (stack_copy, stack_size);
5478 stack_copy_size = stack_size; 5496 stack_copy_size = stack_size;
5479 } 5497 }
5480 memcpy (stack_copy, stack, stack_size); 5498 no_sanitize_memcpy (stack_copy, stack, stack_size);
5481 } 5499 }
5482 } 5500 }
5483#endif /* MAX_SAVE_STACK > 0 */ 5501#endif /* MAX_SAVE_STACK > 0 */
diff --git a/src/conf_post.h b/src/conf_post.h
index 66dd9a36f00..04c4f4f5f15 100644
--- a/src/conf_post.h
+++ b/src/conf_post.h
@@ -50,8 +50,19 @@ typedef bool bool_bf;
50#endif 50#endif
51#endif 51#endif
52 52
53/* When not using Clang, assume its attributes and features are absent. */
53#ifndef __has_attribute 54#ifndef __has_attribute
54# define __has_attribute(a) false /* non-clang */ 55# define __has_attribute(a) false
56#endif
57#ifndef __has_feature
58# define __has_feature(a) false
59#endif
60
61/* True if addresses are being sanitized. */
62#if defined __SANITIZE_ADDRESS__ || __has_feature (address_sanitizer)
63# define ADDRESS_SANITIZER true
64#else
65# define ADDRESS_SANITIZER false
55#endif 66#endif
56 67
57#ifdef DARWIN_OS 68#ifdef DARWIN_OS
@@ -204,6 +215,32 @@ extern void _DebPrint (const char *fmt, ...);
204 215
205#define ATTRIBUTE_CONST _GL_ATTRIBUTE_CONST 216#define ATTRIBUTE_CONST _GL_ATTRIBUTE_CONST
206 217
218/* Work around GCC bug 59600: when a function is inlined, the inlined
219 code may have its addresses sanitized even if the function has the
220 no_sanitize_address attribute. This bug is present in GCC 4.8.2
221 and clang 3.3, the latest releases as of December 2013, and the
222 only platforms known to support address sanitization. When the bug
223 is fixed the #if can be updated accordingly. */
224#if ADDRESS_SANITIZER
225# define ADDRESS_SANITIZER_WORKAROUND NO_INLINE
226#else
227# define ADDRESS_SANITIZER_WORKAROUND
228#endif
229
230/* Attribute of functions whose code should not have addresses
231 sanitized. */
232
233#if (__has_attribute (no_sanitize_address) \
234 || 4 < __GNUC__ + (8 <= __GNUC_MINOR__))
235# define ATTRIBUTE_NO_SANITIZE_ADDRESS \
236 __attribute__ ((no_sanitize_address)) ADDRESS_SANITIZER_WORKAROUND
237#elif __has_attribute (no_address_safety_analysis)
238# define ATTRIBUTE_NO_SANITIZE_ADDRESS \
239 __attribute__ ((no_address_safety_analysis)) ADDRESS_SANITIZER_WORKAROUND
240#else
241# define ATTRIBUTE_NO_SANITIZE_ADDRESS
242#endif
243
207/* Some versions of GNU/Linux define noinline in their headers. */ 244/* Some versions of GNU/Linux define noinline in their headers. */
208#ifdef noinline 245#ifdef noinline
209#undef noinline 246#undef noinline