This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Handle older glibc versions in ThreadDescriptorSize (PR sanitizer/60038)


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]