diff options
author | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-02-04 07:37:44 +0000 |
---|---|---|
committer | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-02-04 07:37:44 +0000 |
commit | 5fc776946f5178139a6ec015d4f5707d377ff492 (patch) | |
tree | abc2ecabc213c9fd2c3476ae441836c8c49fdb43 /libsanitizer | |
parent | abcb2cab20538431c8089a6849be35d29735907b (diff) | |
download | gcc-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/ChangeLog | 13 | ||||
-rw-r--r-- | libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cc | 45 |
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; |