Index: lib/sanitizer_common/sanitizer_linux_libcdep.cc =================================================================== --- lib/sanitizer_common/sanitizer_linux_libcdep.cc +++ lib/sanitizer_common/sanitizer_linux_libcdep.cc @@ -74,6 +74,10 @@ #include #endif +#ifdef __GLIBC__ +#include +#endif + namespace __sanitizer { SANITIZER_WEAK_ATTRIBUTE int @@ -157,16 +161,31 @@ } #endif +int GetGlibcVersion(int *patch) { + if (patch) + *patch = 0; +#ifdef __GLIBC__ + const char *version = gnu_get_libc_version(); + if (version[0] == '2' && version[1] == '.') { + char *end; + int minor = internal_simple_strtoll(version + 2, &end, 10); + if (end != version + 2 && (*end == '\0' || *end == '.' || *end == '-')) { + if (*end == '.' && patch) + // strtoll will return 0 if no valid conversion could be performed + *patch = internal_simple_strtoll(end + 1, nullptr, 10); + return minor; + } + } +#endif // __GLIBC__ + return 0; +} + #if !SANITIZER_FREEBSD && !SANITIZER_ANDROID && !SANITIZER_GO && \ !SANITIZER_NETBSD && !SANITIZER_OPENBSD && !SANITIZER_SOLARIS static uptr g_tls_size; #ifdef __i386__ -# ifndef __GLIBC_PREREQ -# define CHECK_GET_TLS_STATIC_INFO_VERSION 1 -# else -# define CHECK_GET_TLS_STATIC_INFO_VERSION (!__GLIBC_PREREQ(2, 27)) -# endif +# define CHECK_GET_TLS_STATIC_INFO_VERSION 1 #else # define CHECK_GET_TLS_STATIC_INFO_VERSION 0 #endif @@ -204,8 +223,7 @@ // 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 (CHECK_GET_TLS_STATIC_INFO_VERSION && - !dlvsym(RTLD_NEXT, "glob", "GLIBC_2.27")) + if (CHECK_GET_TLS_STATIC_INFO_VERSION && GetGlibcVersion(nullptr) < 27) CallGetTls(get_tls_static_info_ptr, &tls_size, &tls_align); else @@ -232,41 +250,32 @@ if (val) return val; #if defined(__x86_64__) || defined(__i386__) || defined(__arm__) -#ifdef _CS_GNU_LIBC_VERSION - char buf[64]; - uptr len = confstr(_CS_GNU_LIBC_VERSION, buf, sizeof(buf)); - if (len < sizeof(buf) && internal_strncmp(buf, "glibc 2.", 8) == 0) { - char *end; - int minor = internal_simple_strtoll(buf + 8, &end, 10); - if (end != buf + 8 && (*end == '\0' || *end == '.' || *end == '-')) { - int patch = 0; - if (*end == '.') - // strtoll will return 0 if no valid conversion could be performed - patch = internal_simple_strtoll(end + 1, nullptr, 10); - - /* sizeof(struct pthread) values from various glibc versions. */ - if (SANITIZER_X32) - val = 1728; // Assume only one particular version for x32. - // For ARM sizeof(struct pthread) changed in Glibc 2.23. - else if (SANITIZER_ARM) - val = minor <= 22 ? 1120 : 1216; - else if (minor <= 3) - val = FIRST_32_SECOND_64(1104, 1696); - else if (minor == 4) - val = FIRST_32_SECOND_64(1120, 1728); - else if (minor == 5) - val = FIRST_32_SECOND_64(1136, 1728); - else if (minor <= 9) - val = FIRST_32_SECOND_64(1136, 1712); - else if (minor == 10) - val = FIRST_32_SECOND_64(1168, 1776); - else if (minor == 11 || (minor == 12 && patch == 1)) - val = FIRST_32_SECOND_64(1168, 2288); - else if (minor <= 13) - val = FIRST_32_SECOND_64(1168, 2304); - else - val = FIRST_32_SECOND_64(1216, 2304); - } +#ifdef __GLIBC__ + int patch = 0; + int minor = GetGlibcVersion(&patch); + if (minor) { + /* sizeof(struct pthread) values from various glibc versions. */ + if (SANITIZER_X32) + val = 1728; // Assume only one particular version for x32. + // For ARM sizeof(struct pthread) changed in Glibc 2.23. + else if (SANITIZER_ARM) + val = minor <= 22 ? 1120 : 1216; + else if (minor <= 3) + val = FIRST_32_SECOND_64(1104, 1696); + else if (minor == 4) + val = FIRST_32_SECOND_64(1120, 1728); + else if (minor == 5) + val = FIRST_32_SECOND_64(1136, 1728); + else if (minor <= 9) + val = FIRST_32_SECOND_64(1136, 1712); + else if (minor == 10) + val = FIRST_32_SECOND_64(1168, 1776); + else if (minor == 11 || (minor == 12 && patch == 1)) + val = FIRST_32_SECOND_64(1168, 2288); + else if (minor <= 13) + val = FIRST_32_SECOND_64(1168, 2304); + else + val = FIRST_32_SECOND_64(1216, 2304); } #endif #elif defined(__mips__)