[compiler-rt] r200733 - [sanitizer] Handle TLS sizes for glibc < 2.13; As discussed in http://gcc.gnu.org/PR60038, the hardcoded sizeof(struct thread); patch by Jakub Jelinek
Kostya Serebryany
kcc at google.com
Mon Feb 3 20:09:39 PST 2014
Author: kcc
Date: Mon Feb 3 22:09:38 2014
New Revision: 200733
URL: http://llvm.org/viewvc/llvm-project?rev=200733&view=rev
Log:
[sanitizer] Handle TLS sizes for glibc < 2.13; As discussed in http://gcc.gnu.org/PR60038, the hardcoded sizeof(struct thread); patch by Jakub Jelinek
Modified:
compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc?rev=200733&r1=200732&r2=200733&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc Mon Feb 3 22:09:38 2014
@@ -21,6 +21,7 @@
#include "sanitizer_placement_new.h"
#include "sanitizer_procmaps.h"
#include "sanitizer_stacktrace.h"
+#include "sanitizer_atomic.h"
#include <dlfcn.h>
#include <pthread.h>
@@ -32,6 +33,7 @@
#if !SANITIZER_ANDROID
#include <elf.h>
#include <link.h>
+#include <unistd.h>
#endif
#ifndef SANITIZER_GO
@@ -226,16 +228,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.
@@ -263,7 +290,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;
More information about the llvm-commits
mailing list