From e1ef3b22499d5cf2788219760cb40c6beddb8cba Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Thu, 14 Feb 2019 01:06:26 +0300 Subject: [PATCH] Fix 'wrong __data_start/_end pair' error on Android (fix of commits b746e637b, 5e73ff184, a25965b5f) Issue #259 (bdwgc). * include/gc.h [(HOST_ANDROID || __ANDROID__) && IGNORE_DYNAMIC_LOADING] (_etext, __data_start, __end__, _end): Do not declare weak symbols. * os_dep.c [SEARCH_FOR_DATA_START && (LINUX || HURD) && HOST_ANDROID] (etext, __dso_handle): Likewise. * include/gc.h [(HOST_ANDROID || __ANDROID__) && IGNORE_DYNAMIC_LOADING] (GC_find_limit): Declare function as public. * include/gc.h [(HOST_ANDROID || __ANDROID__) && IGNORE_DYNAMIC_LOADING] (GC_INIT_CONF_ROOTS): Update comment; do not use _etext, __data_start, __end__, _end symbols; use GC_find_limit(__dso_handle,1) as the end of the added GC data root. * include/private/gc_priv.h [SEARCH_FOR_DATA_START || NETBSD && __ELF__] (GC_find_limit): Change ptr_t type to void*, GC_bool to int. * include/private/gcconfig.h [(SPARC || ALPHA) && FREEBSD] (GC_find_limit): Likewise. * os_dep.c [NEED_FIND_LIMIT || USE_PROC_FOR_LIBRARIES] (GC_find_limit): Likewise. * include/private/gcconfig.h [(SPARC || ALPHA) && FREEBSD] (DATAEND): Cast the result to ptr_t. * include/private/gcconfig.h [AARCH64 && LINUX && HOST_ANDROID] (SEARCH_FOR_DATA_START): Remove outdated comment about __data_start. * os_dep.c [SEARCH_FOR_DATA_START && (LINUX || HURD) && !IGNORE_PROG_DATA_START && HOST_ANDROID && !CPPCHECK] (GC_init_linux_data_start): Do not compare __dso_handle to _etext and do not use __dso_handle as data start. * os_dep.c [SEARCH_FOR_DATA_START] (GC_init_linux_data_start): Cast the result of GC_find_limit() to ptr_t. * os_dep.c [NETBSD && __ELF__] (GC_init_netbsd_elf): Likewise. * os_dep.c [LINUX_STACKBOTTOM && IA64] (GC_get_register_stack_base): Likewise. * os_dep.c [!AMIGA && !HAIKU && !OS2 && !MSWIN32 && !MSWINCE && !CYGWIN32 && !GC_OPENBSD_THREADS && (!GC_SOLARIS_THREADS || _STRICT_STDC)] (GC_get_main_stack_base): Likewise. * os_dep.c [DATASTART_USES_BSDGETDATASTART] (GC_FreeBSDGetDataStart): Likewise. --- include/gc.h | 36 +++++++++--------------------------- include/private/gc_priv.h | 4 ++-- include/private/gcconfig.h | 11 ++++------- os_dep.c | 35 ++++++++++------------------------- 4 files changed, 25 insertions(+), 61 deletions(-) diff --git a/include/gc.h b/include/gc.h index 9eff116..df48399 100644 --- a/include/gc.h +++ b/include/gc.h @@ -1917,34 +1917,16 @@ GC_API int GC_CALL GC_get_force_unmap_on_gcollect(void); # define GC_DATAEND ((void *)((ulong)_end)) # define GC_INIT_CONF_ROOTS GC_add_roots(GC_DATASTART, GC_DATAEND) #elif (defined(HOST_ANDROID) || defined(__ANDROID__)) \ - && !defined(GC_NOT_DLL) && defined(IGNORE_DYNAMIC_LOADING) - /* It causes the entire binary section of memory be pushed as a root. */ - /* This might be a bad idea though because on some Android devices */ - /* some of the binary data might become unmapped thus causing SIGSEGV */ - /* with code SEGV_MAPERR. */ -# pragma weak _etext -# pragma weak __data_start + && defined(IGNORE_DYNAMIC_LOADING) + /* This is ugly but seems the only way to register data roots of the */ + /* client shared library if the GC dynamic loading support is off. */ # pragma weak __dso_handle - extern int _etext[], __data_start[], __dso_handle[]; -# pragma weak __end__ - extern int __end__[], _end[]; - /* Explicitly register caller static data roots. Workaround for */ - /* __data_start: NDK "gold" linker might miss it or place it */ - /* incorrectly, __dso_handle is an alternative data start reference. */ - /* Workaround for _end: NDK Clang 3.5+ does not place it at correct */ - /* offset (as of NDK r10e) but "bfd" linker provides __end__ symbol */ - /* that could be used instead. */ -# define GC_INIT_CONF_ROOTS \ - (void)((GC_word)__data_start < (GC_word)_etext \ - && (GC_word)_etext < (GC_word)__dso_handle \ - ? (__end__ != 0 \ - ? (GC_add_roots(__dso_handle, __end__), 0) \ - : (GC_word)__dso_handle < (GC_word)_end \ - ? (GC_add_roots(__dso_handle, _end), 0) : 0) \ - : __data_start != 0 ? (__end__ != 0 \ - ? (GC_add_roots(__data_start, __end__), 0) \ - : (GC_word)__data_start < (GC_word)_end \ - ? (GC_add_roots(__data_start, _end), 0) : 0) : 0) + extern int __dso_handle[]; + GC_API void * GC_CALL GC_find_limit(void * /* start */, int /* up */); +# define GC_INIT_CONF_ROOTS (void)(__dso_handle != 0 \ + ? (GC_add_roots(__dso_handle, \ + GC_find_limit(__dso_handle, \ + 1 /*up*/)), 0) : 0) #else # define GC_INIT_CONF_ROOTS /* empty */ #endif diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h index 94c2cca..c62453f 100644 --- a/include/private/gc_priv.h +++ b/include/private/gc_priv.h @@ -2485,12 +2485,12 @@ GC_INNER void *GC_store_debug_info_inner(void *p, word sz, const char *str, #ifdef SEARCH_FOR_DATA_START GC_INNER void GC_init_linux_data_start(void); - ptr_t GC_find_limit(ptr_t, GC_bool); + void * GC_find_limit(void *, int); #endif #if defined(NETBSD) && defined(__ELF__) GC_INNER void GC_init_netbsd_elf(void); - ptr_t GC_find_limit(ptr_t, GC_bool); + void * GC_find_limit(void *, int); #endif #ifdef UNIX_LIKE diff --git a/include/private/gcconfig.h b/include/private/gcconfig.h index 3923a9a..88dddef 100644 --- a/include/private/gcconfig.h +++ b/include/private/gcconfig.h @@ -1347,8 +1347,8 @@ EXTERN_C_BEGIN # endif # 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) + void * GC_find_limit(void *, int); +# define DATAEND (ptr_t)GC_find_limit(DATASTART, TRUE) # define DATAEND_IS_FUNC # define GC_HAVE_DATAREGION2 # define DATASTART2 ((ptr_t)(&edata)) @@ -2055,8 +2055,8 @@ EXTERN_C_BEGIN # endif # 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) + void * GC_find_limit(void *, int); +# define DATAEND (ptr_t)GC_find_limit(DATASTART, TRUE) # define DATAEND_IS_FUNC # define GC_HAVE_DATAREGION2 # define DATASTART2 ((ptr_t)(&edata)) @@ -2291,9 +2291,6 @@ EXTERN_C_BEGIN # define DYNAMIC_LOADING # if defined(HOST_ANDROID) # define SEARCH_FOR_DATA_START - /* As of NDK r18b, __data_start is not provided */ - /* if "gold" linker is used. But __dso_handle */ - /* symbol should be usable instead. */ # else extern int __data_start[]; # define DATASTART ((ptr_t)__data_start) diff --git a/os_dep.c b/os_dep.c index 4fe414b..01332ed 100644 --- a/os_dep.c +++ b/os_dep.c @@ -420,11 +420,6 @@ GC_INNER char * GC_get_maps(void) # pragma weak __data_start # pragma weak data_start extern int __data_start[], data_start[]; -# ifdef HOST_ANDROID -# pragma weak _etext -# pragma weak __dso_handle - extern int _etext[], __dso_handle[]; -# endif EXTERN_C_END # endif /* LINUX */ @@ -436,18 +431,7 @@ GC_INNER char * GC_get_maps(void) # if (defined(LINUX) || defined(HURD)) && !defined(IGNORE_PROG_DATA_START) /* Try the easy approaches first: */ -# if defined(HOST_ANDROID) && !defined(CPPCHECK) - /* Workaround for "gold" (default) linker (as of Android NDK r10e). */ - if ((word)__data_start < (word)_etext - && (word)_etext < (word)__dso_handle) { - GC_data_start = (ptr_t)(__dso_handle); -# ifdef DEBUG_ADD_DEL_ROOTS - GC_log_printf( - "__data_start is wrong; using __dso_handle as data start\n"); -# endif - } else -# endif - /* else */ if (COVERT_DATAFLOW(__data_start) != 0) { + if (COVERT_DATAFLOW(__data_start) != 0) { GC_data_start = (ptr_t)(__data_start); } else { GC_data_start = (ptr_t)(data_start); @@ -470,7 +454,7 @@ GC_INNER char * GC_get_maps(void) return; } - GC_data_start = GC_find_limit(data_end, FALSE); + GC_data_start = (ptr_t)GC_find_limit(data_end, FALSE); } #endif /* SEARCH_FOR_DATA_START */ @@ -511,7 +495,7 @@ GC_INNER char * GC_get_maps(void) { /* This may need to be environ, without the underscore, for */ /* some versions. */ - GC_data_start = GC_find_limit((ptr_t)&environ, FALSE); + GC_data_start = (ptr_t)GC_find_limit(&environ, FALSE); } #endif /* NETBSD */ @@ -1027,9 +1011,10 @@ GC_INNER size_t GC_page_size = 0; return(result); } - ptr_t GC_find_limit(ptr_t p, GC_bool up) + void * GC_find_limit(void * p, int up) { - return GC_find_limit_with_bound(p, up, up ? (ptr_t)GC_WORD_MAX : 0); + return GC_find_limit_with_bound((ptr_t)p, (GC_bool)up, + up ? (ptr_t)GC_WORD_MAX : 0); } # endif /* NEED_FIND_LIMIT || USE_PROC_FOR_LIBRARIES */ @@ -1092,7 +1077,7 @@ GC_INNER size_t GC_page_size = 0; # endif result = backing_store_base_from_proc(); if (0 == result) { - result = GC_find_limit(GC_save_regs_in_stack(), FALSE); + result = (ptr_t)GC_find_limit(GC_save_regs_in_stack(), FALSE); /* Now seems to work better than constant displacement */ /* heuristic used in 6.X versions. The latter seems to */ /* fail for 2.6 kernels. */ @@ -1280,7 +1265,7 @@ GC_INNER size_t GC_page_size = 0; { ptr_t sp = GC_approx_sp(); # ifdef STACK_GROWS_DOWN - result = GC_find_limit(sp, TRUE); + result = (ptr_t)GC_find_limit(sp, TRUE); # if defined(HEURISTIC2_LIMIT) && !defined(CPPCHECK) if ((word)result > (word)HEURISTIC2_LIMIT && (word)sp < (word)HEURISTIC2_LIMIT) { @@ -1288,7 +1273,7 @@ GC_INNER size_t GC_page_size = 0; } # endif # else - result = GC_find_limit(sp, FALSE); + result = (ptr_t)GC_find_limit(sp, FALSE); # if defined(HEURISTIC2_LIMIT) && !defined(CPPCHECK) if ((word)result < (word)HEURISTIC2_LIMIT && (word)sp > (word)HEURISTIC2_LIMIT) { @@ -1996,7 +1981,7 @@ void GC_register_data_segments(void) } else { GC_reset_fault_handler(); /* As above, we go to plan B */ - result = GC_find_limit(DATAEND, FALSE); + result = (ptr_t)GC_find_limit(DATAEND, FALSE); } return(result); } -- 2.7.4