diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2016-01-26 23:00:10 -0800 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2016-01-26 23:01:48 -0800 |
commit | b88e9cded7ae3756e3a2ec4a23e8df352a0239f9 (patch) | |
tree | 201806e4c770722fa29ef77365030df930751d06 /src/alloc.c | |
parent | cf17002326ba29d78f20118e0016dbd32fc3527e (diff) | |
download | emacs-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.c | 76 |
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. */ |