# define GC_INIT_CONF_ROOTS GC_add_roots(GC_DATASTART, GC_DATAEND)
#elif (defined(PLATFORM_ANDROID) || defined(__ANDROID__)) \
&& !defined(GC_NOT_DLL)
-# pragma weak __data_start
- extern int __data_start[], _end[];
# pragma weak _etext
+# pragma weak __data_start
# pragma weak __dso_handle
- extern int _etext[], __dso_handle[];
- /* Explicitly register caller static data roots (__data_start points */
- /* to the beginning typically but NDK "gold" linker could provide it */
- /* incorrectly, so the workaround is to check the value and use */
- /* __dso_handle as an alternative data start reference if provided). */
- /* It also works for Android/x86 target where __data_start is not */
- /* defined currently (regardless of linker used). */
+ 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 ? \
- (GC_add_roots(__dso_handle, _end), 0) : \
- (GC_word)__data_start != 0 ? \
- (GC_add_roots(__data_start, _end), 0) : 0)
+ && (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)
#else
# define GC_INIT_CONF_ROOTS /* empty */
#endif
# define DATAEND ((ptr_t)(end))
#endif
+/* Workaround for Android NDK clang 3.5+ (as of NDK r10e) which does */
+/* not provide correct _end symbol. Unfortunately, alternate __end__ */
+/* symbol is provided only by NDK "bfd" linker. */
+#if defined(PLATFORM_ANDROID) && defined(__clang__)
+# undef DATAEND
+# pragma weak __end__
+ extern int __end__[];
+# define DATAEND (__end__ != 0 ? (ptr_t)__end__ : (ptr_t)_end)
+#endif
+
#if defined(PLATFORM_ANDROID) && !defined(THREADS) \
&& !defined(USE_GET_STACKBASE_FOR_MAIN)
/* Always use pthread_attr_getstack on Android ("-lpthread" option is */
extern int _etext[], __dso_handle[];
# endif
# endif /* LINUX */
- extern int _end[];
ptr_t GC_data_start = NULL;
GC_INNER void GC_init_linux_data_start(void)
{
+ ptr_t data_end = DATAEND;
+
# if (defined(LINUX) || defined(HURD)) && !defined(IGNORE_PROG_DATA_START)
/* Try the easy approaches first: */
# ifdef PLATFORM_ANDROID
- /* Workaround for "gold" (default) linker (as of Android NDK r9b). */
+ /* 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);
GC_log_printf(
"__data_start is wrong; using __dso_handle as data start\n");
# endif
- GC_ASSERT((word)GC_data_start <= (word)_end);
+ GC_ASSERT((word)GC_data_start <= (word)data_end);
return;
}
# endif
if ((ptr_t)__data_start != 0) {
GC_data_start = (ptr_t)(__data_start);
- GC_ASSERT((word)GC_data_start <= (word)_end);
+ GC_ASSERT((word)GC_data_start <= (word)data_end);
return;
}
if ((ptr_t)data_start != 0) {
GC_data_start = (ptr_t)(data_start);
- GC_ASSERT((word)GC_data_start <= (word)_end);
+ GC_ASSERT((word)GC_data_start <= (word)data_end);
return;
}
# ifdef DEBUG_ADD_DEL_ROOTS
if (GC_no_dls) {
/* Not needed, avoids the SIGSEGV caused by */
/* GC_find_limit which complicates debugging. */
- GC_data_start = (ptr_t)_end; /* set data root size to 0 */
+ GC_data_start = data_end; /* set data root size to 0 */
return;
}
- GC_data_start = GC_find_limit((ptr_t)(_end), FALSE);
+ GC_data_start = GC_find_limit(data_end, FALSE);
}
#endif /* SEARCH_FOR_DATA_START */