unsigned int maj_dev;
ptr_t least_ha, greatest_ha;
unsigned i;
- ptr_t datastart = (ptr_t)(DATASTART);
+ ptr_t datastart;
+
+# ifdef DATASTART_IS_FUNC
+ static ptr_t datastart_cached = (ptr_t)(word)-1;
+
+ /* Evaluate DATASTART only once. */
+ if (datastart_cached == (ptr_t)(word)-1) {
+ datastart_cached = (ptr_t)(DATASTART);
+ }
+ datastart = datastart_cached;
+# else
+ datastart = (ptr_t)(DATASTART);
+# endif
GC_ASSERT(I_HOLD_LOCK());
sort_heap_sects(GC_our_memory, GC_n_memory);
# define HAVE_REGISTER_MAIN_STATIC_DATA
-#endif /* USE_PROC_FOR_LIBRARIES */
+#else /* !USE_PROC_FOR_LIBRARIES */
-#if !defined(USE_PROC_FOR_LIBRARIES)
/* The following is the preferred way to walk dynamic libraries */
/* For glibc 2.2.4+. Unfortunately, it doesn't work for older */
/* versions. Thanks to Jakub Jelinek for most of the code. */
-# if (defined(LINUX) || defined (__GLIBC__)) /* Are others OK here, too? */ \
+#if (defined(LINUX) || defined (__GLIBC__)) /* Are others OK here, too? */ \
&& (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) \
|| (__GLIBC__ == 2 && __GLIBC_MINOR__ == 2 && defined(DT_CONFIG)))
/* We have the header files for a glibc that includes dl_iterate_phdr. */
/* It may still not be available in the library on the target system. */
/* Thus we also treat it as a weak symbol. */
-#define HAVE_DL_ITERATE_PHDR
-#pragma weak dl_iterate_phdr
+# define HAVE_DL_ITERATE_PHDR
+# pragma weak dl_iterate_phdr
#endif
-# if (defined(FREEBSD) && __FreeBSD__ >= 7)
-/* On the FreeBSD system, any target system at major version 7 shall */
-/* have dl_iterate_phdr; therefore, we need not make it weak as above. */
-#define HAVE_DL_ITERATE_PHDR
-#define DL_ITERATE_PHDR_STRONG
+#if (defined(FREEBSD) && __FreeBSD__ >= 7)
+ /* On the FreeBSD system, any target system at major version 7 shall */
+ /* have dl_iterate_phdr; therefore, we need not make it weak as above. */
+# define HAVE_DL_ITERATE_PHDR
+# define DL_ITERATE_PHDR_STRONG
#endif
#if defined(HAVE_DL_ITERATE_PHDR)
# ifdef PT_GNU_RELRO
-
/* Instead of registering PT_LOAD sections directly, we keep them */
/* in a temporary list, and filter them by excluding PT_GNU_RELRO */
/* segments. Processing PT_GNU_RELRO sections with */
/* it runs into trouble if a client registers an overlapping segment, */
/* which unfortunately seems quite possible. */
-#define MAX_LOAD_SEGS MAX_ROOT_SETS
+# define MAX_LOAD_SEGS MAX_ROOT_SETS
-static struct load_segment {
- ptr_t start;
- ptr_t end;
- /* Room for a second segment if we remove a RELRO segment */
- /* from the middle. */
- ptr_t start2;
- ptr_t end2;
-} load_segs[MAX_LOAD_SEGS];
-
-static int n_load_segs;
+ static struct load_segment {
+ ptr_t start;
+ ptr_t end;
+ /* Room for a second segment if we remove a RELRO segment */
+ /* from the middle. */
+ ptr_t start2;
+ ptr_t end2;
+ } load_segs[MAX_LOAD_SEGS];
+ static int n_load_segs;
# endif /* PT_GNU_RELRO */
STATIC int GC_register_dynlib_callback(struct dl_phdr_info * info,
}
# endif
} else {
+ char *datastart;
+ char *dataend;
+# ifdef DATASTART_IS_FUNC
+ static ptr_t datastart_cached = (ptr_t)(word)-1;
+
+ /* Evaluate DATASTART only once. */
+ if (datastart_cached == (ptr_t)(word)-1) {
+ datastart_cached = (ptr_t)(DATASTART);
+ }
+ datastart = (char *)datastart_cached;
+# else
+ datastart = DATASTART;
+# endif
+# ifdef DATAEND_IS_FUNC
+ {
+ static ptr_t dataend_cached = 0;
+ /* Evaluate DATAEND only once. */
+ if (dataend_cached == 0) {
+ dataend_cached = (ptr_t)(DATAEND);
+ }
+ dataend = (char *)dataend_cached;
+ }
+# else
+ dataend = DATAEND;
+# endif
+
/* dl_iterate_phdr may forget the static data segment in */
/* statically linked executables. */
- GC_add_roots_inner(DATASTART, (char *)(DATAEND), TRUE);
+ GC_add_roots_inner(datastart, dataend, TRUE);
# if defined(DATASTART2)
GC_add_roots_inner(DATASTART2, (char *)(DATAEND2), TRUE);
# endif
return TRUE;
}
-#define HAVE_REGISTER_MAIN_STATIC_DATA
+# define HAVE_REGISTER_MAIN_STATIC_DATA
-# else /* !LINUX || version(glibc) < 2.2.4 */
+#else /* !HAVE_DL_ITERATE_PHDR */
/* Dynamic loading code for Linux running ELF. Somewhat tested on
* Linux/x86, untested but hopefully should work on Linux/Alpha.
/* This doesn't necessarily work in all cases, e.g. with preloaded
* dynamic libraries. */
-#if defined(NETBSD) || defined(OPENBSD)
-# include <sys/exec_elf.h>
-/* for compatibility with 1.4.x */
-# ifndef DT_DEBUG
-# define DT_DEBUG 21
-# endif
-# ifndef PT_LOAD
-# define PT_LOAD 1
-# endif
-# ifndef PF_W
-# define PF_W 2
-# endif
-#elif !defined(PLATFORM_ANDROID)
+# if defined(NETBSD) || defined(OPENBSD)
+# include <sys/exec_elf.h>
+ /* for compatibility with 1.4.x */
+# ifndef DT_DEBUG
+# define DT_DEBUG 21
+# endif
+# ifndef PT_LOAD
+# define PT_LOAD 1
+# endif
+# ifndef PF_W
+# define PF_W 2
+# endif
+# elif !defined(PLATFORM_ANDROID)
# include <elf.h>
-#endif
-
-#ifndef PLATFORM_ANDROID
-# include <link.h>
-#endif
+# endif
+# ifndef PLATFORM_ANDROID
+# include <link.h>
# endif
+#endif /* !HAVE_DL_ITERATE_PHDR */
+
#ifdef __GNUC__
# pragma weak _DYNAMIC
#endif
{
static GC_bool initialized = FALSE;
- if(initialized) return;
+ if (initialized) return;
-# ifdef DARWIN_DEBUG
- GC_printf("Registering dyld callbacks...\n");
-# endif
+# ifdef DARWIN_DEBUG
+ GC_printf("Registering dyld callbacks...\n");
+# endif
/* Apple's Documentation:
When you call _dyld_register_func_for_add_image, the dynamic linker
linked in the future.
*/
- _dyld_register_func_for_add_image(GC_dyld_image_add);
- _dyld_register_func_for_remove_image(GC_dyld_image_remove);
- /* Ignore 2 compiler warnings here: passing argument 1 of */
- /* '_dyld_register_func_for_add/remove_image' from incompatible */
- /* pointer type. */
+ _dyld_register_func_for_add_image(GC_dyld_image_add);
+ _dyld_register_func_for_remove_image(GC_dyld_image_remove);
+ /* Ignore 2 compiler warnings here: passing argument 1 of */
+ /* '_dyld_register_func_for_add/remove_image' from incompatible */
+ /* pointer type. */
+ /* Set this early to avoid reentrancy issues. */
+ initialized = TRUE;
- /* Set this early to avoid reentrancy issues. */
- initialized = TRUE;
-
+# ifdef NO_DYLD_BIND_FULLY_IMAGE
+ /* FIXME: What should we do in this case? */
+# else
+ /* When the environment variable is set, the dynamic linker binds */
+ /* all undefined symbols the application needs at launch time. */
+ /* This includes function symbols that are normally bound lazily at */
+ /* the time of their first invocation. */
if (GETENV("DYLD_BIND_AT_LAUNCH") == 0) {
+ /* The environment variable is unset, so we should bind manually. */
# ifdef DARWIN_DEBUG
GC_printf("Forcing full bind of GC code...\n");
# endif
/* FIXME: '_dyld_bind_fully_image_containing_address' is deprecated. */
- if(!_dyld_bind_fully_image_containing_address((unsigned long*)GC_malloc))
- ABORT("_dyld_bind_fully_image_containing_address failed");
+ if (!_dyld_bind_fully_image_containing_address(
+ (unsigned long *)GC_malloc))
+ ABORT("_dyld_bind_fully_image_containing_address failed");
}
-
+# endif
}
#define HAVE_REGISTER_MAIN_STATIC_DATA
GC_INNER void GC_register_dynamic_libraries(void)
{
/* Add new static data areas of dynamically loaded modules. */
- {
- PCR_IL_LoadedFile * p = PCR_IL_GetLastLoadedFile();
- PCR_IL_LoadedSegment * q;
-
- /* Skip uncommitted files */
- while (p != NIL && !(p -> lf_commitPoint)) {
- /* The loading of this file has not yet been committed */
- /* Hence its description could be inconsistent. */
- /* Furthermore, it hasn't yet been run. Hence its data */
- /* segments can't possibly reference heap allocated */
- /* objects. */
- p = p -> lf_prev;
- }
- for (; p != NIL; p = p -> lf_prev) {
- for (q = p -> lf_ls; q != NIL; q = q -> ls_next) {
- if ((q -> ls_flags & PCR_IL_SegFlags_Traced_MASK)
- == PCR_IL_SegFlags_Traced_on) {
- GC_add_roots_inner
- ((char *)(q -> ls_addr),
- (char *)(q -> ls_addr) + q -> ls_bytes,
- TRUE);
- }
- }
- }
+ PCR_IL_LoadedFile * p = PCR_IL_GetLastLoadedFile();
+ PCR_IL_LoadedSegment * q;
+
+ /* Skip uncommitted files */
+ while (p != NIL && !(p -> lf_commitPoint)) {
+ /* The loading of this file has not yet been committed */
+ /* Hence its description could be inconsistent. */
+ /* Furthermore, it hasn't yet been run. Hence its data */
+ /* segments can't possibly reference heap allocated */
+ /* objects. */
+ p = p -> lf_prev;
+ }
+ for (; p != NIL; p = p -> lf_prev) {
+ for (q = p -> lf_ls; q != NIL; q = q -> ls_next) {
+ if ((q -> ls_flags & PCR_IL_SegFlags_Traced_MASK)
+ == PCR_IL_SegFlags_Traced_on) {
+ GC_add_roots_inner
+ ((char *)(q -> ls_addr),
+ (char *)(q -> ls_addr) + q -> ls_bytes,
+ TRUE);
}
+ }
+ }
}
-
#endif /* PCR && !DYNAMIC_LOADING && !MSWIN32 */
#if !defined(HAVE_REGISTER_MAIN_STATIC_DATA) && defined(DYNAMIC_LOADING)
# define OS_TYPE "OPENBSD"
# define HEURISTIC2
# ifdef __ELF__
+ extern ptr_t GC_data_start;
# define DATASTART GC_data_start
# define DYNAMIC_LOADING
# else
# define OS_TYPE "NETBSD"
# define HEURISTIC2
# ifdef __ELF__
+ extern ptr_t GC_data_start;
# define DATASTART GC_data_start
# define DYNAMIC_LOADING
# else
# ifdef NEXT
# define OS_TYPE "NEXT"
# define DATASTART ((ptr_t) get_etext())
+# define DATASTART_IS_FUNC
# define STACKBOTTOM ((ptr_t) 0x4000000)
# define DATAEND /* not needed */
# endif
/* XXX: see get_end(3), get_etext() and get_end() should not be used.
These aren't used when dyld support is enabled (it is by default) */
# define DATASTART ((ptr_t) get_etext())
-# define DATAEND ((ptr_t) get_end())
+# define DATAEND ((ptr_t) get_end())
# ifndef USE_MMAP
# define USE_MMAP
# endif
extern char etext[];
ptr_t GC_FreeBSDGetDataStart(size_t, ptr_t);
# define DATASTART GC_FreeBSDGetDataStart(0x1000, (ptr_t)etext)
+# define DATASTART_IS_FUNC
# endif
# ifdef NETBSD
# define ALIGNMENT 4
# define OS_TYPE "NETBSD"
# define HEURISTIC2
extern char etext[];
+ extern ptr_t GC_data_start;
# define DATASTART GC_data_start
# define DYNAMIC_LOADING
# endif
extern int _end[];
ptr_t GC_SysVGetDataStart(size_t, ptr_t);
# define DATASTART GC_SysVGetDataStart(0x10000, (ptr_t)_etext)
+# define DATASTART_IS_FUNC
# define DATAEND (ptr_t)(_end)
# if !defined(USE_MMAP) && defined(REDIRECT_MALLOC)
# define USE_MMAP
ptr_t GC_SysVGetDataStart(size_t, ptr_t);
extern int etext[];
# define DATASTART GC_SysVGetDataStart(0x10000, (ptr_t)etext)
+# define DATASTART_IS_FUNC
# define MPROTECT_VDB
# define STACKBOTTOM ((ptr_t) 0xdfff0000)
# define DYNAMIC_LOADING
# else
# define DATASTART GC_SysVGetDataStart(0x10000, (ptr_t)_etext)
# endif
+# define DATASTART_IS_FUNC
# define LINUX_STACKBOTTOM
# endif
# ifdef OPENBSD
# define OS_TYPE "NETBSD"
# define HEURISTIC2
# ifdef __ELF__
+ extern ptr_t GC_data_start;
# define DATASTART GC_data_start
# define DYNAMIC_LOADING
# else
extern char end[];
# define NEED_FIND_LIMIT
# define DATASTART ((ptr_t)(&etext))
+ ptr_t GC_find_limit(ptr_t, GC_bool);
# define DATAEND (GC_find_limit (DATASTART, TRUE))
+# define DATAEND_IS_FUNC
# define DATASTART2 ((ptr_t)(&edata))
# define DATAEND2 ((ptr_t)(&end))
# endif
extern int _etext[], _end[];
ptr_t GC_SysVGetDataStart(size_t, ptr_t);
# define DATASTART GC_SysVGetDataStart(0x1000, (ptr_t)_etext)
+# define DATASTART_IS_FUNC
# define DATAEND (ptr_t)(_end)
/* # define STACKBOTTOM ((ptr_t)(_start)) worked through 2.7, */
/* but reportedly breaks under 2.8. It appears that the stack */
extern int _etext, _end;
ptr_t GC_SysVGetDataStart(size_t, ptr_t);
# define DATASTART GC_SysVGetDataStart(0x1000, (ptr_t)(&_etext))
+# define DATASTART_IS_FUNC
# define DATAEND (ptr_t)(&_end)
# define STACK_GROWS_DOWN
# define HEURISTIC2
extern char etext[];
char * GC_FreeBSDGetDataStart(size_t, ptr_t);
# define DATASTART GC_FreeBSDGetDataStart(0x1000, (ptr_t)etext)
+# define DATASTART_IS_FUNC
# endif
# ifdef NETBSD
# define OS_TYPE "NETBSD"
# ifdef NEXT
# define OS_TYPE "NEXT"
# define DATASTART ((ptr_t) get_etext())
+# define DATASTART_IS_FUNC
# define STACKBOTTOM ((ptr_t)0xc0000000)
# define DATAEND /* not needed */
# endif
/* XXX: see get_end(3), get_etext() and get_end() should not be used.
These aren't used when dyld support is enabled (it is by default) */
# define DATASTART ((ptr_t) get_etext())
-# define DATAEND ((ptr_t) get_end())
+# define DATAEND ((ptr_t) get_end())
# define STACKBOTTOM ((ptr_t) 0xc0000000)
# ifndef USE_MMAP
# define USE_MMAP
# define HEURISTIC2
# ifdef __ELF__
extern int etext[];
+ extern ptr_t GC_data_start;
# define DATASTART GC_data_start
# define NEED_FIND_LIMIT
# define DYNAMIC_LOADING
# ifdef NETBSD
# define OS_TYPE "NETBSD"
# define HEURISTIC2
+ extern ptr_t GC_data_start;
# define DATASTART GC_data_start
# define ELFCLASS32 32
# define ELFCLASS64 64
extern char end[];
# define NEED_FIND_LIMIT
# define DATASTART ((ptr_t)(&etext))
+ ptr_t GC_find_limit(ptr_t, GC_bool);
# define DATAEND (GC_find_limit (DATASTART, TRUE))
+# define DATAEND_IS_FUNC
# define DATASTART2 ((ptr_t)(&edata))
# define DATAEND2 ((ptr_t)(&end))
# endif
# define OS_TYPE "DGUX"
ptr_t GC_SysVGetDataStart(size_t, ptr_t);
# define DATASTART GC_SysVGetDataStart(0x10000, (ptr_t)etext)
+# define DATASTART_IS_FUNC
# endif
# define STACKBOTTOM ((char*)0xf0000000) /* determined empirically */
# endif
extern int _end[];
ptr_t GC_SysVGetDataStart(size_t, ptr_t);
# define DATASTART GC_SysVGetDataStart(0x10000, (ptr_t)_etext)
+# define DATASTART_IS_FUNC
# define DATAEND (ptr_t)(_end)
# define HEURISTIC2
# endif
# define OS_TYPE "NETBSD"
# define HEURISTIC2
# ifdef __ELF__
+ extern ptr_t GC_data_start;
# define DATASTART GC_data_start
# define DYNAMIC_LOADING
# else
# ifdef DARWIN
/* iPhone */
# define OS_TYPE "DARWIN"
+# define DYNAMIC_LOADING
# define DATASTART ((ptr_t) get_etext())
-# define DATAEND ((ptr_t) get_end())
+# define DATAEND ((ptr_t) get_end())
# define STACKBOTTOM ((ptr_t) 0x30000000)
# ifndef USE_MMAP
# define USE_MMAP
# endif
# define USE_MMAP_ANON
# define MPROTECT_VDB
+# include <unistd.h>
+# define GETPAGESIZE() getpagesize()
+ /* FIXME: There seems to be some issues with trylock hanging on */
+ /* darwin. This should be looked into some more. */
+# define NO_PTHREAD_TRYLOCK
+# define NO_DYLD_BIND_FULLY_IMAGE
# endif
# ifdef OPENBSD
# define ALIGNMENT 4
# ifdef NETBSD
# define OS_TYPE "NETBSD"
# define HEURISTIC2
+ extern ptr_t GC_data_start;
# define DATASTART GC_data_start
# define DYNAMIC_LOADING
# endif
/* XXX: see get_end(3), get_etext() and get_end() should not be used.
These aren't used when dyld support is enabled (it is by default) */
# define DATASTART ((ptr_t) get_etext())
-# define DATAEND ((ptr_t) get_end())
+# define DATAEND ((ptr_t) get_end())
# define STACKBOTTOM ((ptr_t) 0x7fff5fc00000)
# ifndef USE_MMAP
# define USE_MMAP
extern char etext[];
ptr_t GC_FreeBSDGetDataStart(size_t, ptr_t);
# define DATASTART GC_FreeBSDGetDataStart(0x1000, (ptr_t)etext)
+# define DATASTART_IS_FUNC
# endif
# ifdef NETBSD
# define OS_TYPE "NETBSD"
extern int _etext[], _end[];
ptr_t GC_SysVGetDataStart(size_t, ptr_t);
# define DATASTART GC_SysVGetDataStart(0x1000, (ptr_t)_etext)
+# define DATASTART_IS_FUNC
# define DATAEND (ptr_t)(_end)
/* # define STACKBOTTOM ((ptr_t)(_start)) worked through 2.7, */
/* but reportedly breaks under 2.8. It appears that the stack */