https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84761

--- Comment #4 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
That won't really work, if you configure against one glibc version and run
against another one, that will still not work properly.
So I think we need something like:
--- libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cc    2017-10-19
13:20:58.972958379 +0200
+++ libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cc    2018-03-19
13:50:41.978147828 +0100
@@ -151,25 +151,35 @@ bool SanitizerGetThreadName(char *name,
     !SANITIZER_NETBSD
 static uptr g_tls_size;

-#ifdef __i386__
-# define DL_INTERNAL_FUNCTION __attribute__((regparm(3), stdcall))
-#else
-# define DL_INTERNAL_FUNCTION
-#endif
-
 void InitTlsSize() {
 // all current supported platforms have 16 bytes stack alignment
   const size_t kStackAlign = 16;
-  typedef void (*get_tls_func)(size_t*, size_t*) DL_INTERNAL_FUNCTION;
-  get_tls_func get_tls;
-  void *get_tls_static_info_ptr = dlsym(RTLD_NEXT, "_dl_get_tls_static_info");
-  CHECK_EQ(sizeof(get_tls), sizeof(get_tls_static_info_ptr));
-  internal_memcpy(&get_tls, &get_tls_static_info_ptr,
-                  sizeof(get_tls_static_info_ptr));
-  CHECK_NE(get_tls, 0);
   size_t tls_size = 0;
   size_t tls_align = 0;
-  get_tls(&tls_size, &tls_align);
+  void *get_tls_static_info_ptr = dlsym(RTLD_NEXT, "_dl_get_tls_static_info");
+#ifdef __i386__
+  /* On i?86, _dl_get_tls_static_info used to be regparm(3) before glibc 2.27
+     and is now a normal function.  */
+  if (!dlvsym(RTLD_NEXT, "glob", "GLIBC_2.27")) {
+    typedef void (*get_tls_func)(size_t*, size_t*)
+      __attribute__((regparm(3), stdcall));
+    get_tls_func get_tls;
+    CHECK_EQ(sizeof(get_tls), sizeof(get_tls_static_info_ptr));
+    internal_memcpy(&get_tls, &get_tls_static_info_ptr,
+                    sizeof(get_tls_static_info_ptr));
+    CHECK_NE(get_tls, 0);
+    get_tls(&tls_size, &tls_align);
+  } else
+#endif
+  {
+    typedef void (*get_tls_func)(size_t*, size_t*);
+    get_tls_func get_tls;
+    CHECK_EQ(sizeof(get_tls), sizeof(get_tls_static_info_ptr));
+    internal_memcpy(&get_tls, &get_tls_static_info_ptr,
+                    sizeof(get_tls_static_info_ptr));
+    CHECK_NE(get_tls, 0);
+    get_tls(&tls_size, &tls_align);
+  }
   if (tls_align < kStackAlign)
     tls_align = kStackAlign;
   g_tls_size = RoundUpTo(tls_size, tls_align);

instead.  If we only support using the glibc with which gcc has been configured
or later, perhaps that dlvsym call could be avoided if __GLIBC_PREREQ(2, 27).

Reply via email to