diff mbox

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

Message ID 20140204074201.GB12671@tucnak.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Feb. 4, 2014, 7:42 a.m. UTC
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.


	Jakub
diff mbox

Patch

--- 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;