mirror of
git://git.musl-libc.org/musl
synced 2025-01-25 08:03:04 +00:00
give libc access to its own malloc even if public malloc is interposed
allowing the application to replace malloc (since commitc9f415d7ea
) has brought multiple headaches where it's used from various critical sections in libc components. for example: - the thread-local message buffers allocated for dlerror can't be freed at thread exit time because application code would then run in the context of a non-existant thread. this was handled in commitaa5a9d15e0
by queuing them for free later. - the dynamic linker has to be careful not to pass memory allocated at early startup time (necessarily using its own malloc) to realloc or free after redoing relocations with the application and all libraries present. bugs in this area were fixed several times, at least in commits0c5c8f5da6
and2f1f51ae7b
and possibly others. - by calling the allocator from contexts where libc-internal locks are held, we impose undocumented requirements on alternate malloc implementations not to call into any libc function that might attempt to take these locks; if they do, deadlock results. - work to make fork of a multithreaded parent give the child an unrestricted execution environment is blocked by lock order issues as long as the application-provided allocator can be called with libc-internal locks held. these problems are all fixed by giving libc internals access to the original, non-replaced allocator, for use where needed. it can't be used everywhere, as some interfaces like str[n]dup, open_[w]memstream, getline/getdelim, etc. are required to provide the called memory obtained as if by (the public) malloc. and there are a number of libc interfaces that are "pure library" code, not part of some internal singleton, and where using the application's choice of malloc implementation is preferable -- things like glob, regex, etc. one might expect there to be significant cost to static-linked programs, pulling in two malloc implementations, one of them mostly-unused, if malloc is replaced. however, in almost all of the places where malloc is used internally, care has been taken already not to pull in realloc/free (i.e. to link with just the bump allocator). this size optimization carries over automatically. the newly-exposed internal allocator functions are obtained by renaming the actual definitions, then adding new wrappers around them with the public names. technically __libc_realloc and __libc_free could be aliases rather than needing a layer of wrapper, but this would almost surely break certain instrumentation (valgrind) and the size and performance difference is negligible. __libc_calloc needs to be handled specially since calloc is designed to work with either the internal or the replaced malloc. as a bonus, this change also eliminates the longstanding ugly dependency of the static bump allocator on order of object files in libc.a, by making it so there's only one definition of the malloc function and having it in the same source file as the bump allocator.
This commit is contained in:
parent
c1e5d243b7
commit
8d37958d58
@ -9,4 +9,10 @@ hidden int __mkostemps(char *, int, int);
|
||||
hidden int __ptsname_r(int, char *, size_t);
|
||||
hidden char *__randname(char *);
|
||||
|
||||
hidden void *__libc_malloc(size_t);
|
||||
hidden void *__libc_malloc_impl(size_t);
|
||||
hidden void *__libc_calloc(size_t, size_t);
|
||||
hidden void *__libc_realloc(void *, size_t);
|
||||
hidden void __libc_free(void *);
|
||||
|
||||
#endif
|
||||
|
6
src/malloc/free.c
Normal file
6
src/malloc/free.c
Normal file
@ -0,0 +1,6 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
void free(void *p)
|
||||
{
|
||||
return __libc_free(p);
|
||||
}
|
4
src/malloc/libc_calloc.c
Normal file
4
src/malloc/libc_calloc.c
Normal file
@ -0,0 +1,4 @@
|
||||
#define calloc __libc_calloc
|
||||
#define malloc __libc_malloc
|
||||
|
||||
#include "calloc.c"
|
@ -100,4 +100,16 @@ static void *__simple_malloc(size_t n)
|
||||
return p;
|
||||
}
|
||||
|
||||
weak_alias(__simple_malloc, malloc);
|
||||
weak_alias(__simple_malloc, __libc_malloc_impl);
|
||||
|
||||
void *__libc_malloc(size_t n)
|
||||
{
|
||||
return __libc_malloc_impl(n);
|
||||
}
|
||||
|
||||
static void *default_malloc(size_t n)
|
||||
{
|
||||
return __libc_malloc_impl(n);
|
||||
}
|
||||
|
||||
weak_alias(default_malloc, malloc);
|
||||
|
@ -20,6 +20,10 @@
|
||||
#define is_allzero __malloc_allzerop
|
||||
#define dump_heap __dump_heap
|
||||
|
||||
#define malloc __libc_malloc_impl
|
||||
#define realloc __libc_realloc
|
||||
#define free __libc_free
|
||||
|
||||
#if USE_REAL_ASSERT
|
||||
#include <assert.h>
|
||||
#else
|
||||
|
@ -10,6 +10,10 @@
|
||||
#include "pthread_impl.h"
|
||||
#include "malloc_impl.h"
|
||||
|
||||
#define malloc __libc_malloc
|
||||
#define realloc __libc_realloc
|
||||
#define free __libc_free
|
||||
|
||||
#if defined(__GNUC__) && defined(__PIC__)
|
||||
#define inline inline __attribute__((always_inline))
|
||||
#endif
|
||||
|
6
src/malloc/realloc.c
Normal file
6
src/malloc/realloc.c
Normal file
@ -0,0 +1,6 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
void *realloc(void *p, size_t n)
|
||||
{
|
||||
return __libc_realloc(p, n);
|
||||
}
|
Loading…
Reference in New Issue
Block a user