This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Handle older glibc versions in ThreadDescriptorSize (PR sanitizer/60038)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Konstantin Serebryany <konstantin dot s dot serebryany at gmail dot com>
- Date: Tue, 4 Feb 2014 08:42:01 +0100
- Subject: [PATCH] Handle older glibc versions in ThreadDescriptorSize (PR sanitizer/60038)
- Authentication-results: sourceware.org; auth=none
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
As discussed in the PR, this patch hardcodes more sizeof (thread)
sizes for various glibc versions and checks at runtime which one to use.
While I don't like the hardcoding at all and Kostya is asking for some glibc
API to query it, having hardcoded values that are just wrong is worse than
this. The patch has been committed today to compiler-rt SVN, this is just a
backport of it, committed to trunk.
2014-02-04 Jakub Jelinek <jakub@redhat.com>
PR sanitizer/60038
* sanitizer_common/sanitizer_linux_libcdep.cc: Include
sanitizer_atomic.h and unistd.h.
(kThreadDescriptorSize): Made static, remove initializer and const,
change type to atomic_uintptr_t.
(ThreadDescriptorSize): Use confstr(_CS_GNU_LIBC_VERSION, ...) to
query glibc version, compute kThreadDescriptorSize depending on
glibc version minor number.
(GetThreadStackAndTls): Use ThreadDescriptorSize() instead of
kThreadDescriptorSize directly.
--- libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cc 2014/02/04 01:28:36 200732
+++ libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cc 2014/02/04 04:09:38 200733
@@ -19,6 +19,7 @@
#include "sanitizer_placement_new.h"
#include "sanitizer_procmaps.h"
#include "sanitizer_stacktrace.h"
+#include "sanitizer_atomic.h"
#include <dlfcn.h>
#include <pthread.h>
@@ -29,6 +30,7 @@
#if !SANITIZER_ANDROID
#include <elf.h>
#include <link.h>
+#include <unistd.h>
#endif
// This function is defined elsewhere if we intercepted pthread_attr_getstack.
@@ -205,16 +207,41 @@ uptr GetTlsSize() {
#if defined(__x86_64__) || defined(__i386__)
// sizeof(struct thread) from glibc.
-// There has been a report of this being different on glibc 2.11 and 2.13. We
-// don't know when this change happened, so 2.14 is a conservative estimate.
-#if __GLIBC_PREREQ(2, 14)
-const uptr kThreadDescriptorSize = FIRST_32_SECOND_64(1216, 2304);
-#else
-const uptr kThreadDescriptorSize = FIRST_32_SECOND_64(1168, 2304);
-#endif
+static atomic_uintptr_t kThreadDescriptorSize;
uptr ThreadDescriptorSize() {
- return kThreadDescriptorSize;
+ char buf[64];
+ uptr val = atomic_load(&kThreadDescriptorSize, memory_order_relaxed);
+ if (val)
+ return val;
+#ifdef _CS_GNU_LIBC_VERSION
+ 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 == '.')) {
+ /* sizeof(struct thread) values from various glibc versions. */
+ 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 <= 12)
+ val = FIRST_32_SECOND_64(1168, 2288);
+ else
+ val = FIRST_32_SECOND_64(1216, 2304);
+ }
+ if (val)
+ atomic_store(&kThreadDescriptorSize, val, memory_order_relaxed);
+ return val;
+ }
+#endif
+ return 0;
}
// The offset at which pointer to self is located in the thread descriptor.
@@ -242,7 +269,7 @@ void GetThreadStackAndTls(bool main, upt
*tls_addr = ThreadSelf();
*tls_size = GetTlsSize();
*tls_addr -= *tls_size;
- *tls_addr += kThreadDescriptorSize;
+ *tls_addr += ThreadDescriptorSize();
#else
*tls_addr = 0;
*tls_size = 0;
Jakub