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