From c57fa2338ee2a5ad9da4d08142c33bd958ea9aaa Mon Sep 17 00:00:00 2001 From: ivmai Date: Sat, 12 Feb 2011 15:06:57 +0000 Subject: [PATCH] 2011-02-10 Ivan Maidanski * dyn_load.c (GC_register_map_entries, GC_register_dynamic_libraries_dl_iterate_phdr): Calculate DATASTART only once if DATASTART_IS_FUNC. * dyn_load.c (GC_register_dynamic_libraries_dl_iterate_phdr): Calculate DATAEND only once if DATAEND_IS_FUNC. * dyn_load.c: Add comment to some endif; realign some code. * dyn_load.c (GC_init_dyld): Don't use _dyld_bind_fully_image_containing_address if NO_DYLD_BIND_FULLY_IMAGE defined; add FIXME. * include/private/gcconfig.h (GC_data_start, GC_find_limit): Declare if used by DATASTART/DATAEND, respectively. * include/private/gcconfig.h (DATASTART_IS_FUNC, DATAEND_IS_FUNC): Define if DATASTART/DATAEND is a function, respectively. * include/private/gcconfig.h (GETPAGESIZE, NO_PTHREAD_TRYLOCK, NO_DYLD_BIND_FULLY_IMAGE): Define for Darwin/arm as well; include unistd.h. --- ChangeLog | 19 ++++ dyn_load.c | 208 ++++++++++++++++++++++--------------- include/private/gcconfig.h | 40 ++++++- 3 files changed, 179 insertions(+), 88 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4c243aee..f306a299 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2011-02-10 Ivan Maidanski + + * dyn_load.c (GC_register_map_entries, + GC_register_dynamic_libraries_dl_iterate_phdr): Calculate + DATASTART only once if DATASTART_IS_FUNC. + * dyn_load.c (GC_register_dynamic_libraries_dl_iterate_phdr): + Calculate DATAEND only once if DATAEND_IS_FUNC. + * dyn_load.c: Add comment to some endif; realign some code. + * dyn_load.c (GC_init_dyld): Don't use + _dyld_bind_fully_image_containing_address if + NO_DYLD_BIND_FULLY_IMAGE defined; add FIXME. + * include/private/gcconfig.h (GC_data_start, GC_find_limit): + Declare if used by DATASTART/DATAEND, respectively. + * include/private/gcconfig.h (DATASTART_IS_FUNC, DATAEND_IS_FUNC): + Define if DATASTART/DATAEND is a function, respectively. + * include/private/gcconfig.h (GETPAGESIZE, NO_PTHREAD_TRYLOCK, + NO_DYLD_BIND_FULLY_IMAGE): Define for Darwin/arm as well; include + unistd.h. + 2011-02-10 Ivan Maidanski * os_dep.c (GC_setpagesize, GC_task_self, PROTECT, UNPROTECT): diff --git a/dyn_load.c b/dyn_load.c index 128be6ed..41e89dfc 100644 --- a/dyn_load.c +++ b/dyn_load.c @@ -290,7 +290,19 @@ STATIC word GC_register_map_entries(char *maps) 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); @@ -382,34 +394,32 @@ GC_INNER GC_bool GC_register_main_static_data(void) # 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 */ @@ -417,19 +427,18 @@ GC_INNER GC_bool GC_register_main_static_data(void) /* 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, @@ -564,9 +573,35 @@ STATIC GC_bool GC_register_dynamic_libraries_dl_iterate_phdr(void) } # 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 @@ -574,9 +609,9 @@ STATIC GC_bool GC_register_dynamic_libraries_dl_iterate_phdr(void) 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. @@ -586,28 +621,28 @@ STATIC GC_bool GC_register_dynamic_libraries_dl_iterate_phdr(void) /* This doesn't necessarily work in all cases, e.g. with preloaded * dynamic libraries. */ -#if defined(NETBSD) || defined(OPENBSD) -# include -/* 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 + /* 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 -#endif - -#ifndef PLATFORM_ANDROID -# include -#endif +# endif +# ifndef PLATFORM_ANDROID +# include # endif +#endif /* !HAVE_DL_ITERATE_PHDR */ + #ifdef __GNUC__ # pragma weak _DYNAMIC #endif @@ -1268,11 +1303,11 @@ GC_INNER void GC_init_dyld(void) { 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 @@ -1285,25 +1320,33 @@ GC_INNER void GC_init_dyld(void) 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 @@ -1324,33 +1367,30 @@ GC_INNER GC_bool GC_register_main_static_data(void) 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) diff --git a/include/private/gcconfig.h b/include/private/gcconfig.h index c75b7cee..53feea1d 100644 --- a/include/private/gcconfig.h +++ b/include/private/gcconfig.h @@ -682,6 +682,7 @@ # define OS_TYPE "OPENBSD" # define HEURISTIC2 # ifdef __ELF__ + extern ptr_t GC_data_start; # define DATASTART GC_data_start # define DYNAMIC_LOADING # else @@ -693,6 +694,7 @@ # define OS_TYPE "NETBSD" # define HEURISTIC2 # ifdef __ELF__ + extern ptr_t GC_data_start; # define DATASTART GC_data_start # define DYNAMIC_LOADING # else @@ -751,6 +753,7 @@ # 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 @@ -805,7 +808,7 @@ /* 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 @@ -863,12 +866,14 @@ 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 @@ -963,6 +968,7 @@ 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 @@ -1000,6 +1006,7 @@ 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 @@ -1021,6 +1028,7 @@ # else # define DATASTART GC_SysVGetDataStart(0x10000, (ptr_t)_etext) # endif +# define DATASTART_IS_FUNC # define LINUX_STACKBOTTOM # endif # ifdef OPENBSD @@ -1042,6 +1050,7 @@ # define OS_TYPE "NETBSD" # define HEURISTIC2 # ifdef __ELF__ + extern ptr_t GC_data_start; # define DATASTART GC_data_start # define DYNAMIC_LOADING # else @@ -1062,7 +1071,9 @@ 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 @@ -1098,6 +1109,7 @@ 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 */ @@ -1146,6 +1158,7 @@ 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 @@ -1314,6 +1327,7 @@ 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" @@ -1335,6 +1349,7 @@ # 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 @@ -1372,7 +1387,7 @@ /* 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 @@ -1482,6 +1497,7 @@ # 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 @@ -1600,6 +1616,7 @@ # 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 @@ -1637,7 +1654,9 @@ 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 @@ -1792,6 +1811,7 @@ # 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 @@ -1808,6 +1828,7 @@ 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 @@ -1846,6 +1867,7 @@ # define OS_TYPE "NETBSD" # define HEURISTIC2 # ifdef __ELF__ + extern ptr_t GC_data_start; # define DATASTART GC_data_start # define DYNAMIC_LOADING # else @@ -1890,14 +1912,21 @@ # 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 +# 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 @@ -1955,6 +1984,7 @@ # ifdef NETBSD # define OS_TYPE "NETBSD" # define HEURISTIC2 + extern ptr_t GC_data_start; # define DATASTART GC_data_start # define DYNAMIC_LOADING # endif @@ -2077,7 +2107,7 @@ /* 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 @@ -2111,6 +2141,7 @@ 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" @@ -2127,6 +2158,7 @@ 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 */ -- 2.50.0