On March 19, 2018 8:57:22 PM GMT+01:00, Jakub Jelinek <ja...@redhat.com> wrote:
>Hi!
>
>As mentioned in the PR, libsanitizer cheats and attempts to call
>@GLIBC_PRIVATE functions which are reserved to glibc and can change
>anytime.  They have changed on i?86 in particular in glibc 2.27, where
>internal_function attribute has been dropped, so the functions for some
>reason sadly aren't regparm(3) anymore.
>
>This patch changes libsanitizer, so that when built against glibc 2.26
>and
>earlier, it checks at runtime if glibc 2.27+ is used using a symbol
>that has
>been added ~ a month after the internal_function change, and when built
>against glibc 2.27+, it just assumes it will never be regparm(3).
>
>Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

OK. 

Richard. 

>I've submitted it to upstream in https://reviews.llvm.org/D44623 too,
>but
>it might take some time to get it through there.
>
>2018-03-19  Jakub Jelinek  <ja...@redhat.com>
>
>       PR sanitizer/84761
>       * sanitizer_common/sanitizer_linux_libcdep.cc (__GLIBC_PREREQ):
>       Define if not defined.
>       (DL_INTERNAL_FUNCTION): Don't define.
>       (InitTlsSize): For __i386__ if not compiled against glibc 2.27+
>       determine at runtime whether to use regparm(3), stdcall calling
>       convention for older glibcs or normal calling convention for
>       newer glibcs for call to _dl_get_tls_static_info.
>
>---
>libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cc.jj    2017-10-19
>13:20:58.972958379 +0200
>+++ libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cc   2018-03-19
>14:05:56.178952563 +0100
>@@ -147,29 +147,44 @@ bool SanitizerGetThreadName(char *name,
> #endif
> }
> 
>+#ifndef __GLIBC_PREREQ
>+#define __GLIBC_PREREQ(x, y) 0
>+#endif
>+
> #if !SANITIZER_FREEBSD && !SANITIZER_ANDROID && !SANITIZER_GO && \
>     !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");
>+#if defined(__i386__) && !__GLIBC_PREREQ(2, 27)
>+  /* On i?86, _dl_get_tls_static_info used to be internal_function,
>i.e.
>+     __attribute__((regparm(3), stdcall)) before glibc 2.27 and is
>normal
>+     function in 2.27 and later.  */
>+  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);
>
>       Jakub

Reply via email to