Fix 'wrong __data_start/_end pair' error on Android
authorIvan Maidanski <ivmai@mail.ru>
Wed, 13 Feb 2019 22:06:26 +0000 (01:06 +0300)
committerIvan Maidanski <ivmai@mail.ru>
Wed, 13 Feb 2019 22:06:26 +0000 (01:06 +0300)
(fix of commits b746e637b5e73ff184a25965b5f)

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
include/private/gc_priv.h
include/private/gcconfig.h
os_dep.c

index 9eff116..df48399 100644 (file)
@@ -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
index 94c2cca..c62453f 100644 (file)
@@ -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
index 3923a9a..88dddef 100644 (file)
@@ -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)
index 4fe414b..01332ed 100644 (file)
--- 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);
   }