summaryrefslogtreecommitdiff
path: root/malloc.c
diff options
context:
space:
mode:
authorIvan Maidanski <ivmai@mail.ru>2022-10-21 09:03:07 +0300
committerIvan Maidanski <ivmai@mail.ru>2022-10-21 11:05:58 +0300
commit8d209bffe46c94a0b9e37b82de3f43c86f1f3e5c (patch)
tree814672605c2f7082c12a051bfd243264d796d1d8 /malloc.c
parentc0c286cd5aaeaea49c18dba71a89d66918d667a5 (diff)
downloadbdwgc-8d209bffe46c94a0b9e37b82de3f43c86f1f3e5c.tar.gz
Get libpthread.so '.text' mapping only for glibc prior to v2.34 (Linux)
Some libc implementations like bionic (on Android), musl and glibc 2.34 (and later) do not have libpthread.so (because the code implementing POSIX threads is located in libc.so file). * include/private/gcconfig.h [GC_LINUX_THREADS && REDIRECT_MALLOC && !HAVE_LIBPTHREAD_SO && __GLIBC__ && !GC_GLIBC_PREREQ(2,34)] (HAVE_LIBPTHREAD_SO): Define macro; move comment from GC_init_lib_bounds. * malloc.c [REDIRECT_MALLOC && GC_LINUX_THREADS] (GC_libpthread_start, GC_libpthread_end): Define variable only if HAVE_LIBPTHREAD_SO. * malloc.c [REDIRECT_MALLOC && GC_LINUX_THREADS] (GC_init_lib_bounds): Call GC_text_mapping("libpthread-") only if HAVE_LIBPTHREAD_SO; remove TODO item. * malloc.c [REDIRECT_MALLOC && GC_LINUX_THREADS] (calloc): Update and place comments properly. * malloc.c [REDIRECT_MALLOC && GC_LINUX_THREADS] (calloc): Check the caller is in range between GC_libpthread_start and GC_libpthread_end only if HAVE_LIBPTHREAD_SO. * malloc.c [REDIRECT_FREE && !REDIRECT_MALLOC_IN_HEADER && !IGNORE_FREE && GC_LINUX_THREADS && !USE_PROC_FOR_LIBRARIES] (free): Likewise.
Diffstat (limited to 'malloc.c')
-rw-r--r--malloc.c57
1 files changed, 30 insertions, 27 deletions
diff --git a/malloc.c b/malloc.c
index 7b07dc05..ef8daddd 100644
--- a/malloc.c
+++ b/malloc.c
@@ -456,10 +456,12 @@ GC_API GC_ATTR_MALLOC void * GC_CALL GC_malloc_uncollectable(size_t lb)
}
# if defined(GC_LINUX_THREADS)
- STATIC ptr_t GC_libpthread_start = 0;
- STATIC ptr_t GC_libpthread_end = 0;
- STATIC ptr_t GC_libld_start = 0;
- STATIC ptr_t GC_libld_end = 0;
+# ifdef HAVE_LIBPTHREAD_SO
+ STATIC ptr_t GC_libpthread_start = NULL;
+ STATIC ptr_t GC_libpthread_end = NULL;
+# endif
+ STATIC ptr_t GC_libld_start = NULL;
+ STATIC ptr_t GC_libld_end = NULL;
STATIC void GC_init_lib_bounds(void)
{
@@ -467,21 +469,14 @@ GC_API GC_ATTR_MALLOC void * GC_CALL GC_malloc_uncollectable(size_t lb)
DISABLE_CANCEL(cancel_state);
GC_init(); /* if not called yet */
- if (!GC_text_mapping("libpthread-",
- &GC_libpthread_start, &GC_libpthread_end)) {
- /* Some libc implementations like bionic, musl and glibc 2.34 */
- /* do not have libpthread.so because the pthreads-related code */
- /* is located in libc.so, thus potential calloc calls from such */
- /* code are forwarded to real (libc) calloc without any special */
- /* handling on the libgc side. Checking glibc version at */
- /* compile time to turn off the warning seems to be fine. */
- /* TODO: Remove GC_text_mapping() call for this case. */
-# if defined(__GLIBC__) && !GC_GLIBC_PREREQ(2, 34)
+# ifdef HAVE_LIBPTHREAD_SO
+ if (!GC_text_mapping("libpthread-",
+ &GC_libpthread_start, &GC_libpthread_end)) {
WARN("Failed to find libpthread.so text mapping: Expect crash\n", 0);
/* This might still work with some versions of libpthread, */
/* so we do not abort. */
-# endif
- }
+ }
+# endif
if (!GC_text_mapping("ld-", &GC_libld_start, &GC_libld_end)) {
WARN("Failed to find ld.so text mapping: Expect crash\n", 0);
}
@@ -495,24 +490,29 @@ GC_API GC_ATTR_MALLOC void * GC_CALL GC_malloc_uncollectable(size_t lb)
&& lb && n > GC_SIZE_MAX / lb)
return (*GC_get_oom_fn())(GC_SIZE_MAX); /* n*lb overflow */
# if defined(GC_LINUX_THREADS)
- /* libpthread allocated some memory that is only pointed to by */
+ /* The linker may allocate some memory that is only pointed to by */
/* mmapped thread stacks. Make sure it is not collectible. */
{
static GC_bool lib_bounds_set = FALSE;
ptr_t caller = (ptr_t)__builtin_return_address(0);
+
/* This test does not need to ensure memory visibility, since */
/* the bounds will be set when/if we create another thread. */
if (!EXPECT(lib_bounds_set, TRUE)) {
GC_init_lib_bounds();
lib_bounds_set = TRUE;
}
- if (((word)caller >= (word)GC_libpthread_start
- && (word)caller < (word)GC_libpthread_end)
- || ((word)caller >= (word)GC_libld_start
- && (word)caller < (word)GC_libld_end))
+ if (((word)caller >= (word)GC_libld_start
+ && (word)caller < (word)GC_libld_end)
+# ifdef HAVE_LIBPTHREAD_SO
+ || ((word)caller >= (word)GC_libpthread_start
+ && (word)caller < (word)GC_libpthread_end)
+ /* The two ranges are actually usually adjacent, */
+ /* so there may be a way to speed this up. */
+# endif
+ ) {
return GC_generic_malloc_uncollectable(n * lb, UNCOLLECTABLE);
- /* The two ranges are actually usually adjacent, so there may */
- /* be a way to speed this up. */
+ }
}
# endif
return (void *)REDIRECT_MALLOC_F(n * lb);
@@ -696,10 +696,13 @@ GC_API void GC_CALL GC_free(void * p)
ptr_t caller = (ptr_t)__builtin_return_address(0);
/* This test does not need to ensure memory visibility, since */
/* the bounds will be set when/if we create another thread. */
- if (((word)caller >= (word)GC_libpthread_start
- && (word)caller < (word)GC_libpthread_end)
- || ((word)caller >= (word)GC_libld_start
- && (word)caller < (word)GC_libld_end)) {
+ if (((word)caller >= (word)GC_libld_start
+ && (word)caller < (word)GC_libld_end)
+# ifdef HAVE_LIBPTHREAD_SO
+ || ((word)caller >= (word)GC_libpthread_start
+ && (word)caller < (word)GC_libpthread_end)
+# endif
+ ) {
GC_free(p);
return;
}