summaryrefslogtreecommitdiff
path: root/src/alloc.c
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2016-01-26 23:00:10 -0800
committerPaul Eggert <eggert@cs.ucla.edu>2016-01-26 23:01:48 -0800
commitb88e9cded7ae3756e3a2ec4a23e8df352a0239f9 (patch)
tree201806e4c770722fa29ef77365030df930751d06 /src/alloc.c
parentcf17002326ba29d78f20118e0016dbd32fc3527e (diff)
downloademacs-b88e9cded7ae3756e3a2ec4a23e8df352a0239f9.tar.gz
malloc.h hygiene
This attempts to future-proof Emacs a bit against possible glibc changes, by having Emacs use <malloc.h> declarations rather than coding them up by hand. Problem noted by Florian Weimer in: https://sourceware.org/ml/libc-alpha/2016-01/msg00777.html Implement this mainly by moving malloc.h-related functions from emacs.c (which does not include <malloc.h>) to alloc.c (which does). * src/alloc.c (my_heap_start) [DOUG_LEA_MALLOC || GNU_LINUX]: New function. The remaining changes to this file apply only if DOUG_LEA_MALLOC. (alloc_unexec_pre, alloc_unexec_post): New functions. (malloc_initialize_hook): Use my_heap_start and alloc_unexec_post. (__MALLOC_HOOK_VOLATILE): New macro, if not already defined. (__malloc_initialize_hook): Use it. (malloc_state_ptr, malloc_initialize_hook, __malloc_initialize_hook): Move here from ... * src/emacs.c: ... here. (malloc_get_state, malloc_set_state): Remove extern decls. (my_heap_start) [DOUG_LEA_MALLOC || GNU_LINUX]: Remove static var. All uses changed to similarly-named new function. (Fdump_emacs): Use new functions alloc_unexec_pre, alloc_unexec_post. * src/lisp.h (my_heap_start, alloc_unexec_pre, alloc_unexec_post): New decls.
Diffstat (limited to 'src/alloc.c')
-rw-r--r--src/alloc.c76
1 files changed, 75 insertions, 1 deletions
diff --git a/src/alloc.c b/src/alloc.c
index 03dacc77c6e..d379761c168 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -92,6 +92,18 @@ static bool valgrind_p;
#include "w32heap.h" /* for sbrk */
#endif
+#if defined DOUG_LEA_MALLOC || defined GNU_LINUX
+/* The address where the heap starts. */
+void *
+my_heap_start (void)
+{
+ static void *start;
+ if (! start)
+ start = sbrk (0);
+ return start;
+}
+#endif
+
#ifdef DOUG_LEA_MALLOC
#include <malloc.h>
@@ -101,7 +113,69 @@ static bool valgrind_p;
#define MMAP_MAX_AREAS 100000000
-#endif /* not DOUG_LEA_MALLOC */
+/* A pointer to the memory allocated that copies that static data
+ inside glibc's malloc. */
+static void *malloc_state_ptr;
+
+/* Get and free this pointer; useful around unexec. */
+void
+alloc_unexec_pre (void)
+{
+ malloc_state_ptr = malloc_get_state ();
+}
+void
+alloc_unexec_post (void)
+{
+ free (malloc_state_ptr);
+}
+
+/* Restore the dumped malloc state. Because malloc can be invoked
+ even before main (e.g. by the dynamic linker), the dumped malloc
+ state must be restored as early as possible using this special hook. */
+static void
+malloc_initialize_hook (void)
+{
+ static bool malloc_using_checking;
+
+ if (! initialized)
+ {
+ my_heap_start ();
+ malloc_using_checking = getenv ("MALLOC_CHECK_") != NULL;
+ }
+ else
+ {
+ if (!malloc_using_checking)
+ {
+ /* Work around a bug in glibc's malloc. MALLOC_CHECK_ must be
+ ignored if the heap to be restored was constructed without
+ malloc checking. Can't use unsetenv, since that calls malloc. */
+ char **p = environ;
+ if (p)
+ for (; *p; p++)
+ if (strncmp (*p, "MALLOC_CHECK_=", 14) == 0)
+ {
+ do
+ *p = p[1];
+ while (*++p);
+
+ break;
+ }
+ }
+
+ malloc_set_state (malloc_state_ptr);
+# ifndef XMALLOC_OVERRUN_CHECK
+ alloc_unexec_post ();
+# endif
+ }
+}
+
+# ifndef __MALLOC_HOOK_VOLATILE
+# define __MALLOC_HOOK_VOLATILE
+# endif
+voidfuncptr __MALLOC_HOOK_VOLATILE __malloc_initialize_hook
+ = malloc_initialize_hook;
+
+#endif
/* Mark, unmark, query mark bit of a Lisp string. S must be a pointer
to a struct Lisp_String. */