diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp @@ -220,11 +220,9 @@ // sizeof(struct pthread) from glibc. static atomic_uintptr_t thread_descriptor_size; -uptr ThreadDescriptorSize() { - uptr val = atomic_load_relaxed(&thread_descriptor_size); - if (val) - return val; -#if defined(__x86_64__) || defined(__i386__) || defined(__arm__) +static uptr ThreadDescriptorSizeFallback() { + uptr val = 0; +# if defined(__x86_64__) || defined(__i386__) || defined(__arm__) int major; int minor; int patch; @@ -285,12 +283,26 @@ #elif defined(__powerpc64__) val = 1776; // from glibc.ppc64le 2.20-8.fc21 #endif + return val; +} + +uptr ThreadDescriptorSize() { + uptr val = atomic_load_relaxed(&thread_descriptor_size); if (val) - atomic_store_relaxed(&thread_descriptor_size, val); + return val; + // _thread_db_sizeof_pthread is a GLIBC_PRIVATE symbol that is + // exported in glibc 2.34 and later. + auto psizeof = + static_cast(dlsym(RTLD_DEFAULT, "_thread_db_sizeof_pthread")); + if (psizeof != nullptr) + val = *psizeof; + if (!val) + val = ThreadDescriptorSizeFallback(); + atomic_store_relaxed(&thread_descriptor_size, val); return val; } -#if defined(__mips__) || defined(__powerpc64__) || SANITIZER_RISCV64 +# if defined(__mips__) || defined(__powerpc64__) || SANITIZER_RISCV64 // TlsPreTcbSize includes size of struct pthread_descr and size of tcb // head structure. It lies before the static tls blocks. static uptr TlsPreTcbSize() {