summaryrefslogtreecommitdiff
path: root/libsanitizer
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2014-02-04 07:37:44 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2014-02-04 07:37:44 +0000
commit5fc776946f5178139a6ec015d4f5707d377ff492 (patch)
treeabc2ecabc213c9fd2c3476ae441836c8c49fdb43 /libsanitizer
parentabcb2cab20538431c8089a6849be35d29735907b (diff)
downloadgcc-5fc776946f5178139a6ec015d4f5707d377ff492.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@207452 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libsanitizer')
-rw-r--r--libsanitizer/ChangeLog13
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cc45
2 files changed, 49 insertions, 9 deletions
diff --git a/libsanitizer/ChangeLog b/libsanitizer/ChangeLog
index f4cc57f83f1..94eae5e8b89 100644
--- a/libsanitizer/ChangeLog
+++ b/libsanitizer/ChangeLog
@@ -1,3 +1,16 @@
+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.
+
2014-01-23 Yury Gribov <y.gribov@samsung.com>
Jakub Jelinek <jakub@redhat.com>
diff --git a/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cc b/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cc
index 5b70a69abec..c9eb435be91 100644
--- a/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cc
+++ b/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cc
@@ -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, uptr *stk_addr, uptr *stk_size,
*tls_addr = ThreadSelf();
*tls_size = GetTlsSize();
*tls_addr -= *tls_size;
- *tls_addr += kThreadDescriptorSize;
+ *tls_addr += ThreadDescriptorSize();
#else
*tls_addr = 0;
*tls_size = 0;