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 @@ -188,8 +188,8 @@ #endif } -// ThreadDescriptorSize() is only used by lsan to get the pointer to -// thread-specific data keys in the thread control block. +// ThreadDescriptorSize() is only used by lsan to scan thread-specific data keys +// in the thread control block. #if (defined(__x86_64__) || defined(__i386__) || defined(__mips__) || \ defined(__aarch64__) || defined(__powerpc64__) || defined(__s390__) || \ defined(__arm__) || SANITIZER_RISCV64) && \ @@ -201,35 +201,18 @@ uptr val = atomic_load_relaxed(&thread_descriptor_size); if (val) return val; -#if defined(__x86_64__) || defined(__i386__) || defined(__arm__) +#if defined(__i386__) || defined(__x86_64__) || defined(__s390__) + // The size of a prefix of TCB including pthread::{specific_1stblock,specific} + // suffices. Just return offsetof(struct pthread, specific_used), which hasn't + // changed since 2007-05. + return FIRST_32_SECOND_64(524, 1552); +#elif defined(__arm__) int major; int minor; int patch; if (GetLibcVersion(&major, &minor, &patch) && major == 2) { - /* 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 <= 14) - val = FIRST_32_SECOND_64(1168, 2304); - else if (minor < 32) // Unknown version - val = FIRST_32_SECOND_64(1216, 2304); - else // minor == 32 - val = FIRST_32_SECOND_64(1344, 2496); + val = minor <= 22 ? 1120 : 1216; } #elif defined(__mips__) // TODO(sagarthakur): add more values as per different glibc versions. @@ -254,8 +237,6 @@ val = 1776; #elif defined(__powerpc64__) val = 1776; // from glibc.ppc64le 2.20-8.fc21 -#elif defined(__s390__) - val = FIRST_32_SECOND_64(1152, 1776); // valid for glibc 2.22 #endif if (val) atomic_store_relaxed(&thread_descriptor_size, val); diff --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_linux_test.cpp b/compiler-rt/lib/sanitizer_common/tests/sanitizer_linux_test.cpp --- a/compiler-rt/lib/sanitizer_common/tests/sanitizer_linux_test.cpp +++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_linux_test.cpp @@ -187,7 +187,7 @@ EXPECT_EQ(0, getenv(kEnvName)); } -#if (defined(__x86_64__) || defined(__i386__)) && !SANITIZER_ANDROID +#if (defined(__x86_64__) || defined(__i386__)) && SANITIZER_GLIBC // libpthread puts the thread descriptor at the end of stack space. void *thread_descriptor_size_test_func(void *arg) { uptr descr_addr = (uptr)pthread_self(); @@ -204,7 +204,9 @@ void *result; ASSERT_EQ(0, pthread_create(&tid, 0, thread_descriptor_size_test_func, 0)); ASSERT_EQ(0, pthread_join(tid, &result)); - EXPECT_EQ((uptr)result, ThreadDescriptorSize()); + // On x86, ThreadDescriptorSize is the size of a prefix of struct pthread, + // which is smaller than the actual struct pthread size. + EXPECT_GT((uptr)result, ThreadDescriptorSize()); } #endif